nu_protocol/value/
record.rs

1//! Our insertion ordered map-type [`Record`]
2use std::{iter::FusedIterator, ops::RangeBounds};
3
4use crate::{ShellError, Span, Value};
5
6use serde::{de::Visitor, ser::SerializeMap, Deserialize, Serialize};
7
8#[derive(Debug, Clone, Default)]
9pub struct Record {
10    inner: Vec<(String, Value)>,
11}
12
13impl Record {
14    pub fn new() -> Self {
15        Self::default()
16    }
17
18    pub fn with_capacity(capacity: usize) -> Self {
19        Self {
20            inner: Vec::with_capacity(capacity),
21        }
22    }
23
24    /// Create a [`Record`] from a `Vec` of columns and a `Vec` of [`Value`]s
25    ///
26    /// Returns an error if `cols` and `vals` have different lengths.
27    ///
28    /// For perf reasons, this will not validate the rest of the record assumptions:
29    /// - unique keys
30    pub fn from_raw_cols_vals(
31        cols: Vec<String>,
32        vals: Vec<Value>,
33        input_span: Span,
34        creation_site_span: Span,
35    ) -> Result<Self, ShellError> {
36        if cols.len() == vals.len() {
37            let inner = cols.into_iter().zip(vals).collect();
38            Ok(Self { inner })
39        } else {
40            Err(ShellError::RecordColsValsMismatch {
41                bad_value: input_span,
42                creation_site: creation_site_span,
43            })
44        }
45    }
46
47    pub fn iter(&self) -> Iter {
48        self.into_iter()
49    }
50
51    pub fn iter_mut(&mut self) -> IterMut {
52        self.into_iter()
53    }
54
55    pub fn is_empty(&self) -> bool {
56        self.inner.is_empty()
57    }
58
59    pub fn len(&self) -> usize {
60        self.inner.len()
61    }
62
63    /// Naive push to the end of the datastructure.
64    ///
65    /// May duplicate data!
66    ///
67    /// Consider to use [`Record::insert`] instead
68    pub fn push(&mut self, col: impl Into<String>, val: Value) {
69        self.inner.push((col.into(), val));
70    }
71
72    /// Insert into the record, replacing preexisting value if found.
73    ///
74    /// Returns `Some(previous_value)` if found. Else `None`
75    pub fn insert<K>(&mut self, col: K, val: Value) -> Option<Value>
76    where
77        K: AsRef<str> + Into<String>,
78    {
79        if let Some(curr_val) = self.get_mut(&col) {
80            Some(std::mem::replace(curr_val, val))
81        } else {
82            self.push(col, val);
83            None
84        }
85    }
86
87    pub fn contains(&self, col: impl AsRef<str>) -> bool {
88        self.columns().any(|k| k == col.as_ref())
89    }
90
91    pub fn index_of(&self, col: impl AsRef<str>) -> Option<usize> {
92        self.columns().position(|k| k == col.as_ref())
93    }
94
95    pub fn get(&self, col: impl AsRef<str>) -> Option<&Value> {
96        self.inner
97            .iter()
98            .find_map(|(k, v)| if k == col.as_ref() { Some(v) } else { None })
99    }
100
101    pub fn get_mut(&mut self, col: impl AsRef<str>) -> Option<&mut Value> {
102        self.inner
103            .iter_mut()
104            .find_map(|(k, v)| if k == col.as_ref() { Some(v) } else { None })
105    }
106
107    pub fn get_index(&self, idx: usize) -> Option<(&String, &Value)> {
108        self.inner.get(idx).map(|(col, val): &(_, _)| (col, val))
109    }
110
111    /// Remove single value by key
112    ///
113    /// Returns `None` if key not found
114    ///
115    /// Note: makes strong assumption that keys are unique
116    pub fn remove(&mut self, col: impl AsRef<str>) -> Option<Value> {
117        let idx = self.index_of(col)?;
118        let (_, val) = self.inner.remove(idx);
119        Some(val)
120    }
121
122    /// Remove elements in-place that do not satisfy `keep`
123    ///
124    /// ```rust
125    /// use nu_protocol::{record, Value};
126    ///
127    /// let mut rec = record!(
128    ///     "a" => Value::test_nothing(),
129    ///     "b" => Value::test_int(42),
130    ///     "c" => Value::test_nothing(),
131    ///     "d" => Value::test_int(42),
132    /// );
133    /// rec.retain(|_k, val| !val.is_nothing());
134    /// let mut iter_rec = rec.columns();
135    /// assert_eq!(iter_rec.next().map(String::as_str), Some("b"));
136    /// assert_eq!(iter_rec.next().map(String::as_str), Some("d"));
137    /// assert_eq!(iter_rec.next(), None);
138    /// ```
139    pub fn retain<F>(&mut self, mut keep: F)
140    where
141        F: FnMut(&str, &Value) -> bool,
142    {
143        self.retain_mut(|k, v| keep(k, v));
144    }
145
146    /// Remove elements in-place that do not satisfy `keep` while allowing mutation of the value.
147    ///
148    /// This can for example be used to recursively prune nested records.
149    ///
150    /// ```rust
151    /// use nu_protocol::{record, Record, Value};
152    ///
153    /// fn remove_foo_recursively(val: &mut Value) {
154    ///     if let Value::Record {val, ..} = val {
155    ///         val.to_mut().retain_mut(keep_non_foo);
156    ///     }
157    /// }
158    ///
159    /// fn keep_non_foo(k: &str, v: &mut Value) -> bool {
160    ///     if k == "foo" {
161    ///         return false;
162    ///     }
163    ///     remove_foo_recursively(v);
164    ///     true
165    /// }
166    ///
167    /// let mut test = Value::test_record(record!(
168    ///     "foo" => Value::test_nothing(),
169    ///     "bar" => Value::test_record(record!(
170    ///         "foo" => Value::test_nothing(),
171    ///         "baz" => Value::test_nothing(),
172    ///         ))
173    ///     ));
174    ///
175    /// remove_foo_recursively(&mut test);
176    /// let expected = Value::test_record(record!(
177    ///     "bar" => Value::test_record(record!(
178    ///         "baz" => Value::test_nothing(),
179    ///         ))
180    ///     ));
181    /// assert_eq!(test, expected);
182    /// ```
183    pub fn retain_mut<F>(&mut self, mut keep: F)
184    where
185        F: FnMut(&str, &mut Value) -> bool,
186    {
187        self.inner.retain_mut(|(col, val)| keep(col, val));
188    }
189
190    /// Truncate record to the first `len` elements.
191    ///
192    /// `len > self.len()` will be ignored
193    ///
194    /// ```rust
195    /// use nu_protocol::{record, Value};
196    ///
197    /// let mut rec = record!(
198    ///     "a" => Value::test_nothing(),
199    ///     "b" => Value::test_int(42),
200    ///     "c" => Value::test_nothing(),
201    ///     "d" => Value::test_int(42),
202    /// );
203    /// rec.truncate(42); // this is fine
204    /// assert_eq!(rec.columns().map(String::as_str).collect::<String>(), "abcd");
205    /// rec.truncate(2); // truncate
206    /// assert_eq!(rec.columns().map(String::as_str).collect::<String>(), "ab");
207    /// rec.truncate(0); // clear the record
208    /// assert_eq!(rec.len(), 0);
209    /// ```
210    pub fn truncate(&mut self, len: usize) {
211        self.inner.truncate(len);
212    }
213
214    pub fn columns(&self) -> Columns {
215        Columns {
216            iter: self.inner.iter(),
217        }
218    }
219
220    pub fn into_columns(self) -> IntoColumns {
221        IntoColumns {
222            iter: self.inner.into_iter(),
223        }
224    }
225
226    pub fn values(&self) -> Values {
227        Values {
228            iter: self.inner.iter(),
229        }
230    }
231
232    pub fn into_values(self) -> IntoValues {
233        IntoValues {
234            iter: self.inner.into_iter(),
235        }
236    }
237
238    /// Obtain an iterator to remove elements in `range`
239    ///
240    /// Elements not consumed from the iterator will be dropped
241    ///
242    /// ```rust
243    /// use nu_protocol::{record, Value};
244    ///
245    /// let mut rec = record!(
246    ///     "a" => Value::test_nothing(),
247    ///     "b" => Value::test_int(42),
248    ///     "c" => Value::test_string("foo"),
249    /// );
250    /// {
251    ///     let mut drainer = rec.drain(1..);
252    ///     assert_eq!(drainer.next(), Some(("b".into(), Value::test_int(42))));
253    ///     // Dropping the `Drain`
254    /// }
255    /// let mut rec_iter = rec.into_iter();
256    /// assert_eq!(rec_iter.next(), Some(("a".into(), Value::test_nothing())));
257    /// assert_eq!(rec_iter.next(), None);
258    /// ```
259    pub fn drain<R>(&mut self, range: R) -> Drain
260    where
261        R: RangeBounds<usize> + Clone,
262    {
263        Drain {
264            iter: self.inner.drain(range),
265        }
266    }
267
268    /// Sort the record by its columns.
269    ///
270    /// ```rust
271    /// use nu_protocol::{record, Value};
272    ///
273    /// let mut rec = record!(
274    ///     "c" => Value::test_string("foo"),
275    ///     "b" => Value::test_int(42),
276    ///     "a" => Value::test_nothing(),
277    /// );
278    ///
279    /// rec.sort_cols();
280    ///
281    /// assert_eq!(
282    ///     Value::test_record(rec),
283    ///     Value::test_record(record!(
284    ///         "a" => Value::test_nothing(),
285    ///         "b" => Value::test_int(42),
286    ///         "c" => Value::test_string("foo"),
287    ///     ))
288    /// );
289    /// ```
290    pub fn sort_cols(&mut self) {
291        self.inner.sort_by(|(k1, _), (k2, _)| k1.cmp(k2))
292    }
293}
294
295impl Serialize for Record {
296    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
297    where
298        S: serde::Serializer,
299    {
300        let mut map = serializer.serialize_map(Some(self.len()))?;
301        for (k, v) in self {
302            map.serialize_entry(k, v)?;
303        }
304        map.end()
305    }
306}
307
308impl<'de> Deserialize<'de> for Record {
309    /// Special deserialization implementation that turns a map-pattern into a [`Record`]
310    ///
311    /// Denies duplicate keys
312    ///
313    /// ```rust
314    /// use serde_json::{from_str, Result};
315    /// use nu_protocol::{Record, Value, record};
316    ///
317    /// // A `Record` in json is a Record with a packed `Value`
318    /// // The `Value` record has a single key indicating its type and the inner record describing
319    /// // its representation of value and the associated `Span`
320    /// let ok = r#"{"a": {"Int": {"val": 42, "span": {"start": 0, "end": 0}}},
321    ///              "b": {"Int": {"val": 37, "span": {"start": 0, "end": 0}}}}"#;
322    /// let ok_rec: Record = from_str(ok).unwrap();
323    /// assert_eq!(Value::test_record(ok_rec),
324    ///            Value::test_record(record!{"a" => Value::test_int(42),
325    ///                                       "b" => Value::test_int(37)}));
326    /// // A repeated key will lead to a deserialization error
327    /// let bad = r#"{"a": {"Int": {"val": 42, "span": {"start": 0, "end": 0}}},
328    ///               "a": {"Int": {"val": 37, "span": {"start": 0, "end": 0}}}}"#;
329    /// let bad_rec: Result<Record> = from_str(bad);
330    /// assert!(bad_rec.is_err());
331    /// ```
332    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
333    where
334        D: serde::Deserializer<'de>,
335    {
336        deserializer.deserialize_map(RecordVisitor)
337    }
338}
339
340struct RecordVisitor;
341
342impl<'de> Visitor<'de> for RecordVisitor {
343    type Value = Record;
344
345    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
346        formatter.write_str("a nushell `Record` mapping string keys/columns to nushell `Value`")
347    }
348
349    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
350    where
351        A: serde::de::MapAccess<'de>,
352    {
353        let mut record = Record::with_capacity(map.size_hint().unwrap_or(0));
354
355        while let Some((key, value)) = map.next_entry::<String, Value>()? {
356            if record.insert(key, value).is_some() {
357                return Err(serde::de::Error::custom(
358                    "invalid entry, duplicate keys are not allowed for `Record`",
359                ));
360            }
361        }
362
363        Ok(record)
364    }
365}
366
367impl FromIterator<(String, Value)> for Record {
368    fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> Self {
369        // TODO: should this check for duplicate keys/columns?
370        Self {
371            inner: iter.into_iter().collect(),
372        }
373    }
374}
375
376impl Extend<(String, Value)> for Record {
377    fn extend<T: IntoIterator<Item = (String, Value)>>(&mut self, iter: T) {
378        for (k, v) in iter {
379            // TODO: should this .insert with a check?
380            self.push(k, v)
381        }
382    }
383}
384
385pub struct IntoIter {
386    iter: std::vec::IntoIter<(String, Value)>,
387}
388
389impl Iterator for IntoIter {
390    type Item = (String, Value);
391
392    fn next(&mut self) -> Option<Self::Item> {
393        self.iter.next()
394    }
395
396    fn size_hint(&self) -> (usize, Option<usize>) {
397        self.iter.size_hint()
398    }
399}
400
401impl DoubleEndedIterator for IntoIter {
402    fn next_back(&mut self) -> Option<Self::Item> {
403        self.iter.next_back()
404    }
405}
406
407impl ExactSizeIterator for IntoIter {
408    fn len(&self) -> usize {
409        self.iter.len()
410    }
411}
412
413impl FusedIterator for IntoIter {}
414
415impl IntoIterator for Record {
416    type Item = (String, Value);
417
418    type IntoIter = IntoIter;
419
420    fn into_iter(self) -> Self::IntoIter {
421        IntoIter {
422            iter: self.inner.into_iter(),
423        }
424    }
425}
426
427pub struct Iter<'a> {
428    iter: std::slice::Iter<'a, (String, Value)>,
429}
430
431impl<'a> Iterator for Iter<'a> {
432    type Item = (&'a String, &'a Value);
433
434    fn next(&mut self) -> Option<Self::Item> {
435        self.iter.next().map(|(col, val): &(_, _)| (col, val))
436    }
437
438    fn size_hint(&self) -> (usize, Option<usize>) {
439        self.iter.size_hint()
440    }
441}
442
443impl DoubleEndedIterator for Iter<'_> {
444    fn next_back(&mut self) -> Option<Self::Item> {
445        self.iter.next_back().map(|(col, val): &(_, _)| (col, val))
446    }
447}
448
449impl ExactSizeIterator for Iter<'_> {
450    fn len(&self) -> usize {
451        self.iter.len()
452    }
453}
454
455impl FusedIterator for Iter<'_> {}
456
457impl<'a> IntoIterator for &'a Record {
458    type Item = (&'a String, &'a Value);
459
460    type IntoIter = Iter<'a>;
461
462    fn into_iter(self) -> Self::IntoIter {
463        Iter {
464            iter: self.inner.iter(),
465        }
466    }
467}
468
469pub struct IterMut<'a> {
470    iter: std::slice::IterMut<'a, (String, Value)>,
471}
472
473impl<'a> Iterator for IterMut<'a> {
474    type Item = (&'a String, &'a mut Value);
475
476    fn next(&mut self) -> Option<Self::Item> {
477        self.iter.next().map(|(col, val)| (&*col, val))
478    }
479
480    fn size_hint(&self) -> (usize, Option<usize>) {
481        self.iter.size_hint()
482    }
483}
484
485impl DoubleEndedIterator for IterMut<'_> {
486    fn next_back(&mut self) -> Option<Self::Item> {
487        self.iter.next_back().map(|(col, val)| (&*col, val))
488    }
489}
490
491impl ExactSizeIterator for IterMut<'_> {
492    fn len(&self) -> usize {
493        self.iter.len()
494    }
495}
496
497impl FusedIterator for IterMut<'_> {}
498
499impl<'a> IntoIterator for &'a mut Record {
500    type Item = (&'a String, &'a mut Value);
501
502    type IntoIter = IterMut<'a>;
503
504    fn into_iter(self) -> Self::IntoIter {
505        IterMut {
506            iter: self.inner.iter_mut(),
507        }
508    }
509}
510
511pub struct Columns<'a> {
512    iter: std::slice::Iter<'a, (String, Value)>,
513}
514
515impl<'a> Iterator for Columns<'a> {
516    type Item = &'a String;
517
518    fn next(&mut self) -> Option<Self::Item> {
519        self.iter.next().map(|(col, _)| col)
520    }
521
522    fn size_hint(&self) -> (usize, Option<usize>) {
523        self.iter.size_hint()
524    }
525}
526
527impl DoubleEndedIterator for Columns<'_> {
528    fn next_back(&mut self) -> Option<Self::Item> {
529        self.iter.next_back().map(|(col, _)| col)
530    }
531}
532
533impl ExactSizeIterator for Columns<'_> {
534    fn len(&self) -> usize {
535        self.iter.len()
536    }
537}
538
539impl FusedIterator for Columns<'_> {}
540
541pub struct IntoColumns {
542    iter: std::vec::IntoIter<(String, Value)>,
543}
544
545impl Iterator for IntoColumns {
546    type Item = String;
547
548    fn next(&mut self) -> Option<Self::Item> {
549        self.iter.next().map(|(col, _)| col)
550    }
551
552    fn size_hint(&self) -> (usize, Option<usize>) {
553        self.iter.size_hint()
554    }
555}
556
557impl DoubleEndedIterator for IntoColumns {
558    fn next_back(&mut self) -> Option<Self::Item> {
559        self.iter.next_back().map(|(col, _)| col)
560    }
561}
562
563impl ExactSizeIterator for IntoColumns {
564    fn len(&self) -> usize {
565        self.iter.len()
566    }
567}
568
569impl FusedIterator for IntoColumns {}
570
571pub struct Values<'a> {
572    iter: std::slice::Iter<'a, (String, Value)>,
573}
574
575impl<'a> Iterator for Values<'a> {
576    type Item = &'a Value;
577
578    fn next(&mut self) -> Option<Self::Item> {
579        self.iter.next().map(|(_, val)| val)
580    }
581
582    fn size_hint(&self) -> (usize, Option<usize>) {
583        self.iter.size_hint()
584    }
585}
586
587impl DoubleEndedIterator for Values<'_> {
588    fn next_back(&mut self) -> Option<Self::Item> {
589        self.iter.next_back().map(|(_, val)| val)
590    }
591}
592
593impl ExactSizeIterator for Values<'_> {
594    fn len(&self) -> usize {
595        self.iter.len()
596    }
597}
598
599impl FusedIterator for Values<'_> {}
600
601pub struct IntoValues {
602    iter: std::vec::IntoIter<(String, Value)>,
603}
604
605impl Iterator for IntoValues {
606    type Item = Value;
607
608    fn next(&mut self) -> Option<Self::Item> {
609        self.iter.next().map(|(_, val)| val)
610    }
611
612    fn size_hint(&self) -> (usize, Option<usize>) {
613        self.iter.size_hint()
614    }
615}
616
617impl DoubleEndedIterator for IntoValues {
618    fn next_back(&mut self) -> Option<Self::Item> {
619        self.iter.next_back().map(|(_, val)| val)
620    }
621}
622
623impl ExactSizeIterator for IntoValues {
624    fn len(&self) -> usize {
625        self.iter.len()
626    }
627}
628
629impl FusedIterator for IntoValues {}
630
631pub struct Drain<'a> {
632    iter: std::vec::Drain<'a, (String, Value)>,
633}
634
635impl Iterator for Drain<'_> {
636    type Item = (String, Value);
637
638    fn next(&mut self) -> Option<Self::Item> {
639        self.iter.next()
640    }
641
642    fn size_hint(&self) -> (usize, Option<usize>) {
643        self.iter.size_hint()
644    }
645}
646
647impl DoubleEndedIterator for Drain<'_> {
648    fn next_back(&mut self) -> Option<Self::Item> {
649        self.iter.next_back()
650    }
651}
652
653impl ExactSizeIterator for Drain<'_> {
654    fn len(&self) -> usize {
655        self.iter.len()
656    }
657}
658
659impl FusedIterator for Drain<'_> {}
660
661#[macro_export]
662macro_rules! record {
663    // The macro only compiles if the number of columns equals the number of values,
664    // so it's safe to call `unwrap` below.
665    {$($col:expr => $val:expr),+ $(,)?} => {
666        $crate::Record::from_raw_cols_vals(
667            ::std::vec![$($col.into(),)+],
668            ::std::vec![$($val,)+],
669            $crate::Span::unknown(),
670            $crate::Span::unknown(),
671        ).unwrap()
672    };
673    {} => {
674        $crate::Record::new()
675    };
676}