viffy 0.1.5

SoA + SIMD automata generator
Documentation
use crate::Serializable;
use crate::Serializer;

/// Use this for "fake" dates, not for actually storing dates (think EU3-style dates)
#[derive(Default, Clone, Copy, PartialEq, PartialOrd, Debug)]
pub struct AbsoluteDate {
	pub year: u16,
	pub month: u8,
	pub day: u8
}
impl AbsoluteDate {
	pub fn to_relative_date(self, start_date: &AbsoluteDate) -> Result<RelativeDate, Box<dyn std::error::Error>> {
		let yd: u32 = self.year.checked_sub(start_date.year)
			.map(|x| x as u32)
			.ok_or("year is before start date")?;
		let mf: i32 = self.month as i32 - start_date.month as i32;
		let df: i32 = self.day as i32 - start_date.day as i32;
		let md: u32 = [12 + mf, mf][(mf >= 0) as usize].try_into()?;
		let dd: u32 = [30 + df, df][(df >= 0) as usize].try_into()?;
		Ok(RelativeDate(yd * 365 + md * 30 + dd))
	}
	pub fn parse(ident: &str) -> Result<Self, Box<dyn std::error::Error>> {
		let mut parts = ident.split(".");
		let mut f = Self::default();
		f.year = parts.next().unwrap_or_else(|| &"1499").parse::<u16>().unwrap_or_default();
		f.month = parts.next().unwrap_or_else(|| &"1").parse::<u8>().unwrap_or_default();
		f.day = parts.next().unwrap_or_else(|| &"1").parse::<u8>().unwrap_or_default();
		Ok(f)
	}
}
impl Serializable for AbsoluteDate {
	fn serialize(&self, s: &mut Serializer) {
		self.year.serialize(s);
		self.month.serialize(s);
		self.day.serialize(s);
	}
	fn deserialize(&mut self, s: &mut Serializer) {
		self.year.deserialize(s);
		self.month.deserialize(s);
		self.day.deserialize(s);
	}
}

/// This is a relative date w.r.t to an absolute date, use for "fake" dates only
#[derive(Default, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug)]
pub struct RelativeDate(u32);
impl std::ops::Add<u32> for RelativeDate {
	type Output = RelativeDate;
	fn add(self, rhs: u32) -> Self::Output {
		RelativeDate(self.0.add(rhs))
	}
}
impl std::ops::Sub<u32> for RelativeDate {
	type Output = RelativeDate;
	fn sub(self, rhs: u32) -> Self::Output {
		RelativeDate(self.0.sub(rhs))
	}
}
impl From<u8> for RelativeDate { fn from(v: u8) -> Self { Self(v as u32) } }
impl From<u16> for RelativeDate { fn from(v: u16) -> Self { Self(v as u32) } }
impl From<u32> for RelativeDate { fn from(v: u32) -> Self { Self(v as u32) } }
impl From<i8> for RelativeDate { fn from(v: i8) -> Self { Self(v as u32) } }
impl From<i16> for RelativeDate { fn from(v: i16) -> Self { Self(v as u32) } }
impl From<i32> for RelativeDate { fn from(v: i32) -> Self { Self(v as u32) } }
impl Serializable for RelativeDate {
	fn serialize(&self, s: &mut Serializer) {
		self.0.serialize(s);
	}
	fn deserialize(&mut self, s: &mut Serializer) {
		self.0.deserialize(s);
	}
}

impl RelativeDate {
	pub fn to_raw_value(&self) -> u32 {
		self.0
	}
	pub fn to_absolute_date(self, start_date: &AbsoluteDate) -> AbsoluteDate {
		let year = start_date.year as u32 + self.0 / 365;
		let month = (start_date.month as u32 + self.0 / 30) % 12 + 1;
		let day = (start_date.day as u32 + self.0) % 30 + 1;
		AbsoluteDate{
			year: unsafe { year.try_into().unwrap_unchecked() },
			month: unsafe { month.try_into().unwrap_unchecked() },
			day: unsafe { day.try_into().unwrap_unchecked() },
		}
	}
}