wezterm_dynamic/
object.rs

1use crate::Value;
2use std::cmp::Ordering;
3use std::collections::BTreeMap;
4use std::ops::{Deref, DerefMut};
5
6/// We'd like to avoid allocating when resolving struct fields,
7/// so this is the borrowed version of Value.
8/// It's a bit involved to make this work; more details can be
9/// found in the excellent guide here:
10/// <https://github.com/sunshowers/borrow-complex-key-example/blob/master/src/lib.rs>
11#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq, Ord, PartialOrd)]
12pub enum BorrowedKey<'a> {
13    Value(&'a Value),
14    Str(&'a str),
15}
16
17pub trait ObjectKeyTrait {
18    fn key<'k>(&'k self) -> BorrowedKey<'k>;
19}
20
21impl ObjectKeyTrait for Value {
22    fn key<'k>(&'k self) -> BorrowedKey<'k> {
23        match self {
24            Value::String(s) => BorrowedKey::Str(s.as_str()),
25            v => BorrowedKey::Value(v),
26        }
27    }
28}
29
30impl<'a> ObjectKeyTrait for BorrowedKey<'a> {
31    fn key<'k>(&'k self) -> BorrowedKey<'k> {
32        *self
33    }
34}
35
36impl<'a> std::borrow::Borrow<dyn ObjectKeyTrait + 'a> for Value {
37    fn borrow(&self) -> &(dyn ObjectKeyTrait + 'a) {
38        self
39    }
40}
41
42impl<'a> PartialEq for (dyn ObjectKeyTrait + 'a) {
43    fn eq(&self, other: &Self) -> bool {
44        self.key().eq(&other.key())
45    }
46}
47
48impl<'a> Eq for (dyn ObjectKeyTrait + 'a) {}
49
50impl<'a> PartialOrd for (dyn ObjectKeyTrait + 'a) {
51    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
52        self.key().partial_cmp(&other.key())
53    }
54}
55
56impl<'a> Ord for (dyn ObjectKeyTrait + 'a) {
57    fn cmp(&self, other: &Self) -> Ordering {
58        self.key().cmp(&other.key())
59    }
60}
61
62impl<'a> std::hash::Hash for (dyn ObjectKeyTrait + 'a) {
63    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
64        self.key().hash(state)
65    }
66}
67
68#[derive(Clone, Default, PartialEq, Eq, Hash)]
69pub struct Object {
70    inner: BTreeMap<Value, Value>,
71}
72
73impl Object {
74    pub fn get_by_str(&self, field_name: &str) -> Option<&Value> {
75        self.inner
76            .get(&BorrowedKey::Str(field_name) as &dyn ObjectKeyTrait)
77    }
78}
79
80impl std::fmt::Debug for Object {
81    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
82        self.inner.fmt(fmt)
83    }
84}
85
86impl Ord for Object {
87    fn cmp(&self, other: &Self) -> Ordering {
88        let self_ptr = self as *const Self;
89        let other_ptr = other as *const Self;
90        self_ptr.cmp(&other_ptr)
91    }
92}
93
94impl PartialOrd for Object {
95    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
96        Some(self.cmp(other))
97    }
98}
99
100impl Drop for Object {
101    fn drop(&mut self) {
102        for (_, child) in std::mem::take(&mut self.inner) {
103            crate::drop::safely(child);
104        }
105    }
106}
107
108impl From<BTreeMap<Value, Value>> for Object {
109    fn from(inner: BTreeMap<Value, Value>) -> Self {
110        Self { inner }
111    }
112}
113
114impl Deref for Object {
115    type Target = BTreeMap<Value, Value>;
116
117    fn deref(&self) -> &Self::Target {
118        &self.inner
119    }
120}
121
122impl DerefMut for Object {
123    fn deref_mut(&mut self) -> &mut Self::Target {
124        &mut self.inner
125    }
126}
127
128fn take(object: Object) -> BTreeMap<Value, Value> {
129    let object = core::mem::ManuallyDrop::new(object);
130    unsafe { core::ptr::read(&object.inner) }
131}
132
133impl IntoIterator for Object {
134    type Item = (Value, Value);
135    type IntoIter = <BTreeMap<Value, Value> as IntoIterator>::IntoIter;
136
137    fn into_iter(self) -> Self::IntoIter {
138        take(self).into_iter()
139    }
140}
141
142impl<'a> IntoIterator for &'a Object {
143    type Item = (&'a Value, &'a Value);
144    type IntoIter = <&'a BTreeMap<Value, Value> as IntoIterator>::IntoIter;
145
146    fn into_iter(self) -> Self::IntoIter {
147        self.iter()
148    }
149}
150
151impl<'a> IntoIterator for &'a mut Object {
152    type Item = (&'a Value, &'a mut Value);
153    type IntoIter = <&'a mut BTreeMap<Value, Value> as IntoIterator>::IntoIter;
154
155    fn into_iter(self) -> Self::IntoIter {
156        self.iter_mut()
157    }
158}
159
160impl FromIterator<(Value, Value)> for Object {
161    fn from_iter<I>(iter: I) -> Self
162    where
163        I: IntoIterator<Item = (Value, Value)>,
164    {
165        Object {
166            inner: BTreeMap::from_iter(iter),
167        }
168    }
169}