Skip to main content

hpr_io/ork/
warning.rs

1//! What a reader accepted but wants to say out loud.
2
3use serde::{Deserialize, Serialize};
4
5/// Something the reader accepted and flagged, rather than failing over.
6///
7/// The roadmap asks the `.ork` importer for "graceful warnings instead of failures": a real design
8/// written by an older OpenRocket, or by another program, should still open. Every departure from
9/// what the file format documents is reported here, with the place in the file it happened.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11pub struct Warning {
12    /// Where it happened: a zip entry name, or a slash-separated path of element names from the
13    /// root, such as `openrocket/rocket/subcomponents/nosecone`.
14    pub at: String,
15    /// Whether anything was lost.
16    pub kind: WarningKind,
17    /// What was read, and how.
18    pub message: String,
19}
20
21/// How serious a [`Warning`] is.
22///
23/// The same three levels `hpr_motor::WarningKind` uses for `.eng` and `.rse` files. The two enums
24/// are kept apart because their readers report different places (a line number there, a path into
25/// an archive or an element tree here) and because `hpr-io` does not otherwise need `hpr-motor`.
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
27#[serde(rename_all = "snake_case")]
28#[non_exhaustive]
29pub enum WarningKind {
30    /// A whole part of the file was left out of the result, such as an archive entry compressed
31    /// by a method this reader does not implement.
32    Skipped,
33    /// A value was dropped or ignored.
34    Dropped,
35    /// Something unusual was read as it stands, such as a schema version newer than any documented.
36    Unusual,
37}
38
39impl Warning {
40    /// Records a warning at `at`.
41    pub(crate) fn new(
42        at: impl Into<String>,
43        kind: WarningKind,
44        message: impl Into<String>,
45    ) -> Self {
46        Self {
47            at: at.into(),
48            kind,
49            message: message.into(),
50        }
51    }
52}
53
54/// A value read from a `.ork` file and the warnings its reader raised, in the order they arose.
55#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
56pub struct Imported<T> {
57    /// The value read.
58    pub value: T,
59    /// The warnings, in file order.
60    pub warnings: Vec<Warning>,
61}
62
63impl<T> Imported<T> {
64    /// Wraps a value with no warnings.
65    pub(crate) fn clean(value: T) -> Self {
66        Self {
67            value,
68            warnings: Vec::new(),
69        }
70    }
71
72    /// Counts the warnings of one kind.
73    pub fn count(&self, kind: WarningKind) -> usize {
74        self.warnings.iter().filter(|w| w.kind == kind).count()
75    }
76}