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},
};
}
#[derive(Clone)]
-pub enum Value<S = RawString> {
+pub enum Datum<S = RawString> {
Number(Option<f64>),
String(S),
}
-impl<S> Debug for Value<S>
+impl<S> Debug for Datum<S>
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))) => {
}
}
-impl Eq for Value {}
+impl Eq for Datum {}
-impl PartialOrd for Value {
+impl PartialOrd for Datum {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
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<H: std::hash::Hasher>(&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<Option<f64>> {
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<f64> for Value {
- fn from(value: f64) -> Self {
- Some(value).into()
+impl From<f64> for Datum {
+ fn from(number: f64) -> Self {
+ Some(number).into()
}
}
-impl From<Option<f64>> for Value {
+impl From<Option<f64>> for Datum {
fn from(value: Option<f64>) -> 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())
}
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");
pt
}
- fn get_field_value(
- index: usize,
- variable: &Variable,
- field: VariableField,
- ) -> Option<PivotValue> {
+ fn get_field_value(index: usize, variable: &Variable, field: VariableField) -> Option<Value> {
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)
let mut values = variable.value_labels.iter().collect::<Vec<_>>();
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!()
todo!()
}
- fn get_field_value(
- index: usize,
- variable: &Variable,
- field: VariableField,
- ) -> Option<PivotValue> {
+ fn get_field_value(index: usize, variable: &Variable, field: VariableField) -> Option<Value> {
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)
/// Value labels, to associate a number (or a string) with a more meaningful
/// description, e.g. 1 -> Apple, 2 -> Banana, ...
- pub value_labels: HashMap<Value, String>,
+ pub value_labels: HashMap<Datum, String>,
/// Variable label, an optional meaningful description for the variable
/// itself.
/// 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,
},
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,
}
}
}
-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,
}
}
-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 {
}
}
-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}")?;
}
}
-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,
}
fn to_binary(&self) -> Option<SmallVec<[u8; 16]>> {
- 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)),
use smallvec::SmallVec;
use crate::{
- dictionary::Value,
+ dictionary::Datum,
endian::Endian,
format::{AbstractFormat, Epoch, Format, Settings, Type, UncheckedFormat, CC},
lex::{
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)
}
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
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(),
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)
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 {
}
}
- 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()),
}
}
}
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)),
}
}
}
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},
/// 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<Value, ParseError>
+ pub fn parse<'b, T>(&self, input: T) -> Result<Datum, ParseError>
where
T: Into<EncodedStr<'b>>,
{
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()),
})
}
- fn parse_number(&self, input: &str, type_: Type) -> Result<Value, ParseErrorKind> {
+ fn parse_number(&self, input: &str, type_: Type) -> Result<Datum, ParseErrorKind> {
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<char>) -> &str {
}
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<Value, ParseErrorKind> {
+ fn parse_n(&self, input: &str) -> Result<Datum, ParseErrorKind> {
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<Value, ParseErrorKind> {
+ fn parse_z(&self, input: &str) -> Result<Datum, ParseErrorKind> {
let input = input.trim();
if input.is_empty() || input == "." {
- return Ok(Value::sysmis());
+ return Ok(Datum::sysmis());
}
enum ZChar {
} else {
number
};
- Ok(Value::Number(Some(number)))
+ Ok(Datum::Number(Some(number)))
}
fn parse_bcd(input: &[u8]) -> Result<u128, ParseErrorKind> {
}
}
- fn parse_pk(&self, input: &[u8]) -> Result<Value, ParseErrorKind> {
+ fn parse_pk(&self, input: &[u8]) -> Result<Datum, ParseErrorKind> {
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<Value, ParseErrorKind> {
+ fn parse_p(&self, input: &[u8]) -> Result<Datum, ParseErrorKind> {
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)?;
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 {
}
}
- fn parse_ib(&self, input: &[u8]) -> Result<Value, ParseErrorKind> {
+ fn parse_ib(&self, input: &[u8]) -> Result<Datum, ParseErrorKind> {
let number = self.parse_binary(input);
let sign_bit = 1 << (input.len() * 8 - 1);
let number = if (number & sign_bit) == 0 {
} 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<Value, ParseErrorKind> {
+ fn parse_pib(&self, input: &[u8]) -> Result<Datum, ParseErrorKind> {
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<Value, ParseErrorKind> {
+ fn parse_rb(&self, input: &[u8]) -> Result<Datum, ParseErrorKind> {
let mut bytes = [0; 8];
let len = input.len().min(8);
bytes[..len].copy_from_slice(&input[..len]);
SYSMIS => None,
other => Some(other),
};
- Ok(Value::Number(number))
+ Ok(Datum::Number(number))
}
- fn parse_ahex(&self, input: &str) -> Result<Value, ParseErrorKind> {
+ fn parse_ahex(&self, input: &str) -> Result<Datum, ParseErrorKind> {
let mut result = Vec::with_capacity(input.len() / 2);
let mut iter = input.chars();
while let Some(hi) = iter.next() {
};
result.push((hi * 16 + lo) as u8);
}
- Ok(Value::String(result.into()))
+ Ok(Datum::String(result.into()))
}
fn parse_hex(&self, input: &str) -> Result<Option<u64>, ParseErrorKind> {
}
}
- fn parse_pibhex(&self, input: &str) -> Result<Value, ParseErrorKind> {
+ fn parse_pibhex(&self, input: &str) -> Result<Datum, ParseErrorKind> {
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<Value, ParseErrorKind> {
+ fn parse_rbhex(&self, input: &str) -> Result<Datum, ParseErrorKind> {
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<Value, ParseErrorKind> {
+ fn parse_date(&self, input: &str) -> Result<Datum, ParseErrorKind> {
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;
} else {
date + time
};
- Ok(Value::Number(Some(time_date)))
+ Ok(Datum::Number(Some(time_date)))
}
fn parse_minute_second(&self, p: &mut StrParser<'_>) -> Result<f64, ParseErrorKind> {
Ok(time + seconds)
}
- fn parse_wkday(&self, input: &str) -> Result<Value, ParseErrorKind> {
+ fn parse_wkday(&self, input: &str) -> Result<Datum, ParseErrorKind> {
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<Value, ParseErrorKind> {
+ fn parse_month(&self, input: &str) -> Result<Datum, ParseErrorKind> {
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)))
}
}
}
use crate::{
calendar::{days_in_month, is_leap_year},
- dictionary::Value,
+ dictionary::Datum,
endian::Endian,
format::{
parse::{ParseError, ParseErrorKind, Sign},
.with_settings(&settings)
.parse(&formatted)
.unwrap();
- assert_eq!(parsed, Value::Number(Some(expected as f64)));
+ assert_eq!(parsed, Datum::Number(Some(expected as f64)));
}
}
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);
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}");
let s = [ac, bc].into_iter().collect::<String>();
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' {
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]
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 {
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,
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,
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(),
*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 {
use crate::{
dictionary::{
- Dictionary, InvalidRole, MultipleResponseSet, MultipleResponseType, Value, VarWidth,
+ Dictionary, InvalidRole, MultipleResponseSet, MultipleResponseType, Datum, VarWidth,
Variable, VariableSet,
},
endian::Endian,
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);
}
// 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);
}
}
.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::<Vec<_>>();
variable.missing_values = MissingValues {
number: string.into(),
}
})?;
- Value::Number(Some(number))
+ Datum::Number(Some(number))
}
VarWidth::String(max_width) => {
let mut value = value.0.as_slice();
max_width,
});
};
- Value::String(value.into())
+ Datum::String(value.into())
}
};
Ok(MultipleResponseType::MultipleDichotomy {
- value,
+ datum: value,
labels: *labels,
})
}
use crate::{
- dictionary::{Attributes, Value, VarWidth},
+ dictionary::{Attributes, Datum, VarWidth},
endian::{Endian, Parse, ToBytes},
format::DisplayPlain,
identifier::{Error as IdError, Identifier},
}
}
-type RawValue = Value<RawStrArray<8>>;
+type RawDatum = Datum<RawStrArray<8>>;
-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)),
}
}
});
}
};
- values.push(Value::from_raw(&UntypedValue(raw), var_type, endian));
+ values.push(Datum::from_raw(&UntypedDatum(raw), var_type, endian));
}
Ok(Some(values))
}
}
}
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
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]))
}
}
}
}
impl Iterator for Cases {
- type Item = Result<Vec<RawValue>, Error>;
+ type Item = Result<Vec<RawDatum>, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.eof {
}
let retval = if self.compression.is_some() {
- Value::read_compressed_case(
+ Datum::read_compressed_case(
&mut self.reader,
&self.var_types,
&mut self.codes,
)
.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
#[derive(Clone, Default)]
pub struct MissingValues {
/// Individual missing values, up to 3 of them.
- pub values: Vec<Value>,
+ pub values: Vec<Datum>,
/// Optional range of missing values.
pub range: Option<MissingValueRange>,
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,
}
}
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)| {
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,
}
#[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);
V: Debug,
S: Debug,
{
- pub value: Value<V>,
+ pub datum: Datum<V>,
pub label: S,
}
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);
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();
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(),