start generalizing datum
authorBen Pfaff <blp@cs.stanford.edu>
Fri, 25 Jul 2025 01:55:12 +0000 (18:55 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 25 Jul 2025 01:55:12 +0000 (18:55 -0700)
rust/pspp/src/data.rs

index 9a84123de8e06b30c5a75e93ed5cc22983c5b594..38510e6b74d71c856f25081f13c39b41e69e8c7b 100644 (file)
@@ -73,12 +73,6 @@ impl RawString {
         EncodedStr::new(&self.0, encoding)
     }
 
-    /// Returns true if this raw string can be resized to `len` bytes without
-    /// dropping non-space characters.
-    pub fn is_resizable(&self, new_len: usize) -> bool {
-        new_len >= self.len() || self.0[new_len..].iter().all(|b| *b == b' ')
-    }
-
     /// Extends or shortens this [RawString] to exactly `len` bytes.  If the
     /// string needs to be extended, does so by appending spaces.
     ///
@@ -216,6 +210,12 @@ impl RawStr {
         }
     }
 
+    /// Returns true if this raw string can be resized to `len` bytes without
+    /// dropping non-space characters.
+    pub fn is_resizable(&self, new_len: usize) -> bool {
+        new_len >= self.len() || self.0[new_len..].iter().all(|b| *b == b' ')
+    }
+
     /// Returns the string's length in bytes.
     pub fn len(&self) -> usize {
         self.0.len()
@@ -602,7 +602,10 @@ where
     }
 }
 
-impl Datum<RawString> {
+impl<B> Datum<B>
+where
+    B: Borrow<RawStr>,
+{
     /// Constructs a new numerical [Datum] for the system-missing value.
     pub const fn sysmis() -> Self {
         Self::Number(None)
@@ -619,13 +622,45 @@ impl Datum<RawString> {
 
     /// Returns the string inside this datum, or `None` if this is a numeric
     /// datum.
-    pub fn as_string(&self) -> Option<&RawString> {
+    pub fn as_string(&self) -> Option<&RawStr> {
         match self {
             Self::Number(_) => None,
-            Self::String(s) => Some(s),
+            Self::String(s) => Some(s.borrow()),
+        }
+    }
+
+    /// Returns true if this datum can be resized to the given `width` without
+    /// loss, which is true only if this datum and `width` are both string or
+    /// both numeric and, for string widths, if resizing would not drop any
+    /// non-space characters.
+    pub fn is_resizable(&self, width: VarWidth) -> bool {
+        match (self, width) {
+            (Self::Number(_), VarWidth::Numeric) => true,
+            (Self::String(s), VarWidth::String(new_width)) => {
+                s.borrow().is_resizable(new_width as usize)
+            }
+            _ => false,
+        }
+    }
+
+    /// Returns the [VarType] corresponding to this datum.
+    pub fn var_type(&self) -> VarType {
+        match self {
+            Self::Number(_) => VarType::Numeric,
+            Self::String(_) => VarType::String,
+        }
+    }
+
+    /// Returns the [VarWidth] corresponding to this datum.
+    pub fn width(&self) -> VarWidth {
+        match self {
+            Self::Number(_) => VarWidth::Numeric,
+            Self::String(s) => VarWidth::String(s.borrow().len().try_into().unwrap()),
         }
     }
+}
 
+impl Datum<RawString> {
     /// Returns the string inside this datum as a mutable borrow, or `None` if
     /// this is a numeric datum.
     pub fn as_string_mut(&mut self) -> Option<&mut RawString> {
@@ -642,18 +677,6 @@ impl Datum<RawString> {
         }
     }
 
-    /// Returns true if this datum can be resized to the given `width` without
-    /// loss, which is true only if this datum and `width` are both string or
-    /// both numeric and, for string widths, if resizing would not drop any
-    /// non-space characters.
-    pub fn is_resizable(&self, width: VarWidth) -> bool {
-        match (self, width) {
-            (Self::Number(_), VarWidth::Numeric) => true,
-            (Self::String(s), VarWidth::String(new_width)) => s.is_resizable(new_width as usize),
-            _ => false,
-        }
-    }
-
     /// Resizes this datum to the given `width`.  Returns an error, without
     /// modifying the datum, if [is_resizable](Self::is_resizable) would return
     /// false.
@@ -672,22 +695,6 @@ impl Datum<RawString> {
         }
     }
 
-    /// Returns the [VarType] corresponding to this datum.
-    pub fn var_type(&self) -> VarType {
-        match self {
-            Self::Number(_) => VarType::Numeric,
-            Self::String(_) => VarType::String,
-        }
-    }
-
-    /// Returns the [VarWidth] corresponding to this datum.
-    pub fn width(&self) -> VarWidth {
-        match self {
-            Self::Number(_) => VarWidth::Numeric,
-            Self::String(s) => VarWidth::String(s.len().try_into().unwrap()),
-        }
-    }
-
     /// Compares this datum and `other` for equality, ignoring trailing ASCII
     /// spaces in either, if they are both strings, for the purpose of
     /// comparison.