serde_path_to_error/
path.rs
1use std::fmt::{self, Display};
2use std::slice;
3
4use super::Chain;
5
6#[derive(Clone, Debug)]
12pub struct Path {
13 segments: Vec<Segment>,
14}
15
16#[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 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
43pub 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}