1use knowledge_base_snapshot::Error as SnapshotError;
2use knowledge_base_validation::Diagnostic;
3use std::fmt;
4use std::io;
5use std::path::PathBuf;
6
7#[derive(Debug)]
8#[non_exhaustive]
9pub enum RepositoryError {
10 Read { path: PathBuf, source: io::Error },
11 ParseStatementBatch { path: PathBuf, source: serde_yaml::Error },
12 ParseReference { path: PathBuf, source: serde_yaml::Error },
13 ParseAllocation { path: PathBuf, source: serde_yaml::Error },
14 ParseEntityType { path: PathBuf, source: serde_yaml::Error },
15 ParseProperty { path: PathBuf, source: serde_yaml::Error },
16 InvalidRequest(String),
17 ParseEntity { path: PathBuf, source: serde_yaml::Error },
18 Snapshot(SnapshotError),
19 InvalidRepository(String),
20 InvalidSnapshot { path: PathBuf, message: String },
21 Edit { path: PathBuf, message: String },
22 Validation(Vec<Diagnostic>),
23 Write { path: PathBuf, source: io::Error },
24 ConcurrentChange(PathBuf),
25 Commit { message: String },
26}
27
28impl fmt::Display for RepositoryError {
29 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
30 match self {
31 Self::Read { path, source } => write!(formatter, "cannot read {}: {source}", path.display()),
32 Self::ParseStatementBatch { path, source } => {
33 write!(formatter, "cannot parse statement manifest {}: {source}", path.display())
34 }
35 Self::ParseReference { path, source } => write!(formatter, "cannot parse reference {}: {source}", path.display()),
36 Self::ParseAllocation { path, source } => write!(formatter, "cannot parse identifier allocation {}: {source}", path.display()),
37 Self::ParseEntityType { path, source } => write!(formatter, "cannot parse entity type {}: {source}", path.display()),
38 Self::ParseProperty { path, source } => write!(formatter, "cannot parse property {}: {source}", path.display()),
39 Self::InvalidRequest(message) => write!(formatter, "invalid mutation request: {message}"),
40 Self::ParseEntity { path, source } => {
41 write!(formatter, "cannot parse entity {}: {source}", path.display())
42 }
43 Self::InvalidRepository(message) => write!(formatter, "cannot query knowledge base: {message}"),
44 Self::Snapshot(source) => source.fmt(formatter),
45 Self::InvalidSnapshot { path, message } => write!(formatter, "cannot load repository snapshot at {}: {message}", path.display()),
46 Self::Edit { path, message } => {
47 write!(formatter, "cannot edit resource {}: {message}", path.display())
48 }
49 Self::Validation(diagnostics) => {
50 writeln!(formatter, "mutation would not produce a valid knowledge base:")?;
51 for (index, diagnostic) in diagnostics.iter().enumerate() {
52 if index + 1 == diagnostics.len() {
53 write!(formatter, "{diagnostic}")?;
54 } else {
55 writeln!(formatter, "{diagnostic}")?;
56 }
57 }
58 Ok(())
59 }
60 Self::Write { path, source } => {
61 write!(formatter, "cannot write {}: {source}", path.display())
62 }
63 Self::ConcurrentChange(path) => {
64 write!(formatter, "resource changed while applying mutation: {}", path.display())
65 }
66 Self::Commit { message } => formatter.write_str(message),
67 }
68 }
69}
70
71impl std::error::Error for RepositoryError {
72 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
73 match self {
74 Self::Read { source, .. } | Self::Write { source, .. } => Some(source),
75 Self::ParseStatementBatch { source, .. }
76 | Self::ParseReference { source, .. }
77 | Self::ParseAllocation { source, .. }
78 | Self::ParseEntityType { source, .. }
79 | Self::ParseProperty { source, .. }
80 | Self::ParseEntity { source, .. } => Some(source),
81 Self::Snapshot(source) => Some(source),
82 Self::InvalidRequest(_)
83 | Self::InvalidRepository(_)
84 | Self::InvalidSnapshot { .. }
85 | Self::Edit { .. }
86 | Self::Validation(_)
87 | Self::ConcurrentChange(_)
88 | Self::Commit { .. } => None,
89 }
90 }
91}