rust_yaml/
zero_copy_value.rs1use indexmap::IndexMap;
8use std::fmt;
9use std::rc::Rc;
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum OptimizedValue {
14 Null,
16 Bool(bool),
18 Int(i64),
20 Float(f64),
22 String(Rc<String>),
24 Sequence(Rc<Vec<OptimizedValue>>),
26 Mapping(Rc<IndexMap<OptimizedValue, OptimizedValue>>),
28}
29
30impl OptimizedValue {
31 pub const fn null() -> Self {
33 Self::Null
34 }
35
36 pub const fn bool(b: bool) -> Self {
38 Self::Bool(b)
39 }
40
41 pub const fn int(i: i64) -> Self {
43 Self::Int(i)
44 }
45
46 pub const fn float(f: f64) -> Self {
48 Self::Float(f)
49 }
50
51 pub fn string(s: impl Into<String>) -> Self {
53 Self::String(Rc::new(s.into()))
54 }
55
56 pub fn sequence() -> Self {
58 Self::Sequence(Rc::new(Vec::new()))
59 }
60
61 pub fn sequence_with(values: Vec<Self>) -> Self {
63 Self::Sequence(Rc::new(values))
64 }
65
66 pub fn mapping() -> Self {
68 Self::Mapping(Rc::new(IndexMap::new()))
69 }
70
71 pub fn mapping_with(pairs: Vec<(Self, Self)>) -> Self {
73 let mut map = IndexMap::new();
74 for (key, value) in pairs {
75 map.insert(key, value);
76 }
77 Self::Mapping(Rc::new(map))
78 }
79
80 pub fn as_str(&self) -> Option<&str> {
82 if let Self::String(s) = self {
83 Some(s.as_str())
84 } else {
85 None
86 }
87 }
88
89 pub fn as_sequence(&self) -> Option<&[OptimizedValue]> {
91 if let Self::Sequence(seq) = self {
92 Some(seq.as_slice())
93 } else {
94 None
95 }
96 }
97
98 pub fn as_mapping(&self) -> Option<&IndexMap<OptimizedValue, OptimizedValue>> {
100 if let Self::Mapping(map) = self {
101 Some(map.as_ref())
102 } else {
103 None
104 }
105 }
106
107 pub fn from_value(value: crate::Value) -> Self {
109 match value {
110 crate::Value::Null => Self::Null,
111 crate::Value::Bool(b) => Self::Bool(b),
112 crate::Value::Int(i) => Self::Int(i),
113 crate::Value::Float(f) => Self::Float(f),
114 crate::Value::String(s) => Self::String(Rc::new(s)),
115 crate::Value::Sequence(seq) => {
116 Self::Sequence(Rc::new(seq.into_iter().map(Self::from_value).collect()))
117 }
118 crate::Value::Mapping(map) => Self::Mapping(Rc::new(
119 map.into_iter()
120 .map(|(k, v)| (Self::from_value(k), Self::from_value(v)))
121 .collect(),
122 )),
123 }
124 }
125
126 pub fn to_value(&self) -> crate::Value {
128 match self {
129 Self::Null => crate::Value::Null,
130 Self::Bool(b) => crate::Value::Bool(*b),
131 Self::Int(i) => crate::Value::Int(*i),
132 Self::Float(f) => crate::Value::Float(*f),
133 Self::String(s) => crate::Value::String((**s).clone()),
134 Self::Sequence(seq) => {
135 crate::Value::Sequence(seq.iter().map(|v| v.to_value()).collect())
136 }
137 Self::Mapping(map) => crate::Value::Mapping(
138 map.iter()
139 .map(|(k, v)| (k.to_value(), v.to_value()))
140 .collect(),
141 ),
142 }
143 }
144}
145
146impl fmt::Display for OptimizedValue {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 match self {
149 Self::Null => write!(f, "null"),
150 Self::Bool(b) => write!(f, "{}", b),
151 Self::Int(i) => write!(f, "{}", i),
152 Self::Float(fl) => write!(f, "{}", fl),
153 Self::String(s) => write!(f, "{}", s),
154 Self::Sequence(seq) => {
155 write!(f, "[")?;
156 for (i, item) in seq.iter().enumerate() {
157 if i > 0 {
158 write!(f, ", ")?;
159 }
160 write!(f, "{}", item)?;
161 }
162 write!(f, "]")
163 }
164 Self::Mapping(map) => {
165 write!(f, "{{")?;
166 for (i, (key, value)) in map.iter().enumerate() {
167 if i > 0 {
168 write!(f, ", ")?;
169 }
170 write!(f, "{}: {}", key, value)?;
171 }
172 write!(f, "}}")
173 }
174 }
175 }
176}
177
178impl std::hash::Hash for OptimizedValue {
179 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
180 match self {
181 Self::Null => 0.hash(state),
182 Self::Bool(b) => {
183 1.hash(state);
184 b.hash(state);
185 }
186 Self::Int(i) => {
187 2.hash(state);
188 i.hash(state);
189 }
190 Self::Float(f) => {
191 3.hash(state);
192 f.to_bits().hash(state);
193 }
194 Self::String(s) => {
195 4.hash(state);
196 s.hash(state);
197 }
198 Self::Sequence(seq) => {
199 5.hash(state);
200 seq.len().hash(state);
201 for item in seq.iter() {
202 item.hash(state);
203 }
204 }
205 Self::Mapping(_) => {
206 6.hash(state);
207 }
209 }
210 }
211}
212
213impl Eq for OptimizedValue {}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218
219 #[test]
220 fn test_rc_string_cloning() {
221 let value1 = OptimizedValue::string("hello world");
222 let value2 = value1.clone();
223
224 if let (OptimizedValue::String(s1), OptimizedValue::String(s2)) = (&value1, &value2) {
226 assert!(Rc::ptr_eq(s1, s2));
227 }
228 }
229
230 #[test]
231 fn test_rc_sequence_cloning() {
232 let value1 =
233 OptimizedValue::sequence_with(vec![OptimizedValue::int(1), OptimizedValue::int(2)]);
234 let value2 = value1.clone();
235
236 if let (OptimizedValue::Sequence(s1), OptimizedValue::Sequence(s2)) = (&value1, &value2) {
238 assert!(Rc::ptr_eq(s1, s2));
239 }
240 }
241
242 #[test]
243 fn test_conversion_roundtrip() {
244 let original = crate::Value::Mapping(indexmap::indexmap! {
245 crate::Value::String("key".to_string()) => crate::Value::Int(42),
246 });
247
248 let optimized = OptimizedValue::from_value(original.clone());
249 let converted_back = optimized.to_value();
250
251 assert_eq!(original, converted_back);
252 }
253}