work
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 10 Dec 2023 23:31:57 +0000 (15:31 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 10 Dec 2023 23:31:57 +0000 (15:31 -0800)
rust/src/cooked.rs
rust/src/dictionary.rs

index be1b4c4b71fd77fa9cb344dec127ef9491cb2b87..757e770520ad6d0a248f8527f9cbd0b2c4cd85c1 100644 (file)
@@ -834,7 +834,7 @@ impl<T> WarnOnError<T> for Result<T, Error> {
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum Value {
     Number(Option<OrderedFloat<f64>>),
-    String(String),
+    String(Box<str>),
 }
 
 impl Value {
index fd408d7725c7345fcc8959facd9a61bd152d626e..7e98575c5ff714462dc577d0368689da889caafc 100644 (file)
@@ -1,6 +1,7 @@
 use std::{
     collections::{HashMap, HashSet},
     fmt::Debug,
+    ops::{Bound, RangeBounds},
 };
 
 use encoding_rs::Encoding;
@@ -49,16 +50,77 @@ impl Dictionary {
         }
     }
 
-    pub fn delete_vars(&mut self, start: DictIndex, count: usize) {
-        self.update_dict_indexes(&|index| {
-            if index < start {
-                Some(index)
-            } else if index < start + count {
-                None
-            } else {
-                Some(index - count)
+    pub fn reorder_var(&mut self, from_index: DictIndex, to_index: DictIndex) {
+        if from_index != to_index {
+            self.variables.move_index(from_index, to_index);
+            self.update_dict_indexes(&|index| {
+                if index == from_index {
+                    Some(to_index)
+                } else if from_index < to_index {
+                    if index > from_index && index <= to_index {
+                        Some(index - 1)
+                    } else {
+                        Some(index)
+                    }
+                } else {
+                    if index >= to_index && index < from_index {
+                        Some(index + 1)
+                    } else {
+                        Some(index)
+                    }
+                }
+            })
+        }
+    }
+
+    pub fn retain_vars<F>(&mut self, keep: F)
+    where
+        F: Fn(&Variable) -> bool,
+    {
+        let mut deleted = Vec::new();
+        let mut index = 0;
+        self.variables.retain(|var_by_id| {
+            let keep = keep(&var_by_id.0);
+            if !keep {
+                deleted.push(index);
             }
-        })
+            index += 1;
+            keep
+        });
+        if !deleted.is_empty() {
+            self.update_dict_indexes(&|index| match deleted.binary_search(&index) {
+                Ok(_) => None,
+                Err(position) => Some(position),
+            })
+        }
+    }
+
+    pub fn delete_vars<R>(&mut self, range: R)
+    where
+        R: RangeBounds<DictIndex>,
+    {
+        let start = match range.start_bound() {
+            Bound::Included(&start) => start,
+            Bound::Excluded(&start) => start + 1,
+            Bound::Unbounded => 0,
+        };
+        let end = match range.end_bound() {
+            Bound::Included(&end) => end + 1,
+            Bound::Excluded(&end) => end,
+            Bound::Unbounded => self.variables.len(),
+        };
+        if end > start {
+            self.variables.drain(start..end);
+            self.update_dict_indexes(&|index| {
+                if index < start {
+                    Some(index)
+                } else if index < end {
+                    None
+                } else {
+                    Some(index - end - start)
+                }
+            })
+        }
     }
 
     fn update_dict_indexes<F>(&mut self, f: &F)