yaml_rt_serde/value/
index.rs1use std::fmt;
2use std::ops;
3
4use super::{Mapping, Number, Value};
5
6mod private {
7 pub trait Sealed {}
8
9 impl Sealed for usize {}
10 impl Sealed for str {}
11 impl Sealed for String {}
12 impl Sealed for super::Value {}
13 impl<T> Sealed for &T where T: ?Sized + Sealed {}
14}
15
16pub trait Index: private::Sealed {
18 #[doc(hidden)]
19 fn index_into<'a>(&self, value: &'a Value) -> Option<&'a Value>;
20
21 #[doc(hidden)]
22 fn index_into_mut<'a>(&self, value: &'a mut Value) -> Option<&'a mut Value>;
23
24 #[doc(hidden)]
25 fn index_or_insert<'a>(&self, value: &'a mut Value) -> &'a mut Value;
26
27 #[doc(hidden)]
28 fn mapping_position(&self, mapping: &Mapping) -> Option<usize>;
29}
30
31impl Index for usize {
32 fn index_into<'a>(&self, value: &'a Value) -> Option<&'a Value> {
33 match value.untag_ref() {
34 Value::Sequence(sequence) => sequence.get(*self),
35 Value::Mapping(mapping) => mapping.get(Value::Number(Number::from(*self))),
36 _ => None,
37 }
38 }
39
40 fn index_into_mut<'a>(&self, value: &'a mut Value) -> Option<&'a mut Value> {
41 match value.untag_mut() {
42 Value::Sequence(sequence) => sequence.get_mut(*self),
43 Value::Mapping(mapping) => mapping.get_mut(Value::Number(Number::from(*self))),
44 _ => None,
45 }
46 }
47
48 fn index_or_insert<'a>(&self, value: &'a mut Value) -> &'a mut Value {
49 match value.untag_mut() {
50 Value::Sequence(sequence) => {
51 let len = sequence.len();
52 sequence.get_mut(*self).unwrap_or_else(|| {
53 panic!("cannot access index {self} of YAML sequence of length {len}")
54 })
55 }
56 Value::Mapping(mapping) => mapping
57 .entry(Value::Number(Number::from(*self)))
58 .or_insert(Value::Null),
59 value => panic!("cannot access index {self} of YAML {}", Type(value)),
60 }
61 }
62
63 fn mapping_position(&self, mapping: &Mapping) -> Option<usize> {
64 mapping.position(&Value::Number(Number::from(*self)))
65 }
66}
67
68impl Index for Value {
69 fn index_into<'a>(&self, value: &'a Value) -> Option<&'a Value> {
70 match value.untag_ref() {
71 Value::Mapping(mapping) => mapping.get(self),
72 _ => None,
73 }
74 }
75
76 fn index_into_mut<'a>(&self, value: &'a mut Value) -> Option<&'a mut Value> {
77 match value.untag_mut() {
78 Value::Mapping(mapping) => mapping.get_mut(self),
79 _ => None,
80 }
81 }
82
83 fn index_or_insert<'a>(&self, value: &'a mut Value) -> &'a mut Value {
84 if matches!(value, Value::Null) {
85 *value = Value::Mapping(Mapping::new());
86 }
87 match value.untag_mut() {
88 Value::Mapping(mapping) => mapping.entry(self.clone()).or_insert(Value::Null),
89 value => panic!("cannot access key {self:?} in YAML {}", Type(value)),
90 }
91 }
92
93 fn mapping_position(&self, mapping: &Mapping) -> Option<usize> {
94 mapping.position(self)
95 }
96}
97
98impl Index for str {
99 fn index_into<'a>(&self, value: &'a Value) -> Option<&'a Value> {
100 match value.untag_ref() {
101 Value::Mapping(mapping) => mapping.get(self),
102 _ => None,
103 }
104 }
105
106 fn index_into_mut<'a>(&self, value: &'a mut Value) -> Option<&'a mut Value> {
107 match value.untag_mut() {
108 Value::Mapping(mapping) => mapping.get_mut(self),
109 _ => None,
110 }
111 }
112
113 fn index_or_insert<'a>(&self, value: &'a mut Value) -> &'a mut Value {
114 if matches!(value, Value::Null) {
115 *value = Value::Mapping(Mapping::new());
116 }
117 match value.untag_mut() {
118 Value::Mapping(mapping) => mapping
119 .entry(Value::String(self.to_owned()))
120 .or_insert(Value::Null),
121 value => panic!("cannot access key {self:?} in YAML {}", Type(value)),
122 }
123 }
124
125 fn mapping_position(&self, mapping: &Mapping) -> Option<usize> {
126 mapping
127 .entries
128 .iter()
129 .position(|(key, _)| matches!(key.untag_ref(), Value::String(key) if key == self))
130 }
131}
132
133impl Index for String {
134 fn index_into<'a>(&self, value: &'a Value) -> Option<&'a Value> {
135 self.as_str().index_into(value)
136 }
137
138 fn index_into_mut<'a>(&self, value: &'a mut Value) -> Option<&'a mut Value> {
139 self.as_str().index_into_mut(value)
140 }
141
142 fn index_or_insert<'a>(&self, value: &'a mut Value) -> &'a mut Value {
143 self.as_str().index_or_insert(value)
144 }
145
146 fn mapping_position(&self, mapping: &Mapping) -> Option<usize> {
147 self.as_str().mapping_position(mapping)
148 }
149}
150
151impl<T> Index for &T
152where
153 T: ?Sized + Index,
154{
155 fn index_into<'a>(&self, value: &'a Value) -> Option<&'a Value> {
156 (**self).index_into(value)
157 }
158
159 fn index_into_mut<'a>(&self, value: &'a mut Value) -> Option<&'a mut Value> {
160 (**self).index_into_mut(value)
161 }
162
163 fn index_or_insert<'a>(&self, value: &'a mut Value) -> &'a mut Value {
164 (**self).index_or_insert(value)
165 }
166
167 fn mapping_position(&self, mapping: &Mapping) -> Option<usize> {
168 (**self).mapping_position(mapping)
169 }
170}
171
172struct Type<'a>(&'a Value);
173
174impl fmt::Display for Type<'_> {
175 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
176 formatter.write_str(match self.0 {
177 Value::Null => "null",
178 Value::Bool(_) => "boolean",
179 Value::Number(_) => "number",
180 Value::String(_) => "string",
181 Value::Sequence(_) => "sequence",
182 Value::Mapping(_) => "mapping",
183 Value::Tagged(_) => "tagged value",
184 })
185 }
186}
187
188impl<I> ops::Index<I> for Value
189where
190 I: Index,
191{
192 type Output = Value;
193
194 fn index(&self, index: I) -> &Self::Output {
195 static NULL: Value = Value::Null;
196 index.index_into(self).unwrap_or(&NULL)
197 }
198}
199
200impl<I> ops::IndexMut<I> for Value
201where
202 I: Index,
203{
204 fn index_mut(&mut self, index: I) -> &mut Self::Output {
205 index.index_or_insert(self)
206 }
207}