Skip to main content

agnes/
access.rs

1/*!
2Traits for accessing data within agnes data structures.
3
4The [DataIndex](trait.DataIndex.html) trait provides index-based access to a field's data as well
5as method which generates a [DataIterator](struct.DataIterator.html).
6*/
7use std::fmt::Debug;
8use std::marker::PhantomData;
9use std::rc::Rc;
10
11use error::*;
12use field::Value;
13use frame::Framed;
14
15/// Trait that provides access to values in a data field.
16pub trait DataIndex: Debug {
17    /// The data type contained within this field.
18    type DType;
19
20    /// Returns the data (possibly NA) at the specified index, if it exists.
21    fn get_datum(&self, idx: usize) -> Result<Value<&Self::DType>>;
22
23    /// Returns the length of this data field.
24    fn len(&self) -> usize;
25
26    /// Returns whether or not this field is empty.
27    fn is_empty(&self) -> bool {
28        self.len() == 0
29    }
30
31    /// Returns an iterator over the values in this field.
32    fn iter(&self) -> DataIterator<Self::DType>
33    where
34        Self: Sized,
35    {
36        DataIterator::new(self)
37    }
38
39    /// Returns a new `DataIndex`-implementing object which provides access to the values in this
40    /// field as permuted by `permutation`. `permutation` is a slice of indices into this
41    /// `DataIndex`.
42    fn permute(self, permutation: &[usize]) -> Framed<Self::DType, Self>
43    where
44        Self: Sized,
45    {
46        Framed::new(Rc::new(permutation.to_vec().into()), self)
47    }
48
49    /// Copies existing values in this field into a new `Vec`.
50    ///
51    /// If this field has missing values, this method will return a vector of length less than that
52    /// returned by the `len` method.
53    fn to_vec(&self) -> Vec<Self::DType>
54    where
55        Self: Sized,
56        Self::DType: Clone,
57    {
58        self.iter()
59            .filter_map(|value| match value {
60                Value::Exists(value) => Some(value.clone()),
61                Value::Na => None,
62            })
63            .collect()
64    }
65
66    /// Copies values (missing or existing) in this field into a new `Vec`.
67    fn to_value_vec(&self) -> Vec<Value<Self::DType>>
68    where
69        Self: Sized,
70        Self::DType: Clone,
71    {
72        self.iter().map(|value| value.cloned()).collect()
73    }
74}
75/// Trait that provides mutable access to values in a data field.
76pub trait DataIndexMut: DataIndex {
77    /// Add a value to this field.
78    fn push(&mut self, value: Value<Self::DType>);
79
80    /// Take the value at the specified index from this field, replacing it with an NA.
81    fn take_datum(&mut self, idx: usize) -> Result<Value<Self::DType>>
82    where
83        Self::DType: Default;
84
85    /// Returns a draining iterator of the vaules in this `DataIndexMut`.
86    fn drain(&mut self) -> DrainIterator<Self::DType>
87    where
88        Self: Sized,
89    {
90        DrainIterator::new(self)
91    }
92}
93
94/// Iterator over the data in a data structure that implement DataIndex.
95pub struct DataIterator<'a, T>
96where
97    T: 'a,
98{
99    data: &'a dyn DataIndex<DType = T>,
100    cur_idx: usize,
101    phantom: PhantomData<T>,
102}
103impl<'a, T> DataIterator<'a, T>
104where
105    T: 'a,
106{
107    /// Create a new `DataIterator` from a type that implements `DataIndex`.
108    pub fn new(data: &'a dyn DataIndex<DType = T>) -> DataIterator<'a, T> {
109        DataIterator {
110            data,
111            cur_idx: 0,
112            phantom: PhantomData,
113        }
114    }
115
116    /// Returns an iterator applying function `F` to the stored values (where they exist) to this
117    /// `DataIterator`. Equivalent to `iter.map(|x: Value<&'a T>| x.map(f))`.
118    pub fn map_existing<B, F>(self, f: F) -> ValueMap<'a, T, Self, F>
119    where
120        Self: Iterator<Item = Value<&'a T>>,
121        F: FnMut(&'a T) -> B,
122    {
123        ValueMap {
124            iter: self,
125            f,
126            _t: PhantomData,
127        }
128    }
129}
130
131impl<'a, T> Iterator for DataIterator<'a, T>
132where
133    T: 'a,
134{
135    type Item = Value<&'a T>;
136
137    fn next(&mut self) -> Option<Value<&'a T>> {
138        if self.cur_idx < self.data.len() {
139            let out = Some(self.data.get_datum(self.cur_idx).unwrap());
140            self.cur_idx += 1;
141            out
142        } else {
143            None
144        }
145    }
146}
147
148/// Mapping iterator applying function `F` to the data in a data structure that implement DataIndex.
149/// `T` is the data type held within this data structure, and `I` is the base iterator that is being
150/// mapped over.
151#[derive(Clone)]
152pub struct ValueMap<'a, T, I, F> {
153    iter: I,
154    f: F,
155    _t: PhantomData<&'a T>,
156}
157
158impl<'a, B, T, I, F> Iterator for ValueMap<'a, T, I, F>
159where
160    I: Iterator<Item = Value<&'a T>>,
161    F: FnMut(&'a T) -> B,
162{
163    type Item = Value<B>;
164
165    #[inline]
166    fn next(&mut self) -> Option<Value<B>> {
167        self.iter.next().map(|value| value.map(&mut self.f))
168    }
169}
170
171/// Draining iterator over the data in a data structure that implements DataIndex.
172pub struct DrainIterator<'a, T>
173where
174    T: 'a,
175{
176    data: &'a mut dyn DataIndexMut<DType = T>,
177    cur_idx: usize,
178    phantom: PhantomData<T>,
179}
180
181impl<'a, T> DrainIterator<'a, T>
182where
183    T: 'a,
184{
185    /// Create a new `DrainIterator` from a type that implements `DataIndex`.
186    pub fn new(data: &'a mut dyn DataIndexMut<DType = T>) -> DrainIterator<'a, T> {
187        DrainIterator {
188            data,
189            cur_idx: 0,
190            phantom: PhantomData,
191        }
192    }
193}
194
195impl<'a, T> Iterator for DrainIterator<'a, T>
196where
197    T: 'a + Default,
198{
199    type Item = Value<T>;
200
201    fn next(&mut self) -> Option<Value<T>> {
202        if self.cur_idx < self.data.len() {
203            let out = Some(self.data.take_datum(self.cur_idx).unwrap());
204            self.cur_idx += 1;
205            out
206        } else {
207            None
208        }
209    }
210}
211
212/// Trait to provide the number of rows of this data structure.
213pub trait NRows {
214    /// Return the number of rows in this data structure.
215    fn nrows(&self) -> usize;
216}
217impl<DI> NRows for DI
218where
219    DI: DataIndex,
220{
221    fn nrows(&self) -> usize {
222        self.len()
223    }
224}
225
226#[cfg(test)]
227mod tests {
228    use super::*;
229
230    use field::FieldData;
231
232    #[test]
233    fn convert() {
234        let field_data = FieldData::from_field_vec(vec![
235            Value::Exists(2u64),
236            Value::Exists(5),
237            Value::Na,
238            Value::Exists(1),
239            Value::Exists(8),
240        ]);
241        let new_field_data = field_data
242            .iter()
243            .map_existing(|u| *u as i64)
244            .collect::<FieldData<i64>>();
245        assert_eq!(
246            new_field_data.to_value_vec(),
247            vec![
248                Value::Exists(2i64),
249                Value::Exists(5),
250                Value::Na,
251                Value::Exists(1),
252                Value::Exists(8),
253            ]
254        );
255    }
256}