1use std::fmt::{self, Display};
4use std::borrow::Cow;
5
6use serde::{ser, de};
7
8use crate::{Figment, Profile, Metadata, value::Tag};
9
10pub type Result<T> = std::result::Result<T, Error>;
12
13#[derive(Clone, Debug, PartialEq)]
89pub struct Error {
90 tag: Tag,
92 pub profile: Option<Profile>,
94 pub metadata: Option<Metadata>,
96 pub path: Vec<String>,
98 pub kind: Kind,
100 prev: Option<Box<Error>>,
101}
102
103#[derive(Clone, Debug, PartialEq)]
105pub enum Kind {
106 Message(String),
108
109 InvalidType(Actual, String),
112 InvalidValue(Actual, String),
115 InvalidLength(usize, String),
118
119 UnknownVariant(String, &'static [&'static str]),
122 UnknownField(String, &'static [&'static str]),
125 MissingField(Cow<'static, str>),
127 DuplicateField(&'static str),
130
131 ISizeOutOfRange(isize),
133 USizeOutOfRange(usize),
135
136 Unsupported(Actual),
138
139 UnsupportedKey(Actual, Cow<'static, str>),
141}
142
143impl Error {
144 pub(crate) fn prefixed(mut self, key: &str) -> Self {
145 self.path.insert(0, key.into());
146 self
147 }
148
149 pub(crate) fn retagged(mut self, tag: Tag) -> Self {
150 if self.tag.is_default() {
151 self.tag = tag;
152 }
153
154 self
155 }
156
157 pub(crate) fn resolved(mut self, config: &Figment) -> Self {
158 let mut error = Some(&mut self);
159 while let Some(e) = error {
160 e.metadata = config.get_metadata(e.tag).cloned();
161 e.profile = e.tag.profile()
162 .or_else(|| Some(config.profile().clone()));
163
164 error = e.prev.as_deref_mut();
165 }
166
167 self
168 }
169}
170
171impl Error {
172 pub fn missing(&self) -> bool {
183 matches!(self.kind, Kind::MissingField(..))
184 }
185
186 pub fn with_path(mut self, path: &str) -> Self {
200 let paths = path.split('.')
201 .filter(|v| !v.is_empty())
202 .map(|v| v.to_string());
203
204 self.path.extend(paths);
205 self
206 }
207
208 pub fn chain(self, mut error: Error) -> Self {
237 error.prev = Some(Box::new(self));
238 error
239 }
240
241 pub fn count(&self) -> usize {
269 1 + self.prev.as_ref().map_or(0, |e| e.count())
270 }
271}
272
273pub struct IntoIter(Option<Error>);
275
276impl Iterator for IntoIter {
277 type Item = Error;
278
279 fn next(&mut self) -> Option<Self::Item> {
280 if let Some(mut error) = self.0.take() {
281 self.0 = error.prev.take().map(|e| *e);
282 Some(error)
283 } else {
284 None
285 }
286 }
287}
288
289impl IntoIterator for Error {
290 type Item = Error;
291 type IntoIter = IntoIter;
292
293 fn into_iter(self) -> Self::IntoIter {
294 IntoIter(Some(self))
295 }
296}
297
298#[allow(missing_docs)]
301#[derive(Clone, Debug, PartialEq)]
302pub enum Actual {
303 Bool(bool),
304 Unsigned(u128),
305 Signed(i128),
306 Float(f64),
307 Char(char),
308 Str(String),
309 Bytes(Vec<u8>),
310 Unit,
311 Option,
312 NewtypeStruct,
313 Seq,
314 Map,
315 Enum,
316 UnitVariant,
317 NewtypeVariant,
318 TupleVariant,
319 StructVariant,
320 Other(String),
321}
322
323impl fmt::Display for Actual {
324 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
325 match self {
326 Actual::Bool(v) => write!(f, "bool {}", v),
327 Actual::Unsigned(v) => write!(f, "unsigned int `{}`", v),
328 Actual::Signed(v) => write!(f, "signed int `{}`", v),
329 Actual::Float(v) => write!(f, "float `{}`", v),
330 Actual::Char(v) => write!(f, "char {:?}", v),
331 Actual::Str(v) => write!(f, "string {:?}", v),
332 Actual::Bytes(v) => write!(f, "bytes {:?}", v),
333 Actual::Unit => write!(f, "unit"),
334 Actual::Option => write!(f, "option"),
335 Actual::NewtypeStruct => write!(f, "new-type struct"),
336 Actual::Seq => write!(f, "sequence"),
337 Actual::Map => write!(f, "map"),
338 Actual::Enum => write!(f, "enum"),
339 Actual::UnitVariant => write!(f, "unit variant"),
340 Actual::NewtypeVariant => write!(f, "new-type variant"),
341 Actual::TupleVariant => write!(f, "tuple variant"),
342 Actual::StructVariant => write!(f, "struct variant"),
343 Actual::Other(v) => v.fmt(f),
344 }
345 }
346}
347
348impl From<de::Unexpected<'_>> for Actual {
349 fn from(value: de::Unexpected<'_>) -> Actual {
350 match value {
351 de::Unexpected::Bool(v) => Actual::Bool(v),
352 de::Unexpected::Unsigned(v) => Actual::Unsigned(v as u128),
353 de::Unexpected::Signed(v) => Actual::Signed(v as i128),
354 de::Unexpected::Float(v) => Actual::Float(v),
355 de::Unexpected::Char(v) => Actual::Char(v),
356 de::Unexpected::Str(v) => Actual::Str(v.into()),
357 de::Unexpected::Bytes(v) => Actual::Bytes(v.into()),
358 de::Unexpected::Unit => Actual::Unit,
359 de::Unexpected::Option => Actual::Option,
360 de::Unexpected::NewtypeStruct => Actual::NewtypeStruct,
361 de::Unexpected::Seq => Actual::Seq,
362 de::Unexpected::Map => Actual::Map,
363 de::Unexpected::Enum => Actual::Enum,
364 de::Unexpected::UnitVariant => Actual::UnitVariant,
365 de::Unexpected::NewtypeVariant => Actual::NewtypeVariant,
366 de::Unexpected::TupleVariant => Actual::TupleVariant,
367 de::Unexpected::StructVariant => Actual::StructVariant,
368 de::Unexpected::Other(v) => Actual::Other(v.into())
369 }
370 }
371}
372
373impl de::Error for Error {
374 fn custom<T: Display>(msg: T) -> Self {
375 Kind::Message(msg.to_string()).into()
376 }
377
378 fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
379 Kind::InvalidType(unexp.into(), exp.to_string()).into()
380 }
381
382 fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
383 Kind::InvalidValue(unexp.into(), exp.to_string()).into()
384 }
385
386 fn invalid_length(len: usize, exp: &dyn de::Expected) -> Self {
387 Kind::InvalidLength(len, exp.to_string()).into()
388 }
389
390 fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
391 Kind::UnknownVariant(variant.into(), expected).into()
392 }
393
394 fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
395 Kind::UnknownField(field.into(), expected).into()
396 }
397
398 fn missing_field(field: &'static str) -> Self {
399 Kind::MissingField(field.into()).into()
400 }
401
402 fn duplicate_field(field: &'static str) -> Self {
403 Kind::DuplicateField(field).into()
404 }
405}
406
407impl ser::Error for Error {
408 fn custom<T: Display>(msg: T) -> Self {
409 Kind::Message(msg.to_string()).into()
410 }
411}
412
413impl From<Kind> for Error {
414 fn from(kind: Kind) -> Error {
415 Error {
416 tag: Tag::Default,
417 path: vec![],
418 profile: None,
419 metadata: None,
420 prev: None,
421 kind,
422 }
423 }
424}
425
426impl From<&str> for Error {
427 fn from(string: &str) -> Error {
428 Kind::Message(string.into()).into()
429 }
430}
431
432impl From<String> for Error {
433 fn from(string: String) -> Error {
434 Kind::Message(string).into()
435 }
436}
437
438impl Display for Kind {
439 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
440 match self {
441 Kind::Message(msg) => f.write_str(&msg),
442 Kind::InvalidType(v, exp) => {
443 write!(f, "invalid type: found {}, expected {}", v, exp)
444 }
445 Kind::InvalidValue(v, exp) => {
446 write!(f, "invalid value {}, expected {}", v, exp)
447 },
448 Kind::InvalidLength(v, exp) => {
449 write!(f, "invalid length {}, expected {}", v, exp)
450 },
451 Kind::UnknownVariant(v, exp) => {
452 write!(f, "unknown variant: found `{}`, expected `{}`", v, OneOf(exp))
453 }
454 Kind::UnknownField(v, exp) => {
455 write!(f, "unknown field: found `{}`, expected `{}`", v, OneOf(exp))
456 }
457 Kind::MissingField(v) => {
458 write!(f, "missing field `{}`", v)
459 }
460 Kind::DuplicateField(v) => {
461 write!(f, "duplicate field `{}`", v)
462 }
463 Kind::ISizeOutOfRange(v) => {
464 write!(f, "signed integer `{}` is out of range", v)
465 }
466 Kind::USizeOutOfRange(v) => {
467 write!(f, "unsigned integer `{}` is out of range", v)
468 }
469 Kind::Unsupported(v) => {
470 write!(f, "unsupported type `{}`", v)
471 }
472 Kind::UnsupportedKey(a, e) => {
473 write!(f, "unsupported type `{}` for key: must be `{}`", a, e)
474 }
475 }
476 }
477}
478
479impl Display for Error {
480 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
481 self.kind.fmt(f)?;
482
483 if let (Some(profile), Some(md)) = (&self.profile, &self.metadata) {
484 if !self.path.is_empty() {
485 let key = md.interpolate(profile, &self.path);
486 write!(f, " for key {:?}", key)?;
487 }
488 }
489
490 if let Some(md) = &self.metadata {
491 if let Some(source) = &md.source {
492 write!(f, " in {} {}", source, md.name)?;
493 } else {
494 write!(f, " in {}", md.name)?;
495 }
496 }
497
498 if let Some(prev) = &self.prev {
499 write!(f, "\n{}", prev)?;
500 }
501
502 Ok(())
503 }
504}
505
506impl std::error::Error for Error {}
507
508pub struct OneOf(pub &'static [&'static str]);
511
512impl fmt::Display for OneOf {
513 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
514 match self.0.len() {
515 0 => write!(f, "none"),
516 1 => write!(f, "`{}`", self.0[0]),
517 2 => write!(f, "`{}` or `{}`", self.0[0], self.0[1]),
518 _ => {
519 write!(f, "one of ")?;
520 for (i, alt) in self.0.iter().enumerate() {
521 if i > 0 { write!(f, ", ")?; }
522 write!(f, "`{}`", alt)?;
523 }
524
525 Ok(())
526 }
527 }
528 }
529}
530
531impl de::Expected for OneOf {
532 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
533 Display::fmt(self, f)
534 }
535}