nu_protocol/value/
record.rs

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