chunkedge_nbt/
compound.rs

1use std::borrow::{Borrow, Cow};
2use std::fmt;
3use std::hash::Hash;
4use std::iter::FusedIterator;
5use std::ops::{Deref, DerefMut, Index, IndexMut};
6
7use crate::Value;
8
9/// A map type with [`String`] keys and [`Value`] values.
10#[derive(Clone, Default)]
11pub struct Compound<S = String> {
12    map: Map<S>,
13}
14
15/// A wrapper around Compound that encodes and decodes as network NBT
16#[derive(Clone, Default)]
17pub struct NetworkCompound<S = String> {
18    pub compound: Compound<S>,
19}
20
21impl<S> NetworkCompound<S> {
22    pub fn from(inner: Compound<S>) -> NetworkCompound<S> {
23        NetworkCompound::<S> { compound: inner }
24    }
25}
26
27impl<S> Deref for NetworkCompound<S> {
28    type Target = Compound<S>;
29
30    fn deref(&self) -> &Self::Target {
31        &self.compound
32    }
33}
34impl<S> DerefMut for NetworkCompound<S> {
35    fn deref_mut(&mut self) -> &mut Self::Target {
36        &mut self.compound
37    }
38}
39
40#[cfg(not(feature = "preserve_order"))]
41type Map<S> = std::collections::BTreeMap<S, Value<S>>;
42
43#[cfg(feature = "preserve_order")]
44type Map<S> = indexmap::IndexMap<S, Value<S>>;
45
46impl<S: fmt::Debug> fmt::Debug for Compound<S> {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        self.map.fmt(f)
49    }
50}
51
52impl<S> PartialEq for Compound<S>
53where
54    S: Ord + Hash,
55{
56    fn eq(&self, other: &Self) -> bool {
57        self.map == other.map
58    }
59}
60
61#[cfg(feature = "serde")]
62impl<Str> serde::Serialize for Compound<Str>
63where
64    Str: Ord + Hash + serde::Serialize,
65{
66    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
67    where
68        S: serde::Serializer,
69    {
70        self.map.serialize(serializer)
71    }
72}
73
74#[cfg(feature = "serde")]
75impl<'de, S> serde::Deserialize<'de> for Compound<S>
76where
77    S: Ord + Hash + serde::Deserialize<'de>,
78{
79    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
80    where
81        D: serde::Deserializer<'de>,
82    {
83        Map::<S>::deserialize(deserializer).map(|map| Self { map })
84    }
85
86    fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
87    where
88        D: serde::Deserializer<'de>,
89    {
90        Map::<S>::deserialize_in_place(deserializer, &mut place.map)
91    }
92}
93
94impl<S> Compound<S> {
95    pub fn new() -> Self {
96        Self { map: Map::new() }
97    }
98
99    pub fn with_capacity(cap: usize) -> Self {
100        Self {
101            #[cfg(not(feature = "preserve_order"))]
102            map: {
103                // BTreeMap does not have with_capacity.
104                let _ = cap;
105                Map::new()
106            },
107            #[cfg(feature = "preserve_order")]
108            map: Map::with_capacity(cap),
109        }
110    }
111
112    pub fn clear(&mut self) {
113        self.map.clear();
114    }
115}
116
117impl<S> Compound<S>
118where
119    S: Ord + Hash,
120{
121    pub fn get<Q>(&self, k: &Q) -> Option<&Value<S>>
122    where
123        Q: ?Sized + AsBorrowed<S>,
124        <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
125        S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
126    {
127        self.map.get(k.as_borrowed())
128    }
129
130    pub fn contains_key<Q>(&self, k: &Q) -> bool
131    where
132        Q: ?Sized + AsBorrowed<S>,
133        <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
134        S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
135    {
136        self.map.contains_key(k.as_borrowed())
137    }
138
139    pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut Value<S>>
140    where
141        Q: ?Sized + AsBorrowed<S>,
142        <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
143        S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
144    {
145        self.map.get_mut(k.as_borrowed())
146    }
147
148    pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&S, &Value<S>)>
149    where
150        Q: ?Sized + AsBorrowed<S>,
151        <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
152        S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
153    {
154        self.map.get_key_value(k.as_borrowed())
155    }
156
157    pub fn insert<K, V>(&mut self, k: K, v: V) -> Option<Value<S>>
158    where
159        K: Into<S>,
160        V: Into<Value<S>>,
161    {
162        self.map.insert(k.into(), v.into())
163    }
164
165    pub fn remove<Q>(&mut self, k: &Q) -> Option<Value<S>>
166    where
167        Q: ?Sized + AsBorrowed<S>,
168        <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
169        S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
170    {
171        #[cfg(feature = "preserve_order")]
172        return self.swap_remove(k);
173        #[cfg(not(feature = "preserve_order"))]
174        return self.map.remove(k.as_borrowed());
175    }
176
177    #[cfg(feature = "preserve_order")]
178    pub fn swap_remove<Q>(&mut self, k: &Q) -> Option<Value<S>>
179    where
180        Q: ?Sized + AsBorrowed<S>,
181        <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
182        S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
183    {
184        self.map.swap_remove(k.as_borrowed())
185    }
186
187    #[cfg(feature = "preserve_order")]
188    pub fn shift_remove<Q>(&mut self, k: &Q) -> Option<Value<S>>
189    where
190        Q: ?Sized + AsBorrowed<S>,
191        <Q as AsBorrowed<S>>::Borrowed: Hash + Ord,
192        S: Borrow<<Q as AsBorrowed<S>>::Borrowed>,
193    {
194        self.map.shift_remove(k.as_borrowed())
195    }
196
197    pub fn remove_entry<Q>(&mut self, k: &Q) -> Option<(S, Value<S>)>
198    where
199        S: Borrow<Q>,
200        Q: ?Sized + Ord + Hash,
201    {
202        #[cfg(feature = "preserve_order")]
203        return self.swap_remove_entry(k);
204        #[cfg(not(feature = "preserve_order"))]
205        return self.map.remove_entry(k);
206    }
207
208    #[cfg(feature = "preserve_order")]
209    pub fn swap_remove_entry<Q>(&mut self, k: &Q) -> Option<(S, Value<S>)>
210    where
211        S: Borrow<Q>,
212        Q: ?Sized + Ord + Hash,
213    {
214        self.map.swap_remove_entry(k)
215    }
216
217    #[cfg(feature = "preserve_order")]
218    pub fn shift_remove_entry<Q>(&mut self, k: &Q) -> Option<(S, Value<S>)>
219    where
220        S: Borrow<Q>,
221        Q: ?Sized + Ord + Hash,
222    {
223        self.map.shift_remove_entry(k)
224    }
225
226    pub fn append(&mut self, other: &mut Self) {
227        #[cfg(not(feature = "preserve_order"))]
228        self.map.append(&mut other.map);
229
230        #[cfg(feature = "preserve_order")]
231        for (k, v) in std::mem::take(&mut other.map) {
232            self.map.insert(k, v);
233        }
234    }
235
236    pub fn entry<K>(&mut self, k: K) -> Entry<'_, S>
237    where
238        K: Into<S>,
239    {
240        #[cfg(not(feature = "preserve_order"))]
241        use std::collections::btree_map::Entry as EntryImpl;
242
243        #[cfg(feature = "preserve_order")]
244        use indexmap::map::Entry as EntryImpl;
245
246        match self.map.entry(k.into()) {
247            EntryImpl::Vacant(ve) => Entry::Vacant(VacantEntry { entry: ve }),
248            EntryImpl::Occupied(oe) => Entry::Occupied(OccupiedEntry { entry: oe }),
249        }
250    }
251
252    pub fn len(&self) -> usize {
253        self.map.len()
254    }
255
256    pub fn is_empty(&self) -> bool {
257        self.map.is_empty()
258    }
259
260    pub fn iter(&self) -> Iter<'_, S> {
261        Iter {
262            iter: self.map.iter(),
263        }
264    }
265
266    pub fn iter_mut(&mut self) -> IterMut<'_, S> {
267        IterMut {
268            iter: self.map.iter_mut(),
269        }
270    }
271
272    pub fn keys(&self) -> Keys<'_, S> {
273        Keys {
274            iter: self.map.keys(),
275        }
276    }
277
278    pub fn values(&self) -> Values<'_, S> {
279        Values {
280            iter: self.map.values(),
281        }
282    }
283
284    pub fn values_mut(&mut self) -> ValuesMut<'_, S> {
285        ValuesMut {
286            iter: self.map.values_mut(),
287        }
288    }
289
290    pub fn retain<F>(&mut self, f: F)
291    where
292        F: FnMut(&S, &mut Value<S>) -> bool,
293    {
294        self.map.retain(f)
295    }
296
297    /// Inserts all items from `other` into `self` recursively.
298    ///
299    /// # Example
300    ///
301    /// ```
302    /// use chunkedge_nbt::compound;
303    ///
304    /// let mut this = compound! {
305    ///     "foo" => 10,
306    ///     "bar" => compound! {
307    ///         "baz" => 20,
308    ///     }
309    /// };
310    ///
311    /// let other = compound! {
312    ///     "foo" => 15,
313    ///     "bar" => compound! {
314    ///         "quux" => "hello",
315    ///     }
316    /// };
317    ///
318    /// this.merge(other);
319    ///
320    /// assert_eq!(
321    ///     this,
322    ///     compound! {
323    ///         "foo" => 15,
324    ///         "bar" => compound! {
325    ///             "baz" => 20,
326    ///             "quux" => "hello",
327    ///         }
328    ///     }
329    /// );
330    /// ```
331    pub fn merge(&mut self, other: Compound<S>) {
332        for (k, v) in other {
333            match (self.entry(k), v) {
334                (Entry::Occupied(mut oe), Value::Compound(other)) => {
335                    if let Value::Compound(this) = oe.get_mut() {
336                        // Insert compound recursively.
337                        this.merge(other);
338                    }
339                }
340                (Entry::Occupied(mut oe), value) => {
341                    oe.insert(value);
342                }
343                (Entry::Vacant(ve), value) => {
344                    ve.insert(value);
345                }
346            }
347        }
348    }
349}
350
351/// Trait that can be used as a key to query a compound. Basically something
352/// that can be converted to a type `B` such that `S: Borrow<B>`.
353pub trait AsBorrowed<S> {
354    type Borrowed: ?Sized;
355
356    fn as_borrowed(&self) -> &Self::Borrowed;
357}
358
359impl<Q: ?Sized> AsBorrowed<String> for Q
360where
361    String: Borrow<Q>,
362{
363    type Borrowed = Q;
364
365    #[inline]
366    fn as_borrowed(&self) -> &Q {
367        self
368    }
369}
370
371impl<'a, Q: ?Sized> AsBorrowed<Cow<'a, str>> for Q
372where
373    Cow<'a, str>: Borrow<Q>,
374{
375    type Borrowed = Q;
376
377    #[inline]
378    fn as_borrowed(&self) -> &Q {
379        self
380    }
381}
382
383#[cfg(feature = "java_string")]
384impl<Q: ?Sized> AsBorrowed<java_string::JavaString> for Q
385where
386    for<'a> &'a Q: Into<&'a java_string::JavaStr>,
387{
388    type Borrowed = java_string::JavaStr;
389
390    fn as_borrowed(&self) -> &Self::Borrowed {
391        self.into()
392    }
393}
394
395#[cfg(feature = "java_string")]
396impl<Q: ?Sized> AsBorrowed<Cow<'_, java_string::JavaStr>> for Q
397where
398    for<'a> &'a Q: Into<&'a java_string::JavaStr>,
399{
400    type Borrowed = java_string::JavaStr;
401
402    fn as_borrowed(&self) -> &Self::Borrowed {
403        self.into()
404    }
405}
406
407impl<S> Extend<(S, Value<S>)> for Compound<S>
408where
409    S: Ord + Hash,
410{
411    fn extend<T>(&mut self, iter: T)
412    where
413        T: IntoIterator<Item = (S, Value<S>)>,
414    {
415        self.map.extend(iter)
416    }
417}
418
419impl<S> FromIterator<(S, Value<S>)> for Compound<S>
420where
421    S: Ord + Hash,
422{
423    fn from_iter<T>(iter: T) -> Self
424    where
425        T: IntoIterator<Item = (S, Value<S>)>,
426    {
427        Self {
428            map: Map::from_iter(iter),
429        }
430    }
431}
432
433pub enum Entry<'a, S = String> {
434    Vacant(VacantEntry<'a, S>),
435    Occupied(OccupiedEntry<'a, S>),
436}
437
438impl<'a, S> Entry<'a, S>
439where
440    S: Hash + Ord,
441{
442    pub fn key(&self) -> &S {
443        match self {
444            Entry::Vacant(ve) => ve.key(),
445            Entry::Occupied(oe) => oe.key(),
446        }
447    }
448
449    pub fn or_insert<V: Into<Value<S>>>(self, default: V) -> &'a mut Value<S> {
450        match self {
451            Entry::Vacant(ve) => ve.insert(default),
452            Entry::Occupied(oe) => oe.into_mut(),
453        }
454    }
455
456    pub fn or_insert_with<F, V>(self, default: F) -> &'a mut Value<S>
457    where
458        F: FnOnce() -> V,
459        V: Into<Value<S>>,
460    {
461        match self {
462            Entry::Vacant(ve) => ve.insert(default()),
463            Entry::Occupied(oe) => oe.into_mut(),
464        }
465    }
466
467    pub fn and_modify<F>(self, f: F) -> Self
468    where
469        F: FnOnce(&mut Value<S>),
470    {
471        match self {
472            Entry::Vacant(ve) => Entry::Vacant(ve),
473            Entry::Occupied(mut oe) => {
474                f(oe.get_mut());
475                Entry::Occupied(oe)
476            }
477        }
478    }
479}
480
481impl<S> fmt::Debug for Entry<'_, S>
482where
483    S: fmt::Debug + Ord,
484{
485    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
486        match self {
487            Self::Vacant(entry) => f.debug_tuple("Vacant").field(entry).finish(),
488            Self::Occupied(entry) => f.debug_tuple("Occupied").field(entry).finish(),
489        }
490    }
491}
492
493pub struct VacantEntry<'a, S = String> {
494    #[cfg(not(feature = "preserve_order"))]
495    entry: std::collections::btree_map::VacantEntry<'a, S, Value<S>>,
496    #[cfg(feature = "preserve_order")]
497    entry: indexmap::map::VacantEntry<'a, S, Value<S>>,
498}
499
500impl<'a, S> VacantEntry<'a, S>
501where
502    S: Ord + Hash,
503{
504    pub fn key(&self) -> &S {
505        self.entry.key()
506    }
507
508    pub fn insert<V: Into<Value<S>>>(self, v: V) -> &'a mut Value<S> {
509        self.entry.insert(v.into())
510    }
511}
512
513impl<S> fmt::Debug for VacantEntry<'_, S>
514where
515    S: fmt::Debug + Ord,
516{
517    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
518        f.debug_struct("VacantEntry")
519            .field("entry", &self.entry)
520            .finish()
521    }
522}
523
524pub struct OccupiedEntry<'a, S = String> {
525    #[cfg(not(feature = "preserve_order"))]
526    entry: std::collections::btree_map::OccupiedEntry<'a, S, Value<S>>,
527    #[cfg(feature = "preserve_order")]
528    entry: indexmap::map::OccupiedEntry<'a, S, Value<S>>,
529}
530
531impl<'a, S> OccupiedEntry<'a, S>
532where
533    S: Hash + Ord,
534{
535    pub fn key(&self) -> &S {
536        self.entry.key()
537    }
538
539    pub fn get(&self) -> &Value<S> {
540        self.entry.get()
541    }
542
543    pub fn get_mut(&mut self) -> &mut Value<S> {
544        self.entry.get_mut()
545    }
546
547    pub fn into_mut(self) -> &'a mut Value<S> {
548        self.entry.into_mut()
549    }
550
551    pub fn insert<V: Into<Value<S>>>(&mut self, v: V) -> Value<S> {
552        self.entry.insert(v.into())
553    }
554
555    pub fn remove(self) -> Value<S> {
556        #[cfg(feature = "preserve_order")]
557        return self.swap_remove();
558        #[cfg(not(feature = "preserve_order"))]
559        return self.entry.remove();
560    }
561
562    #[cfg(feature = "preserve_order")]
563    pub fn swap_remove(self) -> Value<S> {
564        self.entry.swap_remove()
565    }
566
567    #[cfg(feature = "preserve_order")]
568    pub fn shift_remove(self) -> Value<S> {
569        self.entry.shift_remove()
570    }
571}
572
573impl<S> fmt::Debug for OccupiedEntry<'_, S>
574where
575    S: fmt::Debug + Ord,
576{
577    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
578        f.debug_struct("OccupiedEntry")
579            .field("entry", &self.entry)
580            .finish()
581    }
582}
583
584impl<S, Q> Index<&'_ Q> for Compound<S>
585where
586    S: Borrow<Q> + Ord + Hash,
587    Q: ?Sized + Ord + Hash,
588{
589    type Output = Value<S>;
590
591    fn index(&self, index: &Q) -> &Self::Output {
592        self.map.index(index)
593    }
594}
595
596impl<S, Q> IndexMut<&'_ Q> for Compound<S>
597where
598    S: Borrow<Q> + Hash + Ord,
599    Q: ?Sized + Ord + Hash,
600{
601    fn index_mut(&mut self, index: &Q) -> &mut Self::Output {
602        self.map.get_mut(index).expect("no entry found for key")
603    }
604}
605
606macro_rules! impl_iterator_traits {
607    (($name:ident $($generics:tt)*) => $item:ty) => {
608        impl $($generics)* Iterator for $name $($generics)* {
609            type Item = $item;
610            #[inline]
611            fn next(&mut self) -> Option<Self::Item> {
612                self.iter.next()
613            }
614            #[inline]
615            fn size_hint(&self) -> (usize, Option<usize>) {
616                self.iter.size_hint()
617            }
618        }
619
620        #[cfg(feature = "preserve_order")]
621        impl $($generics)* DoubleEndedIterator for $name $($generics)* {
622            #[inline]
623            fn next_back(&mut self) -> Option<Self::Item> {
624                self.iter.next_back()
625            }
626        }
627
628        impl $($generics)* ExactSizeIterator for $name $($generics)* {
629            #[inline]
630            fn len(&self) -> usize {
631                self.iter.len()
632            }
633        }
634
635        impl $($generics)* FusedIterator for $name $($generics)* {}
636    }
637}
638
639impl<'a, S> IntoIterator for &'a Compound<S> {
640    type Item = (&'a S, &'a Value<S>);
641    type IntoIter = Iter<'a, S>;
642
643    fn into_iter(self) -> Self::IntoIter {
644        Iter {
645            iter: self.map.iter(),
646        }
647    }
648}
649
650#[derive(Clone, Debug)]
651pub struct Iter<'a, S = String> {
652    #[cfg(not(feature = "preserve_order"))]
653    iter: std::collections::btree_map::Iter<'a, S, Value<S>>,
654    #[cfg(feature = "preserve_order")]
655    iter: indexmap::map::Iter<'a, S, Value<S>>,
656}
657
658impl_iterator_traits!((Iter<'a, S>) => (&'a S, &'a Value<S>));
659
660impl<'a, S> IntoIterator for &'a mut Compound<S> {
661    type Item = (&'a S, &'a mut Value<S>);
662    type IntoIter = IterMut<'a, S>;
663
664    fn into_iter(self) -> Self::IntoIter {
665        IterMut {
666            iter: self.map.iter_mut(),
667        }
668    }
669}
670
671#[derive(Debug)]
672pub struct IterMut<'a, S = String> {
673    #[cfg(not(feature = "preserve_order"))]
674    iter: std::collections::btree_map::IterMut<'a, S, Value<S>>,
675    #[cfg(feature = "preserve_order")]
676    iter: indexmap::map::IterMut<'a, S, Value<S>>,
677}
678
679impl_iterator_traits!((IterMut<'a, S>) => (&'a S, &'a mut Value<S>));
680
681impl<S> IntoIterator for Compound<S> {
682    type Item = (S, Value<S>);
683    type IntoIter = IntoIter<S>;
684
685    fn into_iter(self) -> Self::IntoIter {
686        IntoIter {
687            iter: self.map.into_iter(),
688        }
689    }
690}
691
692#[derive(Debug)]
693pub struct IntoIter<S = String> {
694    #[cfg(not(feature = "preserve_order"))]
695    iter: std::collections::btree_map::IntoIter<S, Value<S>>,
696    #[cfg(feature = "preserve_order")]
697    iter: indexmap::map::IntoIter<S, Value<S>>,
698}
699
700impl_iterator_traits!((IntoIter<S>) => (S, Value<S>));
701
702#[derive(Clone, Debug)]
703pub struct Keys<'a, S = String> {
704    #[cfg(not(feature = "preserve_order"))]
705    iter: std::collections::btree_map::Keys<'a, S, Value<S>>,
706    #[cfg(feature = "preserve_order")]
707    iter: indexmap::map::Keys<'a, S, Value<S>>,
708}
709
710impl_iterator_traits!((Keys<'a, S>) => &'a S);
711
712#[derive(Clone, Debug)]
713pub struct Values<'a, S = String> {
714    #[cfg(not(feature = "preserve_order"))]
715    iter: std::collections::btree_map::Values<'a, S, Value<S>>,
716    #[cfg(feature = "preserve_order")]
717    iter: indexmap::map::Values<'a, S, Value<S>>,
718}
719
720impl_iterator_traits!((Values<'a, S>) => &'a Value<S>);
721
722#[derive(Debug)]
723pub struct ValuesMut<'a, S = String> {
724    #[cfg(not(feature = "preserve_order"))]
725    iter: std::collections::btree_map::ValuesMut<'a, S, Value<S>>,
726    #[cfg(feature = "preserve_order")]
727    iter: indexmap::map::ValuesMut<'a, S, Value<S>>,
728}
729
730impl_iterator_traits!((ValuesMut<'a, S>) => &'a mut Value<S>);
731
732#[cfg(test)]
733mod tests {
734    #[cfg(feature = "preserve_order")]
735    #[test]
736    fn compound_preserves_order() {
737        use super::*;
738
739        let letters = ["g", "b", "d", "e", "h", "z", "m", "a", "q"];
740
741        let mut c = Compound::<String>::new();
742        for l in letters {
743            c.insert(l, 0_i8);
744        }
745
746        for (k, l) in c.keys().zip(letters) {
747            assert_eq!(k, l);
748        }
749    }
750}