1use crate::concept_id::ConceptIdError;
4use crate::yaml::YamlError;
5use std::fmt;
6
7#[derive(Clone, Debug, PartialEq, Eq)]
9#[non_exhaustive]
10pub enum DocumentError {
11 UnterminatedFrontmatter,
13 FrontmatterNotMapping,
15 InvalidYaml(YamlError),
17 MissingKeys(Vec<String>),
19 InvalidConceptId(ConceptIdError),
21}
22
23impl fmt::Display for DocumentError {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 match self {
26 Self::UnterminatedFrontmatter => {
27 write!(f, "Unterminated YAML frontmatter block")
28 }
29 Self::FrontmatterNotMapping => {
30 write!(f, "Frontmatter must be a YAML mapping")
31 }
32 Self::InvalidYaml(e) => write!(f, "Invalid YAML in frontmatter: {e}"),
33 Self::MissingKeys(keys) => {
34 write!(f, "Missing required frontmatter keys: {}", keys.join(", "))
35 }
36 Self::InvalidConceptId(e) => write!(f, "Invalid concept id: {e}"),
37 }
38 }
39}
40
41impl std::error::Error for DocumentError {
42 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
43 match self {
44 Self::InvalidYaml(e) => Some(e),
45 Self::InvalidConceptId(e) => Some(e),
46 _ => None,
47 }
48 }
49}
50
51impl From<YamlError> for DocumentError {
52 fn from(e: YamlError) -> Self {
53 Self::InvalidYaml(e)
54 }
55}
56
57impl From<ConceptIdError> for DocumentError {
58 fn from(e: ConceptIdError) -> Self {
59 Self::InvalidConceptId(e)
60 }
61}
62
63#[derive(Clone, Debug)]
65#[non_exhaustive]
66pub enum BundleError {
67 Io {
74 kind: std::io::ErrorKind,
76 message: String,
79 },
80 NotADirectory(std::path::PathBuf),
82 Document {
84 path: std::path::PathBuf,
86 error: DocumentError,
88 },
89}
90
91impl BundleError {
92 #[must_use]
96 pub const fn io_kind(&self) -> Option<std::io::ErrorKind> {
97 match self {
98 Self::Io { kind, .. } => Some(*kind),
99 _ => None,
100 }
101 }
102}
103
104impl fmt::Display for BundleError {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 match self {
107 Self::Io { message, .. } => write!(f, "I/O error: {message}"),
108 Self::NotADirectory(p) => {
109 write!(f, "bundle root is not a directory: {}", p.display())
110 }
111 Self::Document { path, error } => {
112 write!(f, "{}: {error}", path.display())
113 }
114 }
115 }
116}
117
118impl std::error::Error for BundleError {
119 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
120 match self {
121 Self::Document { error, .. } => Some(error),
122 _ => None,
123 }
124 }
125}
126
127impl From<std::io::Error> for BundleError {
128 fn from(e: std::io::Error) -> Self {
129 Self::Io {
130 kind: e.kind(),
131 message: e.to_string(),
132 }
133 }
134}