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<'_, '_> {}