treeflection/
context_vec.rs

1use std::vec::Vec;
2use std::ops::{Deref, DerefMut};
3use serde::ser::{Serialize, Serializer};
4use serde::de::{Deserialize, DeserializeOwned, Deserializer};
5use serde_json;
6
7use crate::node::Node;
8use crate::node_runner::NodeRunner;
9use crate::node_token::NodeToken;
10
11#[derive(Clone, Default)]
12pub struct ContextVec<T> {
13    context: Vec<usize>,
14    vector:  Vec<T>,
15}
16
17/// The purpose of a ContextVec is to provide a way for commands to easily access relevant values.
18/// If we have a ContextVec named foo, the command `foo[?] get` will display the values in foo that the context points to.
19///
20/// # Contents
21///
22/// *   `vector: Vec<T>`
23/// *   `context: Vec<usize>`
24///
25/// # Invariants
26///
27/// *   the values in context will point to a valid value in vector
28/// *   the values in context will continue to point to the same value in vector (even after operations like insert and remove)
29
30impl<T> ContextVec<T> {
31    /// Create a new empty ContextVec
32    pub fn new() -> ContextVec<T> {
33        ContextVec {
34            context: vec!(),
35            vector:  vec!(),
36        }
37    }
38
39    /// Create a new ContextVec from a Vec
40    pub fn from_vec(vector: Vec<T>) -> ContextVec<T> {
41        ContextVec {
42            context: vec!(),
43            vector: vector,
44        }
45    }
46
47    /// Get the value currently pointed to by context
48    pub fn selection_first(&self) -> Option<&T> {
49        match self.context.first() {
50            Some (value) => {
51                self.vector.get(*value)
52            }
53            None => None
54        }
55    }
56
57    /// Mutably get the value currently pointed to by context
58    pub fn selection_first_mut(&mut self) -> Option<&mut T> {
59        match self.context.first() {
60            Some (value) => {
61                self.vector.get_mut(*value)
62            }
63            None => None
64        }
65    }
66
67    /// Get the values currently pointed to by context
68    pub fn selection(&self) -> Vec<&T> {
69        let mut result: Vec<&T> = vec!();
70        for i in &self.context {
71            result.push(&self.vector[*i]);
72        }
73        result
74    }
75
76    /// Get a slice of the context
77    pub fn get_context(&self) -> &[usize] {
78        &self.context
79    }
80
81    /// Consume the ContextVec into the context
82    pub fn into_context(self) -> Vec<usize> {
83        self.context
84    }
85
86    /// Consume the ContextVec into the vector
87    pub fn into_vector(self) -> Vec<T> {
88        self.vector
89    }
90
91    /// Consume the ContextVec into a tuple of the context and the vector
92    pub fn into_tuple(self) -> (Vec<usize>, Vec<T>) {
93        (self.context, self.vector)
94    }
95
96    /// Clears the context
97    pub fn clear_context(&mut self) {
98        self.context.clear();
99    }
100
101    /// Sets a new context
102    pub fn set_context(&mut self, value: usize) {
103        let length = self.vector.len();
104        if value >= length {
105            panic!(format!("Attempted to set context {} on a ContextVec of length {}", value, length));
106        }
107        self.context.clear();
108        self.context.push(value);
109    }
110
111    /// Sets a new context
112    pub fn set_context_vec(&mut self, mut values: Vec<usize>) {
113        self.context.clear();
114        let length = self.vector.len();
115        for value in values.drain(..) {
116            if value >= length {
117                panic!(format!("Attempted to set context {} on a ContextVec of length {}", value, length));
118            }
119            self.context.push(value);
120        }
121    }
122
123    /// Set to a new vector.
124    /// Clears the context.
125    pub fn set_vec(&mut self, vector: Vec<T>) {
126        self.context.clear();
127        self.vector = vector;
128    }
129
130    /// Clears the vector and the context
131    pub fn clear(&mut self) {
132        self.context.clear();
133        self.vector.clear();
134    }
135
136    /// Push a value to the end of the vector
137    pub fn push(&mut self, value: T) {
138        self.vector.push(value);
139    }
140
141    /// Insert a value into the vector.
142    /// Invalid context indices are updated.
143    pub fn insert(&mut self, index: usize, value: T) {
144        self.vector.insert(index, value);
145
146        for i in self.context.iter_mut() {
147            if *i >= index {
148                *i += 1;
149            }
150        }
151    }
152
153    /// Pop a value from the end of the vector.
154    /// If it succeeds invalid context indices are removed.
155    pub fn pop(&mut self) -> Option<T> {
156        match self.vector.pop() {
157            Some(value) => {
158                let len = self.vector.len();
159                self.context.retain(|&x| x < len);
160                Some(value)
161            }
162            None => {
163                None
164            }
165        }
166    }
167
168    /// Remove a value at the specified index.
169    /// Deletes any context indices pointing to the removed value.
170    /// Shifts all larger context indices down.
171    pub fn remove(&mut self, to_remove: usize) -> T {
172        let element = self.vector.remove(to_remove);
173        let mut new_context: Vec<usize> = vec!();
174        for i in self.context.drain(..) {
175            if i < to_remove {
176                new_context.push(i);
177            }
178            else if i > to_remove {
179                new_context.push(i-1);
180            }
181        }
182        self.context = new_context;
183        element
184    }
185}
186
187impl<T> Deref for ContextVec<T> {
188    type Target = [T];
189    fn deref(&self) -> &[T] {
190        &self.vector
191    }
192}
193
194impl<T> DerefMut for ContextVec<T> {
195    fn deref_mut(&mut self) -> &mut [T] {
196        &mut self.vector
197    }
198}
199
200impl<T> Node for ContextVec<T> where T: Node + Serialize + DeserializeOwned + Default {
201    fn node_step(&mut self, mut runner: NodeRunner) -> String {
202        match runner.step() {
203            NodeToken::ChainIndex (index) => {
204                let length = self.vector.len();
205                match self.vector.get_mut(index) {
206                    Some (item) => item.node_step(runner),
207                    None => {
208                        return match length {
209                             0 => format!("Used index {} on an empty vector", index),
210                             1 => format!("Used index {} on a vector of size 1 (try 0)", index),
211                             _ => format!("Used index {} on a vector of size {} (try a value between 0-{})", index, length, length-1)
212                        }
213                    }
214                }
215            }
216            NodeToken::ChainContext => {
217                let mut combined = String::from("|");
218                for i in self.context.iter() {
219                    match self.vector.get_mut(*i) {
220                        Some(ref mut node) => {
221                            let result = node.node_step(runner.clone());
222                            combined.push_str(result.as_str());
223                        }
224                        None => {
225                            combined.push_str("Context out of range. This should never happen.");
226                        }
227                    }
228                    combined.push('|');
229                }
230                combined
231            }
232            NodeToken::ChainAll => {
233                let mut combined = String::from("|");
234                for item in self.vector.iter_mut() {
235                    combined.push_str(item.node_step(runner.clone()).as_ref());
236                    combined.push('|');
237                }
238                combined
239            }
240            NodeToken::ChainProperty (ref s) if s == "length" => { self.vector.len().node_step(runner) }
241            NodeToken::Get => {
242                serde_json::to_string_pretty(&mut self.vector).unwrap()
243            }
244            NodeToken::Set(value) => {
245                match serde_json::from_str(&value) {
246                    Ok(result) => {
247                        self.vector = result;
248                        String::from("")
249                    }
250                    Err(err) => {
251                        format!("vector set error: {}", err)
252                    }
253                }
254            }
255            NodeToken::Insert => {
256                self.push(T::default());
257                String::new()
258            }
259            NodeToken::Remove => {
260                if let Some(_) = self.pop() {
261                    String::new()
262                } else {
263                    String::from("Tried to remove from an empty vector.")
264                }
265            }
266            NodeToken::InsertIndex (index) => {
267                let max_index = self.len();
268                if index > max_index {
269                    format!("Tried to insert at index {} on a vector of size {} (try a value between 0-{})", index, max_index, max_index)
270                }
271                else {
272                    self.insert(index, T::default());
273                    String::new()
274                }
275            }
276            NodeToken::RemoveIndex (index) => {
277                let max_index = self.len() - 1;
278                if index > max_index {
279                    format!("Tried to remove the value at index {} on a vector of size {} (try a value between 0-{})", index, self.len(), max_index)
280                }
281                else {
282                    self.remove(index);
283                    String::new()
284                }
285            }
286            NodeToken::SetDefault => {
287                self.vector = vec!();
288                String::new()
289            }
290            NodeToken::Help => {
291                String::from(r#"
292Context Vector Help
293
294Commands:
295*   help          - display this help
296*   get           - display JSON
297*   set           - set to JSON
298*   insert        - create a new element at the end of the vector
299*   insert $INDEX - create a new element at $INDEX
300*   remove        - remove the element at the end of the vector
301*   remove $INDEX - remove the element at $INDEX
302*   reset         - reset to empty vector
303
304Accessors:
305*   [INDEX] - access item at INDEX
306*   [?]     - access items at current context
307*   .length - display number of items"#)
308            }
309            action => { format!("vector cannot '{:?}'", action) }
310        }
311    }
312}
313
314impl<T> Serialize for ContextVec<T> where T: Serialize {
315    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
316        self.vector.serialize(serializer)
317    }
318}
319
320impl<'de, T> Deserialize<'de> for ContextVec<T> where T: Deserialize<'de> {
321    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
322        Ok(ContextVec {
323            context: vec!(),
324            vector: Vec::<T>::deserialize(deserializer)?,
325        })
326    }
327}