Skip to main content

substrate_data/model/
borrowed.rs

1//! [`ValueRef`]: a value borrowed from where it was read — what schemas
2//! read. Decoded from the binary form ([`crate::binary::decode_ref`]) no
3//! string is copied: every one points into the bytes, and lists and maps
4//! are slices in an arena ([`Bump`]). An owned [`Value`] lends itself the
5//! same way ([`Value::borrow`]).
6
7use bumpalo::Bump;
8
9use crate::model::number::{int_to_f64, whole_to_i64};
10use crate::model::value::{KindName, Map, Ref, RefKey, Value, ValueKind};
11
12/// A borrowed [`Value`]: the same cases, strings `&'a str`, lists and maps slices.
13#[derive(Debug, Clone, Copy, PartialEq)]
14pub enum ValueRef<'a> {
15    /// Nothing.
16    Null,
17    /// `true` or `false`.
18    Bool(bool),
19    /// An integer.
20    Int(i64),
21    /// A number with a fraction or an exponent.
22    Float(f64),
23    /// A string, as spelled.
24    Str(&'a str),
25    /// A list, in the arena.
26    List(&'a [ValueRef<'a>]),
27    /// A map, in the arena.
28    Map(MapRef<'a>),
29    /// `@file:images/logo.png`: its kind checked, its id as written
30    /// (checked where it was read).
31    Ref {
32        /// Its kind.
33        kind: KindName,
34        /// Its id, as written.
35        id: &'a str,
36    },
37    /// Bytes as they are.
38    Bytes(&'a [u8]),
39}
40
41/// A borrowed map: entries in file order.
42#[derive(Debug, Clone, Copy, PartialEq, Default)]
43pub struct MapRef<'a>(pub &'a [(&'a str, ValueRef<'a>)]);
44
45impl<'a> MapRef<'a> {
46    /// The value of `key`.
47    #[must_use]
48    pub fn get(self, key: &str) -> Option<&'a ValueRef<'a>> {
49        self.0.iter().find(|(k, _)| *k == key).map(|(_, v)| v)
50    }
51
52    /// The entries, in order.
53    #[must_use = "an iterator does nothing until it is consumed"]
54    pub fn iter(self) -> impl ExactSizeIterator<Item = (&'a str, &'a ValueRef<'a>)> + 'a {
55        self.0.iter().map(|(k, v)| (*k, v))
56    }
57
58    /// The keys, in order.
59    #[must_use = "an iterator does nothing until it is consumed"]
60    pub fn keys(self) -> impl ExactSizeIterator<Item = &'a str> + 'a {
61        self.0.iter().map(|(k, _)| *k)
62    }
63
64    /// How many entries.
65    #[must_use]
66    pub fn len(self) -> usize {
67        self.0.len()
68    }
69
70    /// Whether it has no entries.
71    #[must_use]
72    pub fn is_empty(self) -> bool {
73        self.0.is_empty()
74    }
75}
76
77impl<'a> ValueRef<'a> {
78    /// Which case it is.
79    #[must_use]
80    pub fn kind(&self) -> ValueKind {
81        match self {
82            ValueRef::Null => ValueKind::Null,
83            ValueRef::Bool(_) => ValueKind::Bool,
84            ValueRef::Int(_) => ValueKind::Int,
85            ValueRef::Float(_) => ValueKind::Float,
86            ValueRef::Str(_) => ValueKind::Str,
87            ValueRef::List(_) => ValueKind::List,
88            ValueRef::Map(_) => ValueKind::Map,
89            ValueRef::Ref { .. } => ValueKind::Ref,
90            ValueRef::Bytes(_) => ValueKind::Bytes,
91        }
92    }
93
94    /// Whether it's null.
95    #[must_use]
96    pub fn is_null(&self) -> bool {
97        matches!(self, ValueRef::Null)
98    }
99
100    /// The bool, if it's one.
101    #[must_use]
102    pub fn as_bool(&self) -> Option<bool> {
103        match self {
104            ValueRef::Bool(b) => Some(*b),
105            _ => None,
106        }
107    }
108
109    /// The integer, if it's one (a float with no fraction is).
110    #[must_use]
111    pub fn as_i64(&self) -> Option<i64> {
112        match self {
113            ValueRef::Int(n) => Some(*n),
114            ValueRef::Float(f) => whole_to_i64(*f),
115            _ => None,
116        }
117    }
118
119    /// The number, if it's one.
120    #[must_use]
121    pub fn as_f64(&self) -> Option<f64> {
122        match self {
123            ValueRef::Int(n) => Some(int_to_f64(*n)),
124            ValueRef::Float(f) => Some(*f),
125            _ => None,
126        }
127    }
128
129    /// The string, if it's one.
130    #[must_use]
131    pub fn as_str(&self) -> Option<&'a str> {
132        match self {
133            ValueRef::Str(s) => Some(s),
134            _ => None,
135        }
136    }
137
138    /// The list, if it's one.
139    #[must_use]
140    pub fn as_list(&self) -> Option<&'a [ValueRef<'a>]> {
141        match self {
142            ValueRef::List(l) => Some(l),
143            _ => None,
144        }
145    }
146
147    /// The map, if it's one.
148    #[must_use]
149    pub fn as_map(&self) -> Option<MapRef<'a>> {
150        match self {
151            ValueRef::Map(m) => Some(*m),
152            _ => None,
153        }
154    }
155
156    /// `self[key]` of a map, `None` for anything else.
157    #[must_use]
158    pub fn get(&self, key: &str) -> Option<&'a ValueRef<'a>> {
159        self.as_map()?.get(key)
160    }
161
162    /// An owned copy.
163    #[must_use]
164    pub fn to_value(self) -> Value {
165        match self {
166            ValueRef::Null => Value::Null,
167            ValueRef::Bool(b) => Value::Bool(b),
168            ValueRef::Int(n) => Value::Int(n),
169            ValueRef::Float(f) => Value::Float(f),
170            ValueRef::Str(s) => Value::Str(s.to_string()),
171            ValueRef::List(l) => Value::List(l.iter().map(|v| v.to_value()).collect()),
172            ValueRef::Map(m) => {
173                let mut out = Map::with_capacity(m.len());
174                for (k, v) in m.iter() {
175                    out.insert(k, v.to_value());
176                }
177                Value::Map(out)
178            }
179            ValueRef::Ref { kind, id } => Value::Ref(Ref::new(kind, RefKey::spelled(id))),
180            ValueRef::Bytes(b) => Value::Bytes(b.to_vec()),
181        }
182    }
183
184    /// The reference of a `Ref`, owned.
185    #[must_use]
186    pub fn to_ref(self) -> Option<Ref> {
187        match self {
188            ValueRef::Ref { kind, id } => Some(Ref::new(kind, RefKey::spelled(id))),
189            _ => None,
190        }
191    }
192}
193
194impl Value {
195    /// This value, borrowed (lists and maps in `arena`) — what schemas read.
196    pub fn borrow<'a>(&'a self, arena: &'a Bump) -> ValueRef<'a> {
197        match self {
198            Value::Null => ValueRef::Null,
199            Value::Bool(b) => ValueRef::Bool(*b),
200            Value::Int(n) => ValueRef::Int(*n),
201            Value::Float(f) => ValueRef::Float(*f),
202            Value::Str(s) => ValueRef::Str(s),
203            Value::List(l) => {
204                ValueRef::List(arena.alloc_slice_fill_iter(l.iter().map(|v| v.borrow(arena))))
205            }
206            Value::Map(m) => ValueRef::Map(MapRef(
207                arena.alloc_slice_fill_iter(m.iter().map(|(k, v)| (k, v.borrow(arena)))),
208            )),
209            Value::Ref(r) => ValueRef::Ref {
210                kind: r.kind,
211                id: r.id.as_str(),
212            },
213            Value::Bytes(b) => ValueRef::Bytes(b),
214        }
215    }
216}