nondestructive/yaml/
data.rs1use core::fmt;
2use core::hash::Hash;
3use core::mem;
4use core::num::NonZeroUsize;
5
6use alloc::boxed::Box;
7
8use std::collections::hash_map::{self, HashMap};
9
10use bstr::BStr;
11#[cfg(feature = "serde-edits")]
12use serde::{Deserialize, Serialize};
13use twox_hash::xxh3::{Hash128, HasherExt};
14
15use crate::yaml::raw;
16
17#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[cfg_attr(feature = "serde-edits", derive(Serialize, Deserialize))]
20#[cfg_attr(feature = "serde-edits", serde(transparent))]
21#[repr(transparent)]
22pub(crate) struct StringId([u8; 16]);
23
24impl fmt::Display for StringId {
25 #[inline]
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 write!(f, "{}", Hex(&self.0))
28 }
29}
30
31impl fmt::Debug for StringId {
32 #[inline]
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 f.debug_tuple("StringId").field(&Hex(&self.0)).finish()
35 }
36}
37
38struct Hex<'a>(&'a [u8]);
39
40impl fmt::Display for Hex<'_> {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 for byte in self.0 {
43 write!(f, "{byte:02x}")?;
44 }
45
46 Ok(())
47 }
48}
49
50impl fmt::Debug for Hex<'_> {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 fmt::Display::fmt(self, f)
53 }
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
70#[cfg_attr(feature = "serde-edits", derive(Serialize, Deserialize))]
71#[cfg_attr(feature = "serde-edits", serde(transparent))]
72#[repr(transparent)]
73pub struct Id(NonZeroUsize);
74
75impl Id {
76 #[inline]
77 fn get(self) -> usize {
78 self.0.get().wrapping_sub(1)
79 }
80}
81
82impl fmt::Display for Id {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 write!(f, "{:08x}", self.get())
85 }
86}
87
88#[derive(Debug, Clone)]
89#[cfg_attr(feature = "serde-edits", derive(Serialize, Deserialize))]
90pub(crate) struct Entry {
91 raw: raw::Raw,
92 layout: raw::Layout,
93}
94
95#[derive(Clone, Default)]
97#[cfg_attr(feature = "serde-edits", derive(Serialize, Deserialize))]
98pub(crate) struct Data {
99 strings: HashMap<StringId, Box<[u8]>>,
100 slab: slab::Slab<Entry>,
101}
102
103impl Data {
104 #[inline]
106 #[must_use]
107 pub(crate) fn str(&self, id: StringId) -> &BStr {
108 let Some(string) = self.strings.get(&id) else {
109 panic!("missing string with id {id}");
110 };
111
112 BStr::new(string.as_ref())
113 }
114
115 pub(crate) fn insert_str<B>(&mut self, string: B) -> StringId
117 where
118 B: AsRef<[u8]>,
119 {
120 let mut hasher = Hash128::default();
121 string.as_ref().hash(&mut hasher);
122 let hash = hasher.finish_ext();
123 let hash = hash.to_le_bytes();
124 let id = StringId(hash);
125
126 if let hash_map::Entry::Vacant(e) = self.strings.entry(id) {
127 e.insert(string.as_ref().into());
128 }
129
130 id
131 }
132
133 #[inline]
134 pub(crate) fn layout(&self, id: Id) -> &raw::Layout {
135 if let Some(raw) = self.slab.get(id.get()) {
136 return &raw.layout;
137 }
138
139 panic!("expected layout at {id}")
140 }
141
142 #[inline]
143 pub(crate) fn prefix(&self, id: Id) -> &BStr {
144 self.str(self.layout(id).prefix)
145 }
146
147 #[inline]
148 pub(crate) fn pair(&self, id: Id) -> (&raw::Raw, &raw::Layout) {
149 if let Some(raw) = self.slab.get(id.get()) {
150 return (&raw.raw, &raw.layout);
151 }
152
153 panic!("expected raw at {id}")
154 }
155
156 #[inline]
157 pub(crate) fn raw(&self, id: Id) -> &raw::Raw {
158 if let Some(raw) = self.slab.get(id.get()) {
159 return &raw.raw;
160 }
161
162 panic!("expected raw at {id}")
163 }
164
165 #[inline]
166 pub(crate) fn raw_mut(&mut self, id: Id) -> &mut raw::Raw {
167 if let Some(raw) = self.slab.get_mut(id.get()) {
168 return &mut raw.raw;
169 }
170
171 panic!("expected raw at {id}")
172 }
173
174 #[inline]
175 pub(crate) fn sequence(&self, id: Id) -> &raw::Sequence {
176 if let Some(Entry {
177 raw: raw::Raw::Sequence(raw),
178 ..
179 }) = self.slab.get(id.get())
180 {
181 return raw;
182 }
183
184 panic!("expected sequence at {id}")
185 }
186
187 #[inline]
188 pub(crate) fn sequence_mut(&mut self, id: Id) -> &mut raw::Sequence {
189 if let Some(Entry {
190 raw: raw::Raw::Sequence(raw),
191 ..
192 }) = self.slab.get_mut(id.get())
193 {
194 return raw;
195 }
196
197 panic!("expected sequence at {id}")
198 }
199
200 #[inline]
201 pub(crate) fn mapping(&self, id: Id) -> &raw::Mapping {
202 if let Some(Entry {
203 raw: raw::Raw::Mapping(raw),
204 ..
205 }) = self.slab.get(id.get())
206 {
207 return raw;
208 }
209
210 panic!("expected mapping at {id}")
211 }
212
213 #[inline]
214 pub(crate) fn sequence_item(&self, id: Id) -> &raw::SequenceItem {
215 if let Some(Entry {
216 raw: raw::Raw::SequenceItem(raw),
217 ..
218 }) = self.slab.get(id.get())
219 {
220 return raw;
221 }
222
223 panic!("expected sequence item at {id}")
224 }
225
226 #[inline]
227 pub(crate) fn mapping_item(&self, id: Id) -> &raw::MappingItem {
228 if let Some(Entry {
229 raw: raw::Raw::MappingItem(raw),
230 ..
231 }) = self.slab.get(id.get())
232 {
233 return raw;
234 }
235
236 panic!("expected mapping item at {id}")
237 }
238
239 #[inline]
240 pub(crate) fn mapping_mut(&mut self, id: Id) -> &mut raw::Mapping {
241 if let Some(Entry {
242 raw: raw::Raw::Mapping(raw),
243 ..
244 }) = self.slab.get_mut(id.get())
245 {
246 return raw;
247 }
248
249 panic!("expected mapping at {id}")
250 }
251
252 #[inline]
254 pub(crate) fn insert(&mut self, raw: raw::Raw, prefix: StringId, parent: Option<Id>) -> Id {
255 let index = self.slab.insert(Entry {
256 raw,
257 layout: raw::Layout { prefix, parent },
258 });
259 let index = NonZeroUsize::new(index.wrapping_add(1)).expect("ran out of ids");
260 Id(index)
261 }
262
263 #[inline]
265 pub(crate) fn drop(&mut self, id: Id) {
266 let Some(value) = self.slab.try_remove(id.get()) else {
267 return;
268 };
269
270 self.drop_kind(value.raw);
271 }
272
273 #[inline]
275 pub(crate) fn drop_kind(&mut self, raw: raw::Raw) {
276 match raw {
277 raw::Raw::Mapping(raw) => {
278 for item in raw.items {
279 self.drop(item);
280 }
281 }
282 raw::Raw::MappingItem(raw) => {
283 let item = self.slab.remove(raw.value.get());
284 self.drop_kind(item.raw);
285 }
286 raw::Raw::Sequence(raw) => {
287 for item in raw.items {
288 self.drop(item);
289 }
290 }
291 raw::Raw::SequenceItem(raw) => {
292 let item = self.slab.remove(raw.value.get());
293 self.drop_kind(item.raw);
294 }
295 _ => {}
296 }
297 }
298
299 pub(crate) fn replace<T>(&mut self, id: Id, raw: T)
301 where
302 T: Into<raw::Raw>,
303 {
304 let Some(value) = self.slab.get_mut(id.get()) else {
305 return;
306 };
307
308 let removed = mem::replace(&mut value.raw, raw.into());
309 self.drop_kind(removed);
310 }
311
312 pub(crate) fn replace_with(&mut self, id: Id, prefix: StringId, raw: raw::Raw) {
314 let Some(value) = self.slab.get_mut(id.get()) else {
315 return;
316 };
317
318 value.layout.prefix = prefix;
319 let removed = mem::replace(&mut value.raw, raw);
320 self.drop_kind(removed);
321 }
322}