agent_first_data/document/
error.rs1use std::fmt;
4use std::io;
5
6pub type DocumentResult<T> = Result<T, DocumentError>;
7
8#[derive(Debug, Clone)]
9pub enum DocumentError {
10 EmptyPath,
11 EmptyValues,
12 UnknownSegment {
13 path: String,
14 segment: String,
15 },
16 UnregisteredArray {
17 path: String,
18 },
19 SlugNotFound {
20 prefix: String,
21 slug: String,
22 },
23 SlugAlreadyExists {
24 prefix: String,
25 slug: String,
26 },
27 NotTraversable {
28 path: String,
29 got: String,
30 },
31 TypeMismatch {
32 path: String,
33 expected: String,
34 got: String,
35 hint: Option<String>,
36 },
37 PathNotFound {
38 path: String,
39 },
40 IndexOutOfBounds {
41 path: String,
42 index: usize,
43 len: usize,
44 },
45 ParseError {
46 format: String,
47 detail: String,
48 },
49 IoError {
50 detail: String,
51 },
52 UnsupportedOperation {
53 format: String,
54 operation: String,
55 detail: String,
56 },
57}
58
59impl fmt::Display for DocumentError {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 match self {
62 DocumentError::EmptyPath => {
63 write!(f, "empty path provided")
64 }
65 DocumentError::EmptyValues => {
66 write!(f, "at least one value required")
67 }
68 DocumentError::UnknownSegment { path, segment } => {
69 write!(f, "path `{}` segment `{}` not found", path, segment)
70 }
71 DocumentError::UnregisteredArray { path } => {
72 write!(f, "array at `{}` not registered in KeyedList", path)
73 }
74 DocumentError::SlugNotFound { prefix, slug } => {
75 write!(f, "no element with slug `{}` found in `{}`", slug, prefix)
76 }
77 DocumentError::SlugAlreadyExists { prefix, slug } => {
78 write!(f, "slug `{}` already exists in `{}`", slug, prefix)
79 }
80 DocumentError::NotTraversable { path, got } => {
81 write!(f, "path `{}` is {}, cannot traverse further", path, got)
82 }
83 DocumentError::TypeMismatch {
84 path,
85 expected,
86 got,
87 hint,
88 } => {
89 write!(f, "field `{}` expects {}, got `{}`", path, expected, got)?;
90 if let Some(h) = hint {
91 write!(f, "\n hint: {}", h)?;
92 }
93 Ok(())
94 }
95 DocumentError::PathNotFound { path } => {
96 write!(f, "path `{}` not found in config", path)
97 }
98 DocumentError::IndexOutOfBounds { path, index, len } => {
99 write!(
100 f,
101 "index {} out of bounds at `{}` (len {})",
102 index, path, len
103 )
104 }
105 DocumentError::ParseError { format, detail } => {
106 write!(f, "failed to parse {}: {}", format, detail)
107 }
108 DocumentError::IoError { detail } => {
109 write!(f, "io error: {}", detail)
110 }
111 DocumentError::UnsupportedOperation {
112 format,
113 operation,
114 detail,
115 } => write!(f, "{} does not support {}: {}", format, operation, detail),
116 }
117 }
118}
119
120impl std::error::Error for DocumentError {}
121
122impl DocumentError {
123 pub fn from_serde(path: impl Into<String>, err: impl std::fmt::Display) -> Self {
127 let msg = err.to_string();
128 let hint = msg
131 .split(" at line ")
132 .next()
133 .unwrap_or(&msg)
134 .trim()
135 .to_string();
136 DocumentError::TypeMismatch {
137 path: path.into(),
138 expected: String::new(),
139 got: hint,
140 hint: None,
141 }
142 }
143}
144
145impl From<io::Error> for DocumentError {
146 fn from(err: io::Error) -> Self {
147 DocumentError::IoError {
148 detail: err.to_string(),
149 }
150 }
151}