serde_path_to_error/
path.rs

1use std::fmt::{self, Display};
2use std::slice;
3
4use super::Chain;
5
6/// Path to the error value in the input, like `dependencies.serde.typo1`.
7///
8/// Use `path.to_string()` to get a string representation of the path with
9/// segments separated by periods, or use `path.iter()` to iterate over
10/// individual segments of the path.
11#[derive(Clone, Debug)]
12pub struct Path {
13    segments: Vec<Segment>,
14}
15
16/// Single segment of a path.
17#[derive(Clone, Debug)]
18pub enum Segment {
19    Seq { index: usize },
20    Map { key: String },
21    Enum { variant: String },
22    Unknown,
23}
24
25impl Path {
26    /// Returns an iterator with element type [`&Segment`][Segment].
27    pub fn iter(&self) -> Segments {
28        Segments {
29            iter: self.segments.iter(),
30        }
31    }
32}
33
34impl<'a> IntoIterator for &'a Path {
35    type Item = &'a Segment;
36    type IntoIter = Segments<'a>;
37
38    fn into_iter(self) -> Self::IntoIter {
39        self.iter()
40    }
41}
42
43/// Iterator over segments of a path.
44pub struct Segments<'a> {
45    iter: slice::Iter<'a, Segment>,
46}
47
48impl<'a> Iterator for Segments<'a> {
49    type Item = &'a Segment;
50
51    fn next(&mut self) -> Option<Self::Item> {
52        self.iter.next()
53    }
54}
55
56impl Display for Path {
57    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
58        if self.segments.is_empty() {
59            return formatter.write_str(".");
60        }
61
62        let mut separator = "";
63        for segment in self {
64            match segment {
65                Segment::Seq { index } => {
66                    write!(formatter, "[{}]", index)?;
67                }
68                Segment::Map { key } | Segment::Enum { variant: key } => {
69                    write!(formatter, "{}{}", separator, key)?;
70                }
71                Segment::Unknown => {
72                    write!(formatter, "{}?", separator)?;
73                }
74            }
75            separator = ".";
76        }
77
78        Ok(())
79    }
80}
81
82impl Path {
83    pub(crate) fn empty() -> Self {
84        Path {
85            segments: Vec::new(),
86        }
87    }
88
89    pub(crate) fn from_chain(mut chain: &Chain) -> Self {
90        let mut segments = Vec::new();
91        loop {
92            match chain {
93                Chain::Root => break,
94                Chain::Seq { parent, index } => {
95                    segments.push(Segment::Seq { index: *index });
96                    chain = parent;
97                }
98                Chain::Map { parent, key } => {
99                    segments.push(Segment::Map { key: key.clone() });
100                    chain = parent;
101                }
102                Chain::Struct { parent, key } => {
103                    let key = *key;
104                    segments.push(Segment::Map {
105                        key: key.to_owned(),
106                    });
107                    chain = parent;
108                }
109                Chain::Enum { parent, variant } => {
110                    segments.push(Segment::Enum {
111                        variant: variant.clone(),
112                    });
113                    chain = parent;
114                }
115                Chain::Some { parent }
116                | Chain::NewtypeStruct { parent }
117                | Chain::NewtypeVariant { parent } => {
118                    chain = parent;
119                }
120                Chain::NonStringKey { parent } => {
121                    segments.push(Segment::Unknown);
122                    chain = parent;
123                }
124            }
125        }
126        segments.reverse();
127        Path { segments }
128    }
129}