catlog/zero/
row.rs

1//! Rows.
2
3use derivative::Derivative;
4use derive_more::From;
5use std::ops::Index;
6
7use indexmap::IndexMap;
8
9use super::qualified::{LabelSegment, NameSegment, label_seg, name_seg};
10use ustr::Ustr;
11
12/// An insertion-ordered map from `NameSegment` to `T`.
13///
14/// Also stores a "label" for each entry, which may not be the same as the
15/// NameSegment in the case that the NameSegment is a UUID.
16///
17/// This is called "row" because it's a short name, and it corresponds to the idea
18/// of a row in a database, which is a map from fields to values.
19///
20/// Create this using the [FromIterator] implementation.
21#[derive(Clone, Derivative, PartialEq, Eq, From)]
22#[derivative(Default(bound = ""))]
23pub struct Row<T>(IndexMap<NameSegment, (LabelSegment, T)>);
24
25impl<T> Index<NameSegment> for Row<T> {
26    type Output = T;
27    fn index(&self, index: NameSegment) -> &Self::Output {
28        self.get(index).unwrap()
29    }
30}
31
32impl<T> Row<T> {
33    /// Lookup the field `name` if it exists.
34    ///
35    /// Also see the [Index] implementation, which just `unwrap`s this.
36    pub fn get(&self, name: NameSegment) -> Option<&T> {
37        self.0.get(&name).map(|p| &p.1)
38    }
39
40    /// Lookup the field `name` by mutable reference.
41    pub fn get_mut(&mut self, name: NameSegment) -> Option<&mut T> {
42        self.0.get_mut(&name).map(|p| &mut p.1)
43    }
44
45    /// Lookup the field `name` if it exists, and get its value and label.
46    pub fn get_with_label(&self, name: NameSegment) -> Option<&(LabelSegment, T)> {
47        self.0.get(&name)
48    }
49
50    /// Iterate through the fields in insertion order.
51    pub fn iter(&self) -> impl Iterator<Item = (&NameSegment, &(LabelSegment, T))> {
52        self.0.iter()
53    }
54
55    /// Return the number of fields.
56    pub fn len(&self) -> usize {
57        self.0.len()
58    }
59
60    /// Return whether the row is empty.
61    pub fn is_empty(&self) -> bool {
62        self.0.is_empty()
63    }
64
65    /// Return whether the row contains the given field.
66    pub fn has(&self, field_name: NameSegment) -> bool {
67        self.0.contains_key(&field_name)
68    }
69
70    /// Construct the empty row.
71    pub fn empty() -> Self {
72        Self(IndexMap::new())
73    }
74
75    /// Map a function to produce a new row.
76    pub fn map<S>(&self, f: impl Fn(&T) -> S) -> Row<S> {
77        self.iter().map(|(name, (label, x))| (*name, (*label, f(x)))).collect()
78    }
79
80    ///  Insert a new field.
81    pub fn insert(&mut self, field: NameSegment, label: LabelSegment, value: T) {
82        self.0.insert(field, (label, value));
83    }
84}
85
86impl<T> FromIterator<(NameSegment, (LabelSegment, T))> for Row<T> {
87    fn from_iter<I: IntoIterator<Item = (NameSegment, (LabelSegment, T))>>(iter: I) -> Self {
88        Row(iter.into_iter().collect())
89    }
90}
91
92impl<S: Clone + Into<Ustr>, T> FromIterator<(S, T)> for Row<T> {
93    fn from_iter<I: IntoIterator<Item = (S, T)>>(iter: I) -> Self {
94        iter.into_iter()
95            .map(|(s, value)| (name_seg(s.clone()), (label_seg(s), value)))
96            .collect()
97    }
98}