use std::io::{Read, Write, Error};
pub trait Serializable {
fn max_serialized_size() -> usize;
fn serialized_size(&self) -> usize;
fn serialize<W: Write>(&self, writer: &mut W) -> Result<usize, SerializationError>;
}
pub trait Deserializable: Sized {
fn deserialize<R: Read>(reader: &mut R) -> Result<Self, DeserializationError>;
}
pub trait Date {
fn year(&self) -> Option<u16>;
fn month(&self) -> Option<u8>;
fn day(&self) -> Option<u8>;
}
pub trait Time {
fn hour(&self) -> Option<u8>;
fn minute(&self) -> Option<u8>;
fn second(&self) -> Option<u8>;
}
pub trait SubSecond {
fn fractional_second(&self) -> FractionalSecond;
}
pub trait Offset {
fn offset(&self) -> OffsetValue;
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum OffsetValue {
None,
SpecifiedElsewhere,
UtcOffset(i16)
}
mod date_only;
mod time_only;
mod date_time;
mod date_time_offset;
mod date_time_subsecond;
mod date_time_subsecond_offset;
mod frac_second;
pub use date_only::DateOnly;
pub use time_only::TimeOnly;
pub use date_time::DateTime;
pub use date_time_offset::DateTimeOffset;
pub use date_time_subsecond::DateTimeSubSecond;
pub use date_time_subsecond_offset::DateTimeSubSecondOffset;
pub use frac_second::FractionalSecond;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CreationError {
InvalidFieldValue,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DeserializationError {
InvalidFieldValue,
IoError,
IncorrectTypeTag,
IncorrectPrecisionTag,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum SerializationError {
IoError
}
pub const YEAR_MIN: u16 = 0;
pub const YEAR_MAX: u16 = 4094;
pub const MONTH_MIN: u8 = 1;
pub const MONTH_MAX: u8 = 12;
pub const DAY_MIN: u8 = 1;
pub const DAY_MAX: u8 = 31;
pub const HOUR_MIN: u8 = 0;
pub const HOUR_MAX: u8 = 23;
pub const MINUTE_MIN: u8 = 0;
pub const MINUTE_MAX: u8 = 59;
pub const SECOND_MIN: u8 = 0;
pub const SECOND_MAX: u8 = 60;
pub const MILLIS_MIN: u16 = 0;
pub const MILLIS_MAX: u16 = 999;
pub const MICROS_MIN: u32 = 0;
pub const MICROS_MAX: u32 = 999_999;
pub const NANOS_MIN: u32 = 0;
pub const NANOS_MAX: u32 = 999_999_999;
pub const OFFSET_MIN: i16 = -(64 * 15);
pub const OFFSET_MAX: i16 = (125 - 64) * 15;
const MONTH_RAW_MIN: u8 = 0;
const MONTH_RAW_MAX: u8 = 11;
const DATE_TAG: u8 = 0b1000_0000;
const TIME_TAG: u8 = 0b1010_0000;
const DATE_TIME_TAG: u8 = 0b0000_0000;
const DATE_TIME_OFFSET_TAG: u8 = 0b1100_0000;
const DATE_TIME_SUBSECOND_TAG: u8 = 0b0100_0000;
const DATE_TIME_SUBSECOND_OFFSET_TAG: u8 = 0b1110_0000;
const PRECISION_DTS_MASK: u8 = 0b0011_0000;
const PRECISION_DTS_MILLIS_TAG: u8 = 0x0;
const PRECISION_DTS_MICROS_TAG: u8 = 0b0001_0000;
const PRECISION_DTS_NANOS_TAG: u8 = 0b0010_0000;
const PRECISION_DTS_NONE_TAG: u8 = 0b0011_0000;
const PRECISION_DTSO_MASK: u8 = PRECISION_DTS_MASK >> 1;
const PRECISION_DTSO_MILLIS_TAG: u8 = PRECISION_DTS_MILLIS_TAG >> 1;
const PRECISION_DTSO_MICROS_TAG: u8 = PRECISION_DTS_MICROS_TAG >> 1;
const PRECISION_DTSO_NANOS_TAG: u8 = PRECISION_DTS_NANOS_TAG >> 1;
const PRECISION_DTSO_NONE_TAG: u8 = PRECISION_DTS_NONE_TAG >> 1;
const YEAR_RAW_NONE: u16 = 4095;
const MONTH_RAW_NONE: u8 = 15;
const DAY_RAW_NONE: u8 = 31;
const HOUR_RAW_NONE: u8 = 31;
const MINUTE_RAW_NONE: u8 = 63;
const SECOND_RAW_NONE: u8 = 63;
const OFFSET_RAW_NONE: u8 = 127;
const OFFSET_RAW_ELSEWHERE: u8 = 126;
#[inline(always)]
fn read_exact<R: Read>(reader: &mut R, buf: &mut [u8]) -> Result<(), DeserializationError> {
reader.read_exact(buf).map_err(|_| DeserializationError::IoError)
}
fn write_array_map_err<W: Write>(bytes: &[u8], writer: &mut W) -> Result<usize, Error> {
writer.write_all(bytes).map(|_| bytes.len())
}
fn check_option_in_range<T: PartialOrd>(val: Option<T>, min: T, max: T, none: T) -> Result<T, CreationError> {
if let Some(v) = val {
return check_in_range(v, min, max, CreationError::InvalidFieldValue);
}
Ok(none)
}
fn check_in_range<T: PartialOrd, E: Copy>(v: T, min: T, max: T, err_val: E)
-> Result<T, E> {
if v < min || v > max {
return Err(err_val)
}
Ok(v)
}
fn check_deser_in_range_or_none<T: PartialOrd>(v: T, min: T, max: T, none: T) -> Result<(), DeserializationError> {
if (v >= min && v <= max) || v == none {
Ok(())
} else {
Err(DeserializationError::InvalidFieldValue)
}
}
#[inline]
fn year_num(year: Option<u16>) -> Result<u16, CreationError> {
check_option_in_range(year, YEAR_MIN, YEAR_MAX, YEAR_RAW_NONE)
}
#[inline]
fn month_num(month: Option<u8>) -> Result<u8, CreationError> {
if let Some(m) = month {
return check_in_range(m, MONTH_MIN, MONTH_MAX, CreationError::InvalidFieldValue).map(|m| m - 1);
}
Ok(MONTH_RAW_NONE)
}
#[inline]
fn day_num(day: Option<u8>) -> Result<u8, CreationError> {
if let Some(d) = day {
return check_in_range(d, DAY_MIN, DAY_MAX, CreationError::InvalidFieldValue).map(|d| d - 1);
}
Ok(DAY_RAW_NONE)
}
#[inline]
fn hour_num(hour: Option<u8>) -> Result<u8, CreationError> {
check_option_in_range(hour, HOUR_MIN, HOUR_MAX, HOUR_RAW_NONE)
}
#[inline]
fn minute_num(minute: Option<u8>) -> Result<u8, CreationError> {
check_option_in_range(minute, MINUTE_MIN, MINUTE_MAX, MINUTE_RAW_NONE)
}
#[inline]
fn second_num(second: Option<u8>) -> Result<u8, CreationError> {
check_option_in_range(second, SECOND_MIN, SECOND_MAX, SECOND_RAW_NONE)
}
#[inline]
fn offset_num(offset: OffsetValue) -> Result<u8, CreationError> {
match offset {
OffsetValue::None => Ok(OFFSET_RAW_NONE),
OffsetValue::SpecifiedElsewhere => Ok(OFFSET_RAW_ELSEWHERE),
OffsetValue::UtcOffset(o) => {
check_in_range(o, OFFSET_MIN, OFFSET_MAX, CreationError::InvalidFieldValue)?;
if o % 15 != 0 {
return Err(CreationError::InvalidFieldValue);
};
Ok(((o / 15) + 64) as u8)
}
}
}
fn check_frac_second(frac_second: FractionalSecond) -> Result<(), CreationError> {
match frac_second {
FractionalSecond::None => {},
FractionalSecond::Milliseconds(ms) => {
check_in_range(ms, MILLIS_MIN, MILLIS_MAX, CreationError::InvalidFieldValue)?;
},
FractionalSecond::Microseconds(us) => {
check_in_range(us, MICROS_MIN, MICROS_MAX, CreationError::InvalidFieldValue)?;
},
FractionalSecond::Nanoseconds(ns) => {
check_in_range(ns, NANOS_MIN, NANOS_MAX, CreationError::InvalidFieldValue)?;
}
}
Ok(())
}