Skip to main content

ephemeris_documents/
error.rs

1//! Error types of the crate.
2
3mod annotation;
4mod columns;
5mod internal;
6mod json;
7mod line_ending;
8mod markdown;
9mod merge;
10mod ownership;
11mod text;
12mod toml;
13mod value;
14mod yaml;
15
16use std::str::Utf8Error;
17
18pub use self::annotation::{AnnotationError, MarkerField};
19pub use self::columns::ColumnsError;
20pub use self::internal::InternalError;
21pub use self::json::{JsonError, JsonErrorKind};
22pub use self::line_ending::LineEndingError;
23pub use self::markdown::MarkdownError;
24pub use self::merge::MergeError;
25pub use self::ownership::{OwnershipError, PathSyntaxError};
26pub use self::text::TextError;
27pub use self::toml::TomlError;
28pub use self::value::{Feature, ValueError};
29pub use self::yaml::YamlError;
30use crate::path::{KeyPath, Segment};
31
32/// Error returned by document validation, rendering, and reconciliation.
33#[derive(Debug, thiserror::Error)]
34pub enum DocumentError {
35    /// A document's bytes are not valid UTF-8.
36    #[error("invalid UTF-8")]
37    Utf8 {
38        /// The underlying UTF-8 decoding error.
39        #[from]
40        source: Utf8Error,
41    },
42    /// A plain text document's comment nodes could not be rendered.
43    #[error(transparent)]
44    Text(#[from] TextError),
45    /// A generic structured value could not be shaped for its format.
46    #[error("at `{path}`")]
47    Value {
48        /// Where in the value the problem is.
49        path: KeyPath,
50        /// What is wrong with the value.
51        #[source]
52        source: ValueError,
53    },
54    /// An inline annotation marker is malformed.
55    #[error("at `{path}`")]
56    Annotation {
57        /// Where in the value the marker is.
58        path: KeyPath,
59        /// What is wrong with the marker.
60        #[source]
61        source: AnnotationError,
62    },
63    /// A column count is invalid.
64    #[error(transparent)]
65    Columns(#[from] ColumnsError),
66    /// An ownership declaration is invalid.
67    #[error(transparent)]
68    Ownership(#[from] OwnershipError),
69    /// A document's line endings are inconsistent.
70    #[error(transparent)]
71    LineEnding(#[from] LineEndingError),
72    /// A desired document cannot be merged into the current one.
73    #[error(transparent)]
74    Merge(#[from] MergeError),
75    /// A JSON or JSON5 document is malformed.
76    #[error(transparent)]
77    Json(#[from] JsonError),
78    /// A Markdown document or selector is malformed.
79    #[error(transparent)]
80    Markdown(#[from] MarkdownError),
81    /// A TOML document or selector is malformed.
82    #[error(transparent)]
83    Toml(#[from] TomlError),
84    /// A YAML document is malformed.
85    #[error(transparent)]
86    Yaml(#[from] YamlError),
87    /// A bug in this crate, not a problem with the input.
88    #[error(transparent)]
89    Internal(#[from] InternalError),
90}
91
92impl DocumentError {
93    pub(crate) const fn value(source: ValueError) -> Self {
94        Self::Value {
95            path: KeyPath::root(),
96            source,
97        }
98    }
99
100    /// The value at `path` is not a string.
101    pub(crate) fn not_string(path: &[String]) -> Self {
102        Self::Value {
103            path: KeyPath::from(path),
104            source: ValueError::NotString,
105        }
106    }
107
108    pub(crate) fn yaml_parse(source: yaml_rt::YamlError) -> Self {
109        Self::Yaml(YamlError::Parse {
110            source: Box::new(source),
111        })
112    }
113
114    pub(crate) const fn annotation(source: AnnotationError) -> Self {
115        Self::Annotation {
116            path: KeyPath::root(),
117            source,
118        }
119    }
120
121    /// Prefix the key path of a value, annotation or duplicate key error with
122    /// `segment`. Every other error is returned unchanged.
123    #[must_use]
124    pub(crate) fn under(self, segment: Segment) -> Self {
125        match self {
126            Self::Value { path, source } => Self::Value {
127                path: path.under(segment),
128                source,
129            },
130            Self::Annotation { path, source } => Self::Annotation {
131                path: path.under(segment),
132                source,
133            },
134            Self::Yaml(YamlError::DuplicateKey { path, key }) => {
135                Self::Yaml(YamlError::DuplicateKey {
136                    path: path.under(segment),
137                    key,
138                })
139            }
140            Self::Utf8 { source: _ }
141            | Self::Text(_)
142            | Self::Columns(_)
143            | Self::Ownership(_)
144            | Self::LineEnding(_)
145            | Self::Merge(_)
146            | Self::Json(_)
147            | Self::Markdown(_)
148            | Self::Toml(_)
149            | Self::Yaml(
150                YamlError::Parse { source: _ }
151                | YamlError::MultipleDocuments { count: _ }
152                | YamlError::UnsupportedLayout { path: _ },
153            )
154            | Self::Internal(_) => self,
155        }
156    }
157}