From ad742bb36412a91492bedcf6923839d462d02652 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 20 May 2025 17:03:39 -0700 Subject: [PATCH] rename value to datum --- rust/pspp/src/dictionary.rs | 122 ++++++++++++--------------- rust/pspp/src/format/display/mod.rs | 56 ++++++------ rust/pspp/src/format/display/test.rs | 10 +-- rust/pspp/src/format/mod.rs | 16 ++-- rust/pspp/src/format/parse.rs | 90 ++++++++++---------- rust/pspp/src/output/pivot/mod.rs | 21 ++--- rust/pspp/src/sys/cooked.rs | 14 +-- rust/pspp/src/sys/raw.rs | 61 ++++++++------ 8 files changed, 186 insertions(+), 204 deletions(-) diff --git a/rust/pspp/src/dictionary.rs b/rust/pspp/src/dictionary.rs index 6994d1289c..12af9e6549 100644 --- a/rust/pspp/src/dictionary.rs +++ b/rust/pspp/src/dictionary.rs @@ -21,9 +21,7 @@ use unicase::UniCase; use crate::{ format::Format, identifier::{ByIdentifier, HasIdentifier, Identifier}, - output::pivot::{ - Axis3, Dimension, Footnote, Footnotes, Group, PivotTable, Value as PivotValue, - }, + output::pivot::{Axis3, Dimension, Footnote, Footnotes, Group, PivotTable, Value}, settings::Show, sys::raw::{Alignment, CategoryLabels, Measure, MissingValues, RawString, VarType}, }; @@ -168,25 +166,25 @@ impl From for VarType { } #[derive(Clone)] -pub enum Value { +pub enum Datum { Number(Option), String(S), } -impl Debug for Value +impl Debug for Datum where S: Debug, { fn fmt(&self, f: &mut Formatter) -> FmtResult { match self { - Value::Number(Some(number)) => write!(f, "{number:?}"), - Value::Number(None) => write!(f, "SYSMIS"), - Value::String(s) => write!(f, "{:?}", s), + Datum::Number(Some(number)) => write!(f, "{number:?}"), + Datum::Number(None) => write!(f, "SYSMIS"), + Datum::String(s) => write!(f, "{:?}", s), } } } -impl PartialEq for Value { +impl PartialEq for Datum { fn eq(&self, other: &Self) -> bool { match (self, other) { (Self::Number(Some(l0)), Self::Number(Some(r0))) => { @@ -199,78 +197,78 @@ impl PartialEq for Value { } } -impl Eq for Value {} +impl Eq for Datum {} -impl PartialOrd for Value { +impl PartialOrd for Datum { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for Value { +impl Ord for Datum { fn cmp(&self, other: &Self) -> Ordering { match (self, other) { - (Value::Number(a), Value::Number(b)) => match (a, b) { + (Datum::Number(a), Datum::Number(b)) => match (a, b) { (None, None) => Ordering::Equal, (None, Some(_)) => Ordering::Less, (Some(_), None) => Ordering::Greater, (Some(a), Some(b)) => a.total_cmp(b), }, - (Value::Number(_), Value::String(_)) => Ordering::Less, - (Value::String(_), Value::Number(_)) => Ordering::Greater, - (Value::String(a), Value::String(b)) => a.cmp(b), + (Datum::Number(_), Datum::String(_)) => Ordering::Less, + (Datum::String(_), Datum::Number(_)) => Ordering::Greater, + (Datum::String(a), Datum::String(b)) => a.cmp(b), } } } -impl Hash for Value { +impl Hash for Datum { fn hash(&self, state: &mut H) { match self { - Value::Number(number) => number.map(OrderedFloat).hash(state), - Value::String(string) => string.hash(state), + Datum::Number(number) => number.map(OrderedFloat).hash(state), + Datum::String(string) => string.hash(state), } } } -impl Value { +impl Datum { pub const fn sysmis() -> Self { Self::Number(None) } pub fn as_number(&self) -> Option> { match self { - Value::Number(number) => Some(*number), - Value::String(_) => None, + Datum::Number(number) => Some(*number), + Datum::String(_) => None, } } pub fn as_string(&self) -> Option<&RawString> { match self { - Value::Number(_) => None, - Value::String(s) => Some(s), + Datum::Number(_) => None, + Datum::String(s) => Some(s), } } } -impl From for Value { - fn from(value: f64) -> Self { - Some(value).into() +impl From for Datum { + fn from(number: f64) -> Self { + Some(number).into() } } -impl From> for Value { +impl From> for Datum { fn from(value: Option) -> Self { Self::Number(value) } } -impl From<&str> for Value { +impl From<&str> for Datum { fn from(value: &str) -> Self { value.as_bytes().into() } } -impl From<&[u8]> for Value { +impl From<&[u8]> for Datum { fn from(value: &[u8]) -> Self { Self::String(value.into()) } @@ -566,7 +564,7 @@ impl<'a> OutputVariables<'a> { pub fn to_pivot_table(&self) -> PivotTable { let mut names = Group::new("Name"); for variable in &self.dictionary.variables { - names.push(PivotValue::new_variable(variable)); + names.push(Value::new_variable(variable)); } let mut attributes = Group::new("Attributes"); @@ -596,32 +594,24 @@ impl<'a> OutputVariables<'a> { pt } - fn get_field_value( - index: usize, - variable: &Variable, - field: VariableField, - ) -> Option { + fn get_field_value(index: usize, variable: &Variable, field: VariableField) -> Option { match field { - VariableField::Position => Some(PivotValue::new_integer(Some(index as f64 + 1.0))), - VariableField::Label => variable - .label() - .map(|label| PivotValue::new_user_text(label)), + VariableField::Position => Some(Value::new_integer(Some(index as f64 + 1.0))), + VariableField::Label => variable.label().map(|label| Value::new_user_text(label)), VariableField::Measure => variable .measure - .map(|measure| PivotValue::new_text(measure.as_str())), - VariableField::Role => Some(PivotValue::new_text(variable.role.as_str())), - VariableField::Width => { - Some(PivotValue::new_integer(Some(variable.display_width as f64))) - } - VariableField::Alignment => Some(PivotValue::new_text(variable.alignment.as_str())), + .map(|measure| Value::new_text(measure.as_str())), + VariableField::Role => Some(Value::new_text(variable.role.as_str())), + VariableField::Width => Some(Value::new_integer(Some(variable.display_width as f64))), + VariableField::Alignment => Some(Value::new_text(variable.alignment.as_str())), VariableField::PrintFormat => { - Some(PivotValue::new_user_text(variable.print_format.to_string())) + Some(Value::new_user_text(variable.print_format.to_string())) } VariableField::WriteFormat => { - Some(PivotValue::new_user_text(variable.write_format.to_string())) + Some(Value::new_user_text(variable.write_format.to_string())) } VariableField::MissingValues if !variable.missing_values.is_empty() => { - Some(PivotValue::new_user_text( + Some(Value::new_user_text( variable .missing_values .display(variable.encoding) @@ -660,7 +650,7 @@ impl<'a> OutputValueLabels<'a> { let mut values = variable.value_labels.iter().collect::>(); values.sort(); for (value, label) in values { - let value = PivotValue::new_variable_value(variable, value) + let value = Value::new_variable_value(variable, value) .with_show_value_label(Some(Show::Value)); //group.push(); todo!() @@ -670,32 +660,24 @@ impl<'a> OutputValueLabels<'a> { todo!() } - fn get_field_value( - index: usize, - variable: &Variable, - field: VariableField, - ) -> Option { + fn get_field_value(index: usize, variable: &Variable, field: VariableField) -> Option { match field { - VariableField::Position => Some(PivotValue::new_integer(Some(index as f64 + 1.0))), - VariableField::Label => variable - .label() - .map(|label| PivotValue::new_user_text(label)), + VariableField::Position => Some(Value::new_integer(Some(index as f64 + 1.0))), + VariableField::Label => variable.label().map(|label| Value::new_user_text(label)), VariableField::Measure => variable .measure - .map(|measure| PivotValue::new_text(measure.as_str())), - VariableField::Role => Some(PivotValue::new_text(variable.role.as_str())), - VariableField::Width => { - Some(PivotValue::new_integer(Some(variable.display_width as f64))) - } - VariableField::Alignment => Some(PivotValue::new_text(variable.alignment.as_str())), + .map(|measure| Value::new_text(measure.as_str())), + VariableField::Role => Some(Value::new_text(variable.role.as_str())), + VariableField::Width => Some(Value::new_integer(Some(variable.display_width as f64))), + VariableField::Alignment => Some(Value::new_text(variable.alignment.as_str())), VariableField::PrintFormat => { - Some(PivotValue::new_user_text(variable.print_format.to_string())) + Some(Value::new_user_text(variable.print_format.to_string())) } VariableField::WriteFormat => { - Some(PivotValue::new_user_text(variable.write_format.to_string())) + Some(Value::new_user_text(variable.write_format.to_string())) } VariableField::MissingValues if !variable.missing_values.is_empty() => { - Some(PivotValue::new_user_text( + Some(Value::new_user_text( variable .missing_values .display(variable.encoding) @@ -881,7 +863,7 @@ pub struct Variable { /// Value labels, to associate a number (or a string) with a more meaningful /// description, e.g. 1 -> Apple, 2 -> Banana, ... - pub value_labels: HashMap, + pub value_labels: HashMap, /// Variable label, an optional meaningful description for the variable /// itself. @@ -1023,7 +1005,7 @@ pub enum MultipleResponseType { /// one value (the "counted value") means that the box was checked, and any /// other value means that it was not. MultipleDichotomy { - value: Value, + datum: Datum, labels: CategoryLabels, }, diff --git a/rust/pspp/src/format/display/mod.rs b/rust/pspp/src/format/display/mod.rs index b315c8873c..7f259b94ee 100644 --- a/rust/pspp/src/format/display/mod.rs +++ b/rust/pspp/src/format/display/mod.rs @@ -13,17 +13,17 @@ use smallvec::{Array, SmallVec}; use crate::{ calendar::{calendar_offset_to_gregorian, day_of_year, month_name, short_month_name}, - dictionary::Value, + dictionary::Datum, endian::ToBytes, format::{Category, DateTemplate, Decimal, Format, NumberStyle, Settings, TemplateItem, Type}, settings::{EndianSettings, Settings as PsppSettings}, }; -pub struct DisplayValue<'a, 'b> { +pub struct DisplayDatum<'a, 'b> { format: Format, settings: &'b Settings, endian: EndianSettings, - value: &'a Value, + datum: &'a Datum, encoding: &'static Encoding, } @@ -58,32 +58,32 @@ impl Display for DisplayPlainF64 { } } -impl Value { - /// Returns an object that implements [Display] for printing this `Value` as - /// `format`. `encoding` specifies this `Value`'s encoding (therefore, it - /// is used only if this is a `Value::String`). +impl Datum { + /// Returns an object that implements [Display] for printing this [Datum] as + /// `format`. `encoding` specifies this `Datum`'s encoding (therefore, it + /// is used only if this is a `Datum::String`). /// /// [Display]: std::fmt::Display - pub fn display(&self, format: Format, encoding: &'static Encoding) -> DisplayValue { - DisplayValue::new(format, self, encoding) + pub fn display(&self, format: Format, encoding: &'static Encoding) -> DisplayDatum { + DisplayDatum::new(format, self, encoding) } - pub fn display_plain(&self, encoding: &'static Encoding) -> DisplayValuePlain { - DisplayValuePlain { - value: self, + pub fn display_plain(&self, encoding: &'static Encoding) -> DisplayDatumPlain { + DisplayDatumPlain { + datum: self, encoding, quote_strings: true, } } } -pub struct DisplayValuePlain<'a> { - value: &'a Value, +pub struct DisplayDatumPlain<'a> { + datum: &'a Datum, encoding: &'static Encoding, quote_strings: bool, } -impl DisplayValuePlain<'_> { +impl DisplayDatumPlain<'_> { pub fn without_quotes(self) -> Self { Self { quote_strings: false, @@ -92,12 +92,12 @@ impl DisplayValuePlain<'_> { } } -impl Display for DisplayValuePlain<'_> { +impl Display for DisplayDatumPlain<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - match self.value { - Value::Number(None) => write!(f, "SYSMIS"), - Value::Number(Some(number)) => number.display_plain().fmt(f), - Value::String(string) => { + match self.datum { + Datum::Number(None) => write!(f, "SYSMIS"), + Datum::Number(Some(number)) => number.display_plain().fmt(f), + Datum::String(string) => { if self.quote_strings { write!(f, "\"{}\"", string.display(self.encoding)) } else { @@ -108,11 +108,11 @@ impl Display for DisplayValuePlain<'_> { } } -impl Display for DisplayValue<'_, '_> { +impl Display for DisplayDatum<'_, '_> { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - let number = match self.value { - Value::Number(number) => *number, - Value::String(string) => { + let number = match self.datum { + Datum::Number(number) => *number, + Datum::String(string) => { if self.format.type_() == Type::AHex { for byte in &string.0 { write!(f, "{byte:02x}")?; @@ -167,12 +167,12 @@ impl Display for DisplayValue<'_, '_> { } } -impl<'a, 'b> DisplayValue<'a, 'b> { - pub fn new(format: Format, value: &'a Value, encoding: &'static Encoding) -> Self { +impl<'a, 'b> DisplayDatum<'a, 'b> { + pub fn new(format: Format, value: &'a Datum, encoding: &'static Encoding) -> Self { let settings = PsppSettings::global(); Self { format, - value, + datum: value, encoding, settings: &settings.formats, endian: settings.endian, @@ -639,7 +639,7 @@ impl<'a, 'b> DisplayValue<'a, 'b> { } fn to_binary(&self) -> Option> { - let number = self.value.as_number()?; + let number = self.datum.as_number()?; match self.format.type_() { Type::P => Some(self.p(number)), Type::PK => Some(self.pk(number)), diff --git a/rust/pspp/src/format/display/test.rs b/rust/pspp/src/format/display/test.rs index cae76487ba..0f581d6d61 100644 --- a/rust/pspp/src/format/display/test.rs +++ b/rust/pspp/src/format/display/test.rs @@ -7,7 +7,7 @@ use smallstr::SmallString; use smallvec::SmallVec; use crate::{ - dictionary::Value, + dictionary::Datum, endian::Endian, format::{AbstractFormat, Epoch, Format, Settings, Type, UncheckedFormat, CC}, lex::{ @@ -63,7 +63,7 @@ fn test(name: &str) { let format: Format = format.try_into().unwrap(); assert_eq!(tokens.get(1), Some(&Token::Punct(Punct::Colon))); let expected = tokens[2].as_string().unwrap(); - let actual = Value::Number(value) + let actual = Datum::Number(value) .display(format, UTF_8) .with_settings(&settings) .with_endian(endian) @@ -171,7 +171,7 @@ fn leading_zeros() { } fn test_with_settings(value: f64, expected: [&str; 2], settings: &Settings) { - let value = Value::from(value); + let value = Datum::from(value); for (expected, d) in expected.into_iter().zip([2, 1].into_iter()) { assert_eq!( &value @@ -202,7 +202,7 @@ fn leading_zeros() { fn non_ascii_cc() { fn test(settings: &Settings, value: f64, expected: &str) { assert_eq!( - &Value::from(value) + &Datum::from(value) .display(Format::new(Type::CC(CC::A), 10, 2).unwrap(), UTF_8) .with_settings(settings) .to_string(), @@ -254,7 +254,7 @@ fn test_binhex(name: &str) { assert_eq!(tokens.get(1), Some(&Token::Punct(Punct::Colon))); let expected = tokens[2].as_string().unwrap(); let mut actual = SmallVec::<[u8; 16]>::new(); - Value::Number(value) + Datum::Number(value) .display(format, UTF_8) .with_endian(endian) .write(&mut actual, UTF_8) diff --git a/rust/pspp/src/format/mod.rs b/rust/pspp/src/format/mod.rs index 51c06096d8..b7c3d81003 100644 --- a/rust/pspp/src/format/mod.rs +++ b/rust/pspp/src/format/mod.rs @@ -12,13 +12,13 @@ use thiserror::Error as ThisError; use unicode_width::UnicodeWidthStr; use crate::{ - dictionary::{Value, VarWidth}, + dictionary::{Datum, VarWidth}, sys::raw::{self, RawString, VarType}, }; mod display; mod parse; -pub use display::{DisplayPlain, DisplayValue}; +pub use display::{DisplayPlain, DisplayDatum}; #[derive(Clone, ThisError, Debug, PartialEq, Eq)] pub enum Error { @@ -374,10 +374,10 @@ impl Type { } } - pub fn default_value(&self) -> Value { + pub fn default_value(&self) -> Datum { match self.var_type() { - VarType::Numeric => Value::sysmis(), - VarType::String => Value::String(RawString::default()), + VarType::Numeric => Datum::sysmis(), + VarType::String => Datum::String(RawString::default()), } } } @@ -596,10 +596,10 @@ impl Format { Ok(self) } - pub fn default_value(&self) -> Value { + pub fn default_value(&self) -> Datum { match self.var_width() { - VarWidth::Numeric => Value::sysmis(), - VarWidth::String(width) => Value::String(RawString::spaces(width as usize)), + VarWidth::Numeric => Datum::sysmis(), + VarWidth::String(width) => Datum::String(RawString::spaces(width as usize)), } } } diff --git a/rust/pspp/src/format/parse.rs b/rust/pspp/src/format/parse.rs index 2f5887370f..118cbe2982 100644 --- a/rust/pspp/src/format/parse.rs +++ b/rust/pspp/src/format/parse.rs @@ -1,6 +1,6 @@ use crate::{ calendar::{calendar_gregorian_to_offset, DateError}, - dictionary::Value, + dictionary::Datum, endian::{Endian, Parse}, format::{DateTemplate, Decimals, Settings, TemplateItem, Type}, settings::{EndianSettings, Settings as PsppSettings}, @@ -175,7 +175,7 @@ impl<'a> ParseValue<'a> { /// input into UTF-8, but this will screw up parsing of binary formats, /// because recoding bytes from (e.g.) windows-1252 into UTF-8, and then /// interpreting them as a binary number yields nonsense. - pub fn parse<'b, T>(&self, input: T) -> Result + pub fn parse<'b, T>(&self, input: T) -> Result where T: Into>, { @@ -212,7 +212,7 @@ impl<'a> ParseValue<'a> { Type::IB => self.parse_ib(input.as_bytes()), Type::PIB => self.parse_pib(input.as_bytes()), Type::RB => self.parse_rb(input.as_bytes()), - Type::A => Ok(Value::String( + Type::A => Ok(Datum::String( input.to_encoding(self.output_encoding).into(), )), Type::AHex => self.parse_ahex(&input.as_str()), @@ -224,12 +224,12 @@ impl<'a> ParseValue<'a> { }) } - fn parse_number(&self, input: &str, type_: Type) -> Result { + fn parse_number(&self, input: &str, type_: Type) -> Result { let style = self.settings.number_style(type_); let input = input.trim(); if input.is_empty() || input == "." { - return Ok(Value::sysmis()); + return Ok(Datum::sysmis()); } let mut p = StrParser::new(input.trim()); fn strip_integer(mut input: &str, grouping: Option) -> &str { @@ -292,22 +292,22 @@ impl<'a> ParseValue<'a> { } match f64::from_str(&number) { - Ok(value) => Ok(Value::Number(Some(value))), + Ok(value) => Ok(Datum::Number(Some(value))), Err(_) => Err(ParseErrorKind::InvalidNumericSyntax), } } - fn parse_n(&self, input: &str) -> Result { + fn parse_n(&self, input: &str) -> Result { match input.chars().find(|c| !c.is_ascii_digit()) { - None => Ok(Value::Number(Some(input.parse().unwrap()))), + None => Ok(Datum::Number(Some(input.parse().unwrap()))), Some(nondigit) => Err(ParseErrorKind::Nondigit(nondigit)), } } - fn parse_z(&self, input: &str) -> Result { + fn parse_z(&self, input: &str) -> Result { let input = input.trim(); if input.is_empty() || input == "." { - return Ok(Value::sysmis()); + return Ok(Datum::sysmis()); } enum ZChar { @@ -361,7 +361,7 @@ impl<'a> ParseValue<'a> { } else { number }; - Ok(Value::Number(Some(number))) + Ok(Datum::Number(Some(number))) } fn parse_bcd(input: &[u8]) -> Result { @@ -381,14 +381,14 @@ impl<'a> ParseValue<'a> { } } - fn parse_pk(&self, input: &[u8]) -> Result { + fn parse_pk(&self, input: &[u8]) -> Result { let number = Self::parse_bcd(input)?; - Ok(Value::Number(Some(self.apply_decimals(number as f64)))) + Ok(Datum::Number(Some(self.apply_decimals(number as f64)))) } - fn parse_p(&self, input: &[u8]) -> Result { + fn parse_p(&self, input: &[u8]) -> Result { if input.is_empty() { - return Ok(Value::Number(None)); + return Ok(Datum::Number(None)); }; let (head, tail) = input.split_at(input.len() - 1); let number = Self::parse_bcd(head)?; @@ -398,7 +398,7 @@ impl<'a> ParseValue<'a> { 0xd => -(number as f64), other => return Err(ParseErrorKind::InvalidBCDSign(other)), }; - Ok(Value::Number(Some(self.apply_decimals(number)))) + Ok(Datum::Number(Some(self.apply_decimals(number)))) } fn parse_binary(&self, input: &[u8]) -> u128 { @@ -408,7 +408,7 @@ impl<'a> ParseValue<'a> { } } - fn parse_ib(&self, input: &[u8]) -> Result { + fn parse_ib(&self, input: &[u8]) -> Result { let number = self.parse_binary(input); let sign_bit = 1 << (input.len() * 8 - 1); let number = if (number & sign_bit) == 0 { @@ -416,15 +416,15 @@ impl<'a> ParseValue<'a> { } else { -(number.wrapping_sub(sign_bit << 1) as i128) }; - Ok(Value::Number(Some(self.apply_decimals(number as f64)))) + Ok(Datum::Number(Some(self.apply_decimals(number as f64)))) } - fn parse_pib(&self, input: &[u8]) -> Result { + fn parse_pib(&self, input: &[u8]) -> Result { let number = self.parse_binary(input); - Ok(Value::Number(Some(self.apply_decimals(number as f64)))) + Ok(Datum::Number(Some(self.apply_decimals(number as f64)))) } - fn parse_rb(&self, input: &[u8]) -> Result { + fn parse_rb(&self, input: &[u8]) -> Result { let mut bytes = [0; 8]; let len = input.len().min(8); bytes[..len].copy_from_slice(&input[..len]); @@ -435,10 +435,10 @@ impl<'a> ParseValue<'a> { SYSMIS => None, other => Some(other), }; - Ok(Value::Number(number)) + Ok(Datum::Number(number)) } - fn parse_ahex(&self, input: &str) -> Result { + fn parse_ahex(&self, input: &str) -> Result { let mut result = Vec::with_capacity(input.len() / 2); let mut iter = input.chars(); while let Some(hi) = iter.next() { @@ -453,7 +453,7 @@ impl<'a> ParseValue<'a> { }; result.push((hi * 16 + lo) as u8); } - Ok(Value::String(result.into())) + Ok(Datum::String(result.into())) } fn parse_hex(&self, input: &str) -> Result, ParseErrorKind> { @@ -468,20 +468,20 @@ impl<'a> ParseValue<'a> { } } - fn parse_pibhex(&self, input: &str) -> Result { + fn parse_pibhex(&self, input: &str) -> Result { self.parse_hex(input) - .map(|value| Value::Number(value.map(|number| number as f64))) + .map(|value| Datum::Number(value.map(|number| number as f64))) } - fn parse_rbhex(&self, input: &str) -> Result { + fn parse_rbhex(&self, input: &str) -> Result { self.parse_hex(input) - .map(|value| Value::Number(value.map(f64::from_bits))) + .map(|value| Datum::Number(value.map(f64::from_bits))) } - fn parse_date(&self, input: &str) -> Result { + fn parse_date(&self, input: &str) -> Result { let mut p = StrParser(input.trim()); if p.0.is_empty() || p.0 == "." { - return Ok(Value::sysmis()); + return Ok(Datum::sysmis()); } let mut day = 1; @@ -566,7 +566,7 @@ impl<'a> ParseValue<'a> { } else { date + time }; - Ok(Value::Number(Some(time_date))) + Ok(Datum::Number(Some(time_date))) } fn parse_minute_second(&self, p: &mut StrParser<'_>) -> Result { @@ -594,25 +594,25 @@ impl<'a> ParseValue<'a> { Ok(time + seconds) } - fn parse_wkday(&self, input: &str) -> Result { + fn parse_wkday(&self, input: &str) -> Result { let mut p = StrParser(input.trim()); if p.0.is_empty() || p.0 == "." { - Ok(Value::sysmis()) + Ok(Datum::sysmis()) } else { let weekday = parse_weekday(&mut p)?; parse_trailer(&mut p)?; - Ok(Value::Number(Some(weekday as f64))) + Ok(Datum::Number(Some(weekday as f64))) } } - fn parse_month(&self, input: &str) -> Result { + fn parse_month(&self, input: &str) -> Result { let mut p = StrParser(input.trim()); if p.0.is_empty() || p.0 == "." { - Ok(Value::sysmis()) + Ok(Datum::sysmis()) } else { let month = parse_month(&mut p)?; parse_trailer(&mut p)?; - Ok(Value::Number(Some(month as f64))) + Ok(Datum::Number(Some(month as f64))) } } } @@ -905,7 +905,7 @@ mod test { use crate::{ calendar::{days_in_month, is_leap_year}, - dictionary::Value, + dictionary::Datum, endian::Endian, format::{ parse::{ParseError, ParseErrorKind, Sign}, @@ -1215,7 +1215,7 @@ mod test { .with_settings(&settings) .parse(&formatted) .unwrap(); - assert_eq!(parsed, Value::Number(Some(expected as f64))); + assert_eq!(parsed, Datum::Number(Some(expected as f64))); } } @@ -1487,7 +1487,7 @@ mod test { let parsed = Type::WkDay .parser(UTF_8) .parse(input) - .unwrap_or(Value::Number(None)) + .unwrap_or(Datum::Number(None)) .as_number() .unwrap(); assert_eq!(parsed, expected); @@ -1560,7 +1560,7 @@ mod test { let parsed = Type::Month .parser(UTF_8) .parse(input) - .unwrap_or(Value::Number(None)) + .unwrap_or(Datum::Number(None)) .as_number() .unwrap(); assert_eq!(parsed, expected, "parsing {input}"); @@ -1582,7 +1582,7 @@ mod test { let s = [ac, bc].into_iter().collect::(); let parsed = parser .parse(&s) - .unwrap_or(Value::Number(None)) + .unwrap_or(Datum::Number(None)) .as_number() .unwrap(); let expected = if ac == 'x' || bc == 'x' { @@ -1593,8 +1593,8 @@ mod test { assert_eq!(parsed, expected); } } - assert_eq!(parser.parse(".").unwrap(), Value::Number(None)); - assert_eq!(parser.parse("",).unwrap(), Value::Number(None)); + assert_eq!(parser.parse(".").unwrap(), Datum::Number(None)); + assert_eq!(parser.parse("",).unwrap(), Datum::Number(None)); } #[test] @@ -1683,7 +1683,7 @@ mod test { assert_eq!(parsed, number as f64, "formatted as {formatted:?}"); } } - assert_eq!(parser.parse(".").unwrap(), Value::Number(None)); + assert_eq!(parser.parse(".").unwrap(), Datum::Number(None)); let parser = Type::Z.parser(UTF_8).with_implied_decimals(1); for number in -999i32..=999 { diff --git a/rust/pspp/src/output/pivot/mod.rs b/rust/pspp/src/output/pivot/mod.rs index e4225c73fa..9973422221 100644 --- a/rust/pspp/src/output/pivot/mod.rs +++ b/rust/pspp/src/output/pivot/mod.rs @@ -52,7 +52,7 @@ use thiserror::Error as ThisError; use tlo::parse_tlo; use crate::{ - dictionary::{Value as DataValue, Variable}, + dictionary::{Datum, Variable}, format::{Decimal, Format, Settings as FormatSettings, Type, UncheckedFormat}, settings::{Settings, Show}, sys::raw::VarType, @@ -1734,17 +1734,17 @@ impl Value { variable_label: variable.label.clone(), })) } - pub fn new_value(value: &DataValue, encoding: &'static Encoding) -> Self { + pub fn new_value(value: &Datum, encoding: &'static Encoding) -> Self { match value { - DataValue::Number(number) => Self::new_number(*number), - DataValue::String(string) => Self::new_user_text(string.decode(encoding).into_owned()), + Datum::Number(number) => Self::new_number(*number), + Datum::String(string) => Self::new_user_text(string.decode(encoding).into_owned()), } } - pub fn new_variable_value(variable: &Variable, value: &DataValue) -> Self { + pub fn new_variable_value(variable: &Variable, value: &Datum) -> Self { let var_name = Some(variable.name.as_str().into()); let value_label = variable.value_labels.get(value).cloned(); match value { - DataValue::Number(number) => Self::new(ValueInner::Number(NumberValue { + Datum::Number(number) => Self::new(ValueInner::Number(NumberValue { show: None, format: match variable.print_format.var_type() { VarType::Numeric => variable.print_format, @@ -1761,7 +1761,7 @@ impl Value { var_name, value_label, })), - DataValue::String(string) => Self::new(ValueInner::String(StringValue { + Datum::String(string) => Self::new(ValueInner::String(StringValue { show: None, hex: variable.print_format.type_() == Type::AHex, s: string.decode(variable.encoding).into_owned(), @@ -2060,12 +2060,7 @@ impl Display for DisplayValue<'_> { *format }; let mut buf = SmallString::<[u8; 40]>::new(); - write!( - &mut buf, - "{}", - DataValue::Number(*value).display(format, UTF_8) - ) - .unwrap(); + write!(&mut buf, "{}", Datum::Number(*value).display(format, UTF_8)).unwrap(); write!(f, "{}", buf.trim_start_matches(' '))?; } if let Some(label) = self.show_label { diff --git a/rust/pspp/src/sys/cooked.rs b/rust/pspp/src/sys/cooked.rs index 7b4c5235f7..139a191682 100644 --- a/rust/pspp/src/sys/cooked.rs +++ b/rust/pspp/src/sys/cooked.rs @@ -3,7 +3,7 @@ use std::{cell::RefCell, collections::HashMap, ops::Range, rc::Rc}; use crate::{ dictionary::{ - Dictionary, InvalidRole, MultipleResponseSet, MultipleResponseType, Value, VarWidth, + Dictionary, InvalidRole, MultipleResponseSet, MultipleResponseType, Datum, VarWidth, Variable, VariableSet, }, endian::Endian, @@ -600,7 +600,7 @@ pub fn decode( for dict_index in dict_indexes { let variable = dictionary.variables.get_index_mut2(dict_index).unwrap(); - for ValueLabel { value, label } in record.labels.iter().cloned() { + for ValueLabel { datum: value, label } in record.labels.iter().cloned() { let value = value.decode(variable.width); variable.value_labels.insert(value, label); } @@ -754,7 +754,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), label); + variable.value_labels.insert(Datum::String(value), label); } } @@ -773,7 +773,7 @@ pub fn decode( .map(|v| { let mut value = RawString::from(v.0.as_slice()); value.resize(variable.width.as_string_width().unwrap()); - Value::String(value) + Datum::String(value) }) .collect::>(); variable.missing_values = MissingValues { @@ -914,7 +914,7 @@ impl MultipleResponseType { number: string.into(), } })?; - Value::Number(Some(number)) + Datum::Number(Some(number)) } VarWidth::String(max_width) => { let mut value = value.0.as_slice(); @@ -930,11 +930,11 @@ impl MultipleResponseType { max_width, }); }; - Value::String(value.into()) + Datum::String(value.into()) } }; Ok(MultipleResponseType::MultipleDichotomy { - value, + datum: value, labels: *labels, }) } diff --git a/rust/pspp/src/sys/raw.rs b/rust/pspp/src/sys/raw.rs index ad879dfa1b..50fbe9930b 100644 --- a/rust/pspp/src/sys/raw.rs +++ b/rust/pspp/src/sys/raw.rs @@ -1,5 +1,5 @@ use crate::{ - dictionary::{Attributes, Value, VarWidth}, + dictionary::{Attributes, Datum, VarWidth}, endian::{Endian, Parse, ToBytes}, format::DisplayPlain, identifier::{Error as IdError, Identifier}, @@ -707,13 +707,13 @@ impl TryFrom for VarWidth { } } -type RawValue = Value>; +type RawDatum = Datum>; -impl RawValue { - pub fn from_raw(raw: &UntypedValue, var_type: VarType, endian: Endian) -> Self { +impl RawDatum { + pub fn from_raw(raw: &UntypedDatum, var_type: VarType, endian: Endian) -> Self { match var_type { - VarType::String => Value::String(RawStrArray(raw.0)), - VarType::Numeric => Value::Number(endian.parse(raw.0)), + VarType::String => Datum::String(RawStrArray(raw.0)), + VarType::Numeric => Datum::Number(endian.parse(raw.0)), } } @@ -737,7 +737,7 @@ impl RawValue { }); } }; - values.push(Value::from_raw(&UntypedValue(raw), var_type, endian)); + values.push(Datum::from_raw(&UntypedDatum(raw), var_type, endian)); } Ok(Some(values)) } @@ -788,7 +788,7 @@ impl RawValue { } } 253 => { - break Self::from_raw(&UntypedValue(read_bytes(reader)?), var_type, endian) + break Self::from_raw(&UntypedDatum(read_bytes(reader)?), var_type, endian) } 254 => match var_type { VarType::String => break Self::String(RawStrArray(*b" ")), // XXX EBCDIC @@ -815,12 +815,12 @@ impl RawValue { Ok(Some(values)) } - pub fn decode(&self, width: VarWidth) -> Value { + pub fn decode(&self, width: VarWidth) -> Datum { match self { - Self::Number(x) => Value::Number(*x), + Self::Number(x) => Datum::Number(*x), Self::String(s) => { let width = width.as_string_width().unwrap(); - Value::String(RawString::from(&s.0[..width])) + Datum::String(RawString::from(&s.0[..width])) } } } @@ -1041,7 +1041,7 @@ impl Cases { } impl Iterator for Cases { - type Item = Result, Error>; + type Item = Result, Error>; fn next(&mut self) -> Option { if self.eof { @@ -1049,7 +1049,7 @@ impl Iterator for Cases { } let retval = if self.compression.is_some() { - Value::read_compressed_case( + Datum::read_compressed_case( &mut self.reader, &self.var_types, &mut self.codes, @@ -1058,7 +1058,7 @@ impl Iterator for Cases { ) .transpose() } else { - Value::read_case(&mut self.reader, &self.var_types, self.endian).transpose() + Datum::read_case(&mut self.reader, &self.var_types, self.endian).transpose() }; self.eof = matches!(retval, None | Some(Err(_))); retval @@ -1124,7 +1124,7 @@ fn format_name(type_: u32) -> Cow<'static, str> { #[derive(Clone, Default)] pub struct MissingValues { /// Individual missing values, up to 3 of them. - pub values: Vec, + pub values: Vec, /// Optional range of missing values. pub range: Option, @@ -1145,13 +1145,13 @@ impl MissingValues { self.values.is_empty() && self.range.is_none() } - pub fn contains(&self, value: &Value) -> bool { + pub fn contains(&self, value: &Datum) -> bool { if self.values.contains(value) { return true; } match value { - Value::Number(Some(number)) => self.range.is_some_and(|range| range.contains(*number)), + Datum::Number(Some(number)) => self.range.is_some_and(|range| range.contains(*number)), _ => false, } } @@ -1188,7 +1188,7 @@ impl MissingValues { Ok(VarWidth::Numeric) => { let values = values .into_iter() - .map(|v| Value::Number(endian.parse(v))) + .map(|v| Datum::Number(endian.parse(v))) .collect(); let range = range.map(|(low, high)| { @@ -1201,7 +1201,7 @@ impl MissingValues { let width = width.min(8) as usize; let values = values .into_iter() - .map(|value| Value::String(RawString::from(&value[..width]))) + .map(|value| Datum::String(RawString::from(&value[..width]))) .collect(); return Ok(Self { values, @@ -1463,9 +1463,9 @@ impl VariableRecord { } #[derive(Copy, Clone)] -pub struct UntypedValue(pub [u8; 8]); +pub struct UntypedDatum(pub [u8; 8]); -impl Debug for UntypedValue { +impl Debug for UntypedDatum { fn fmt(&self, f: &mut Formatter) -> FmtResult { let little: f64 = Endian::Little.parse(self.0); let little = format!("{:?}", little); @@ -1724,7 +1724,7 @@ where V: Debug, S: Debug, { - pub value: Value, + pub datum: Datum, pub label: S, } @@ -1796,7 +1796,7 @@ impl ValueLabelRecord, RawString> { let mut labels = Vec::new(); for _ in 0..n { - let value = UntypedValue(read_bytes(r)?); + let value = UntypedDatum(read_bytes(r)?); let label_len: u8 = endian.parse(read_bytes(r)?); let label_len = label_len as usize; let padded_len = Integer::next_multiple_of(&(label_len + 1), &8); @@ -1872,7 +1872,7 @@ impl ValueLabelRecord, RawString> { let labels = labels .into_iter() .map(|(value, label)| ValueLabel { - value: Value::from_raw(&value, var_type, endian), + datum: Datum::from_raw(&value, var_type, endian), label, }) .collect(); @@ -1890,10 +1890,15 @@ impl ValueLabelRecord, RawString> { let labels = self .labels .iter() - .map(|ValueLabel { value, label }| ValueLabel { - value: value.clone(), - label: decoder.decode(label).to_string(), - }) + .map( + |ValueLabel { + datum: value, + label, + }| ValueLabel { + datum: value.clone(), + label: decoder.decode(label).to_string(), + }, + ) .collect(); ValueLabelRecord { offsets: self.offsets.clone(), -- 2.30.2