use super::dta::release::Release;
use super::missing_value::MissingValue;
use super::stata_error::{Result, StataError};
const DTA_113_MAX_INT32: i32 = 2_147_483_620;
const MISSING_LONG_SYSTEM_113: u32 = 0x7FFF_FFE5;
const MISSING_LONG_SYSTEM_PRE_113: u32 = 0x7FFF_FFFF;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StataLong {
Present(i32),
Missing(MissingValue),
}
impl StataLong {
pub fn from_raw(raw: u32, release: Release) -> Result<Self> {
let signed = raw.cast_signed();
if release.supports_tagged_missing() {
if signed > DTA_113_MAX_INT32 {
Ok(Self::Missing(MissingValue::try_from(raw)?))
} else {
Ok(Self::Present(signed))
}
} else if raw == MISSING_LONG_SYSTEM_PRE_113 {
Ok(Self::Missing(MissingValue::System))
} else {
Ok(Self::Present(signed))
}
}
pub fn to_raw(self, release: Release) -> Result<u32> {
match self {
Self::Present(v) => Ok(v.cast_unsigned()),
Self::Missing(mv) => {
if release.supports_tagged_missing() {
Ok(MISSING_LONG_SYSTEM_113 + u32::from(mv.code()))
} else if mv == MissingValue::System {
Ok(MISSING_LONG_SYSTEM_PRE_113)
} else {
Err(StataError::TaggedMissingUnsupported)
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn v113_present_zero() {
assert_eq!(
StataLong::from_raw(0_u32, Release::V113).unwrap(),
StataLong::Present(0)
);
}
#[test]
fn v113_present_max() {
assert_eq!(
StataLong::from_raw(0x7FFF_FFE4_u32, Release::V113).unwrap(),
StataLong::Present(2_147_483_620),
);
}
#[test]
fn v113_present_min() {
assert_eq!(
StataLong::from_raw(0x8000_0001_u32, Release::V113).unwrap(),
StataLong::Present(-2_147_483_647),
);
}
#[test]
fn v113_present_negative_one() {
assert_eq!(
StataLong::from_raw(0xFFFF_FFFF_u32, Release::V113).unwrap(),
StataLong::Present(-1),
);
}
#[test]
fn v113_present_i32_min() {
assert_eq!(
StataLong::from_raw(0x8000_0000_u32, Release::V113).unwrap(),
StataLong::Present(i32::MIN),
);
}
#[test]
fn v113_missing_system() {
assert_eq!(
StataLong::from_raw(0x7FFF_FFE5_u32, Release::V113).unwrap(),
StataLong::Missing(MissingValue::System),
);
}
#[test]
fn v113_missing_a() {
assert_eq!(
StataLong::from_raw(0x7FFF_FFE6_u32, Release::V113).unwrap(),
StataLong::Missing(MissingValue::A),
);
}
#[test]
fn v113_missing_z() {
assert_eq!(
StataLong::from_raw(0x7FFF_FFFF_u32, Release::V113).unwrap(),
StataLong::Missing(MissingValue::Z),
);
}
#[test]
fn v104_present_lower_sentinel_is_data() {
assert_eq!(
StataLong::from_raw(0x7FFF_FFE5_u32, Release::V104).unwrap(),
StataLong::Present(2_147_483_621),
);
}
#[test]
fn v104_present_2147483646_is_data() {
assert_eq!(
StataLong::from_raw(0x7FFF_FFFE_u32, Release::V104).unwrap(),
StataLong::Present(2_147_483_646),
);
}
#[test]
fn v104_present_i32_min() {
assert_eq!(
StataLong::from_raw(0x8000_0000_u32, Release::V104).unwrap(),
StataLong::Present(i32::MIN),
);
}
#[test]
fn v104_missing_system() {
assert_eq!(
StataLong::from_raw(0x7FFF_FFFF_u32, Release::V104).unwrap(),
StataLong::Missing(MissingValue::System),
);
}
#[test]
fn v112_missing_system() {
assert_eq!(
StataLong::from_raw(0x7FFF_FFFF_u32, Release::V112).unwrap(),
StataLong::Missing(MissingValue::System),
);
}
#[test]
fn v113_to_raw_present_zero() {
assert_eq!(StataLong::Present(0).to_raw(Release::V113).unwrap(), 0);
}
#[test]
fn v113_to_raw_present_max() {
assert_eq!(
StataLong::Present(2_147_483_620)
.to_raw(Release::V113)
.unwrap(),
0x7FFF_FFE4,
);
}
#[test]
fn v113_to_raw_present_min() {
assert_eq!(
StataLong::Present(-2_147_483_647)
.to_raw(Release::V113)
.unwrap(),
0x8000_0001,
);
}
#[test]
fn v113_to_raw_missing_system() {
assert_eq!(
StataLong::Missing(MissingValue::System)
.to_raw(Release::V113)
.unwrap(),
0x7FFF_FFE5,
);
}
#[test]
fn v104_to_raw_missing_system() {
assert_eq!(
StataLong::Missing(MissingValue::System)
.to_raw(Release::V104)
.unwrap(),
0x7FFF_FFFF,
);
}
#[test]
fn v113_to_raw_missing_a() {
assert_eq!(
StataLong::Missing(MissingValue::A)
.to_raw(Release::V113)
.unwrap(),
0x7FFF_FFE6,
);
}
#[test]
fn v113_to_raw_missing_z() {
assert_eq!(
StataLong::Missing(MissingValue::Z)
.to_raw(Release::V113)
.unwrap(),
0x7FFF_FFFF,
);
}
#[test]
fn v104_to_raw_missing_tagged_errors() {
assert_eq!(
StataLong::Missing(MissingValue::A).to_raw(Release::V104),
Err(StataError::TaggedMissingUnsupported),
);
}
#[test]
fn v112_to_raw_missing_tagged_errors() {
assert_eq!(
StataLong::Missing(MissingValue::Z).to_raw(Release::V112),
Err(StataError::TaggedMissingUnsupported),
);
}
}