valuable/
named_values.rs

1use core::iter::{self, FusedIterator};
2
3use crate::field::*;
4use crate::*;
5
6/// Set of values from a `Structable` or `Enumerable` with named fields.
7#[derive(Debug)]
8pub struct NamedValues<'a> {
9    fields: &'a [NamedField<'a>],
10    values: &'a [Value<'a>],
11}
12
13impl<'a> NamedValues<'a> {
14    /// Create a new `NamedValues` instance.
15    ///
16    /// Both `fields` and `values` must be the same length.
17    ///
18    /// # Panics
19    ///
20    /// The method panics if `fields` and `values` are different lengths.
21    ///
22    /// # Examples
23    ///
24    /// ```
25    /// use valuable::{NamedField, NamedValues, Value};
26    ///
27    /// let fields = [
28    ///     NamedField::new("foo"),
29    ///     NamedField::new("bar")
30    /// ];
31    /// let values = [
32    ///     Value::U32(123),
33    ///     Value::U32(456),
34    /// ];
35    ///
36    /// let named_values = NamedValues::new(&fields, &values);
37    ///
38    /// assert_eq!(
39    ///     named_values.get(&fields[0]).unwrap().as_u32(),
40    ///     Some(123));
41    /// ```
42    pub fn new(fields: &'a [NamedField<'a>], values: &'a [Value<'a>]) -> NamedValues<'a> {
43        assert!(
44            fields.len() == values.len(),
45            "`fields` and `values` must be the same length"
46        );
47        NamedValues { fields, values }
48    }
49
50    /// Get a value using a `NamedField` reference.
51    ///
52    /// # Examples
53    ///
54    /// ```
55    /// use valuable::{NamedField, NamedValues, Value};
56    ///
57    /// let fields = [
58    ///     NamedField::new("foo"),
59    ///     NamedField::new("bar")
60    /// ];
61    /// let values = [
62    ///     Value::U32(123),
63    ///     Value::U32(456),
64    /// ];
65    ///
66    /// let named_values = NamedValues::new(&fields, &values);
67    ///
68    /// assert_eq!(
69    ///     named_values.get(&fields[0]).unwrap().as_u32(),
70    ///     Some(123));
71    /// ```
72    pub fn get(&self, field: &NamedField<'_>) -> Option<&Value<'_>> {
73        use core::mem;
74
75        let idx = (field as *const _ as usize - &self.fields[0] as *const _ as usize)
76            / mem::size_of::<NamedField<'_>>();
77        self.values.get(idx)
78    }
79
80    /// Get a value using string.
81    ///
82    /// # Examples
83    ///
84    /// ```
85    /// use valuable::{NamedField, NamedValues, Value};
86    ///
87    /// let fields = [
88    ///     NamedField::new("foo"),
89    ///     NamedField::new("bar")
90    /// ];
91    /// let values = [
92    ///     Value::U32(123),
93    ///     Value::U32(456),
94    /// ];
95    ///
96    /// let named_values = NamedValues::new(&fields, &values);
97    ///
98    /// assert_eq!(
99    ///     named_values.get_by_name("foo").unwrap().as_u32(),
100    ///     Some(123));
101    /// ```
102    pub fn get_by_name(&self, name: impl AsRef<str>) -> Option<&Value<'_>> {
103        let name = name.as_ref();
104
105        for (index, field) in self.fields.iter().enumerate() {
106            if field.name() == name {
107                return Some(&self.values[index]);
108            }
109        }
110
111        None
112    }
113
114    /// Iterate all name-value pairs.
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// use valuable::{NamedField, NamedValues, Value};
120    ///
121    /// let fields = [
122    ///     NamedField::new("foo"),
123    ///     NamedField::new("bar")
124    /// ];
125    /// let values = [
126    ///     Value::U32(123),
127    ///     Value::U32(456),
128    /// ];
129    ///
130    /// let named_values = NamedValues::new(&fields, &values);
131    ///
132    /// for (field, value) in named_values.iter() {
133    ///     println!("{:?}: {:?}", field, value);
134    /// }
135    /// ```
136    pub fn iter<'b>(&'b self) -> Iter<'a, 'b> {
137        Iter {
138            iter: self.fields.iter().enumerate(),
139            values: self.values,
140        }
141    }
142
143    /// Returns the length of fields.
144    pub fn len(&self) -> usize {
145        self.fields.len()
146    }
147
148    /// Returns `true` if fields have a length of 0.
149    pub fn is_empty(&self) -> bool {
150        self.fields.is_empty()
151    }
152}
153
154impl<'a, 'b> IntoIterator for &'b NamedValues<'a> {
155    type Item = (&'b NamedField<'a>, &'b Value<'a>);
156    type IntoIter = Iter<'a, 'b>;
157
158    fn into_iter(self) -> Self::IntoIter {
159        self.iter()
160    }
161}
162
163/// An iterator of name-value pairs contained by [`NamedValues`].
164///
165/// Instances are created by the [`iter()`][NamedValues::iter] method on
166/// [`NamedValues`]. See its documentation for more.
167///
168/// # Examples
169///
170/// ```
171/// use valuable::{NamedField, NamedValues, Value};
172///
173/// let fields = [
174///     NamedField::new("foo"),
175///     NamedField::new("bar")
176/// ];
177/// let values = [
178///     Value::U32(123),
179///     Value::U32(456),
180/// ];
181///
182/// let named_values = NamedValues::new(&fields, &values);
183///
184/// for (field, value) in named_values.iter() {
185///     println!("{:?}: {:?}", field, value);
186/// }
187/// ```
188#[derive(Debug)]
189pub struct Iter<'a, 'b> {
190    iter: iter::Enumerate<core::slice::Iter<'b, NamedField<'a>>>,
191    values: &'a [Value<'a>],
192}
193
194impl<'a, 'b> Iterator for Iter<'a, 'b> {
195    type Item = (&'b NamedField<'a>, &'b Value<'a>);
196
197    fn next(&mut self) -> Option<Self::Item> {
198        self.iter
199            .next()
200            .map(move |(i, field)| (field, &self.values[i]))
201    }
202
203    fn size_hint(&self) -> (usize, Option<usize>) {
204        self.iter.size_hint()
205    }
206}
207
208impl DoubleEndedIterator for Iter<'_, '_> {
209    fn next_back(&mut self) -> Option<Self::Item> {
210        self.iter
211            .next_back()
212            .map(move |(i, field)| (field, &self.values[i]))
213    }
214}
215
216impl ExactSizeIterator for Iter<'_, '_> {
217    fn len(&self) -> usize {
218        self.iter.len()
219    }
220}
221
222impl FusedIterator for Iter<'_, '_> {}