Use RawString instead of Box<[u8]> in Value.
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 13 Apr 2025 17:05:23 +0000 (10:05 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 13 Apr 2025 17:05:23 +0000 (10:05 -0700)
rust/pspp/src/cooked.rs
rust/pspp/src/dictionary.rs
rust/pspp/src/format/display.rs
rust/pspp/src/format/mod.rs
rust/pspp/src/raw.rs

index 96d78ff1f2ea2bbb484fd8478aaac19ea41be5dc..7c68d47c8b664a56f559e89986f263b5be5661ea 100644 (file)
@@ -714,9 +714,7 @@ pub fn decode(
             // XXX warn about too-long value?
             value.0.resize(width, b' ');
             // XXX warn abouat duplicate value labels?
-            variable
-                .value_labels
-                .insert(Value::String(value.0.into_boxed_slice()), label);
+            variable.value_labels.insert(Value::String(value), label);
         }
     }
 
index 67d5539ba72d3099c4597c7e745d4e16ed53b042..d6f0980c2295847f80953b49a2e432e349a2ab23 100644 (file)
@@ -16,7 +16,7 @@ use unicase::UniCase;
 use crate::{
     format::Format,
     identifier::{ByIdentifier, HasIdentifier, Identifier},
-    raw::{Alignment, CategoryLabels, Measure, MissingValues, VarType},
+    raw::{Alignment, CategoryLabels, Measure, MissingValues, RawString, VarType},
 };
 
 pub type DictIndex = usize;
@@ -157,7 +157,7 @@ impl From<VarWidth> for VarType {
 }
 
 #[derive(Clone)]
-pub enum Value<S = Box<[u8]>> {
+pub enum Value<S = RawString> {
     Number(Option<f64>),
     String(S),
 }
@@ -233,7 +233,7 @@ impl Value {
         }
     }
 
-    pub fn as_string(&self) -> Option<&[u8]> {
+    pub fn as_string(&self) -> Option<&RawString> {
         match self {
             Value::Number(_) => None,
             Value::String(s) => Some(s),
index 8955d6b7b9604f3e06450669d2c2127983fd55e0..6edf3dc9f31c7cc47e8c3d3085603422b7ed7e70 100644 (file)
@@ -44,11 +44,15 @@ impl Display for DisplayValue<'_, '_> {
             Value::Number(number) => *number,
             Value::String(string) => {
                 if self.format.type_() == Type::AHex {
-                    for byte in string {
+                    for byte in &string.0 {
                         write!(f, "{byte:02x}")?;
                     }
                 } else {
-                    write!(f, "{}", self.encoding.decode_without_bom_handling(string).0)?;
+                    write!(
+                        f,
+                        "{}",
+                        self.encoding.decode_without_bom_handling(&string.0).0
+                    )?;
                 }
                 return Ok(());
             }
index 3b87aa4664eafe7943e23d8cc15f58de1981169a..8f520266a6fe1ef0473b63f7a0c521589d2301c4 100644 (file)
@@ -13,7 +13,7 @@ use unicode_width::UnicodeWidthStr;
 
 use crate::{
     dictionary::{Value, VarWidth},
-    raw::{self, VarType},
+    raw::{self, RawString, VarType},
 };
 
 mod display;
@@ -592,7 +592,7 @@ impl Format {
     pub fn default_value(&self) -> Value {
         match self.var_width() {
             VarWidth::Numeric => Value::sysmis(),
-            VarWidth::String(width) => Value::String((0..width).map(|_| 0u8).collect()),
+            VarWidth::String(width) => Value::String(RawString::spaces(width as usize)),
         }
     }
 }
index b8d0ea2cb99790ca84f29f6472239437d6a63338..b9f25230adc797415aac6c2d33bd68f0e2886ddf 100644 (file)
@@ -770,7 +770,7 @@ impl RawValue {
             Self::Number(x) => Value::Number(*x),
             Self::String(s) => {
                 let width = width.as_string_width().unwrap();
-                Value::String(Box::from(&s.0[..width]))
+                Value::String(RawString::from(&s.0[..width]))
             }
         }
     }
@@ -1370,9 +1370,15 @@ impl Debug for UntypedValue {
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct RawString(pub Vec<u8>);
 
+impl RawString {
+    pub fn spaces(n: usize) -> Self {
+        Self(std::iter::repeat_n(b' ', n).collect())
+    }
+}
+
 impl From<Vec<u8>> for RawString {
     fn from(source: Vec<u8>) -> Self {
         Self(source)