edtui_jagged/
traits.rs

1//! # Traits Module
2//!
3//! The `traits` module defines traits used by the `edtui_jagged` library for
4//! specific functionalities.
5use crate::{index::RowIndex, Index2, Jagged};
6
7/// A helper trait used for indexing operations of a jagged array.
8pub trait JaggedIndex<T> {
9    type Output: Sized;
10
11    fn get(self, array: &Jagged<T>) -> Option<&Self::Output>;
12    fn get_mut(self, array: &mut Jagged<T>) -> Option<&mut Self::Output>;
13}
14
15pub trait JaggedRemove<T> {
16    type Output: Sized;
17    fn remove(self, array: &mut Jagged<T>) -> Self::Output;
18}
19
20impl<T> JaggedIndex<T> for Index2 {
21    type Output = T;
22
23    fn get(self, array: &Jagged<T>) -> Option<&Self::Output> {
24        array.data.get(self.row).and_then(|line| line.get(self.col))
25    }
26
27    fn get_mut(self, array: &mut Jagged<T>) -> Option<&mut Self::Output> {
28        array
29            .data
30            .get_mut(self.row)
31            .and_then(|line| line.get_mut(self.col))
32    }
33}
34
35impl<T> JaggedRemove<T> for Index2 {
36    type Output = T;
37
38    fn remove(self, array: &mut Jagged<T>) -> Self::Output {
39        array.data[self.row].remove(self.col)
40    }
41}
42
43impl<T> JaggedIndex<T> for RowIndex {
44    type Output = Vec<T>;
45
46    fn get(self, array: &Jagged<T>) -> Option<&Self::Output> {
47        array.data.get(self.0)
48    }
49
50    fn get_mut(self, array: &mut Jagged<T>) -> Option<&mut Self::Output> {
51        array.data.get_mut(self.0)
52    }
53}
54
55impl<T> JaggedRemove<T> for RowIndex {
56    type Output = Vec<T>;
57
58    fn remove(self, array: &mut Jagged<T>) -> Self::Output {
59        array.data.remove(self.0)
60    }
61}
62
63/// A helper trait used for data operations of a jagged array.
64pub trait JaggedSlice<T> {
65    type Index: JaggedIndex<T>;
66    fn push_into(self, array: &mut Jagged<T>);
67    fn insert_into(self, index: Self::Index, array: &mut Jagged<T>);
68}
69
70/// An index representing a specific row in a jagged array.
71#[derive(Default, Debug, PartialEq, Eq)]
72pub struct RowSlice<T> {
73    data: Vec<T>,
74}
75
76impl<T> From<Vec<T>> for RowSlice<T> {
77    fn from(val: Vec<T>) -> Self {
78        Self::new(val)
79    }
80}
81
82impl<T> RowSlice<T> {
83    /// Instantiates a new `RowSlice` from a vector.
84    #[must_use]
85    pub fn new(data: Vec<T>) -> Self {
86        Self { data }
87    }
88}
89
90impl<T> JaggedSlice<T> for T {
91    type Index = Index2;
92
93    fn push_into(self, array: &mut Jagged<T>) {
94        if let Some(row) = array.get_mut(RowIndex::new(array.len().saturating_sub(1))) {
95            row.push(self);
96        }
97    }
98
99    fn insert_into(self, index: Self::Index, array: &mut Jagged<T>) {
100        if let Some(line) = array.get_mut(RowIndex::new(index.row)) {
101            line.insert(index.col, self);
102        }
103    }
104}
105
106impl<T> JaggedSlice<T> for RowSlice<T>
107// where
108//     T: std::fmt::Debug + Clone,
109{
110    type Index = RowIndex;
111
112    fn push_into(self, array: &mut Jagged<T>) {
113        array.data.push(self.data);
114    }
115
116    fn insert_into(self, index: Self::Index, array: &mut Jagged<T>) {
117        array.data.insert(index.0, self.data);
118    }
119}
120
121impl<T> JaggedSlice<T> for Vec<T> {
122    type Index = RowIndex;
123
124    fn push_into(self, array: &mut Jagged<T>) {
125        array.data.push(self);
126    }
127
128    fn insert_into(self, index: Self::Index, array: &mut Jagged<T>) {
129        array.data.insert(index.0, self);
130    }
131}
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136    fn test_data() -> Jagged<char> {
137        Jagged::<char>::from(
138            "Hello\n\
139            World",
140        )
141    }
142
143    #[test]
144    fn test_get_index() {
145        let data = test_data();
146        let index = Index2::new(0, 4);
147
148        assert_eq!(index.get(&data), Some(&'o'));
149    }
150
151    #[test]
152    fn test_get_row() {
153        let data = test_data();
154        let index = RowIndex::new(1);
155
156        assert_eq!(index.get(&data), Some(&vec!['W', 'o', 'r', 'l', 'd']));
157    }
158}