use core::fmt;
#[non_exhaustive]
#[repr(u8)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "js", derive(tsify::Tsify))]
pub enum Scale {
#[default]
TAI,
TT,
ET,
TDB,
UTC,
UTCSpice,
UTCSofa,
GPS,
GST,
BDT,
QZSS,
TCG,
TCB,
LTC,
TCL,
Custom,
}
impl Scale {
#[inline]
pub const fn is_tai(&self) -> bool {
matches!(self, Self::TAI)
}
#[inline]
pub const fn to_utc(&self) -> Self {
if self.uses_leap_seconds() {
*self
} else {
Scale::UTC
}
}
#[inline]
pub const fn uses_leap_seconds(&self) -> bool {
matches!(self, Self::UTC | Self::UTCSpice | Self::UTCSofa)
}
#[inline]
pub const fn is_gnss(&self) -> bool {
matches!(self, Self::GPS | Self::GST | Self::BDT | Self::QZSS)
}
pub fn from_abbrev(s: &str) -> Option<Self> {
let bytes = s.as_bytes();
if !bytes.is_ascii() {
return None;
}
let mut buf = [0u8; 8];
let mut len = 0;
for &byte in bytes {
if len >= 8 {
return None;
}
buf[len] = if byte.is_ascii_lowercase() {
byte - 32
} else {
byte
};
len += 1;
}
let upper = core::str::from_utf8(&buf[..len]).ok()?;
match upper {
"TAI" => Some(Self::TAI),
"TT" => Some(Self::TT),
"ET" => Some(Self::ET),
"TDB" => Some(Self::TDB),
"UTC" => Some(Self::UTC),
"UTCSPICE" => Some(Self::UTCSpice),
"UTCSOFA" => Some(Self::UTCSofa),
"GPS" => Some(Self::GPS),
"GST" => Some(Self::GST),
"BDT" => Some(Self::BDT),
"QZSS" => Some(Self::QZSS),
"TCG" => Some(Self::TCG),
"TCB" => Some(Self::TCB),
"LTC" => Some(Self::LTC),
"TCL" => Some(Self::TCL),
"CUSTOM" => Some(Self::Custom),
_ => None,
}
}
pub const fn abbrev(&self) -> &'static str {
match self {
Self::TAI => "TAI",
Self::TT => "TT",
Self::ET => "ET",
Self::TDB => "TDB",
Self::UTC => "UTC",
Self::UTCSpice => "UTCSPICE",
Self::UTCSofa => "UTCSOFA",
Self::TCG => "TCG",
Self::TCB => "TCB",
Self::GPS => "GPS",
Self::GST => "GST",
Self::BDT => "BDT",
Self::QZSS => "QZSS",
Self::LTC => "LTC",
Self::TCL => "TCL",
Self::Custom => "CUSTOM",
}
}
#[inline]
pub const fn eq(self, other: Self) -> bool {
self.to_wire_byte() == other.to_wire_byte()
}
pub const WIRE_SIZE: usize = 1;
pub const fn from_u8(v: u8) -> Self {
match v {
0 => Self::TAI,
1 => Self::TT,
2 => Self::ET,
3 => Self::TDB,
4 => Self::UTC,
5 => Self::UTCSpice,
6 => Self::UTCSofa,
7 => Self::GPS,
8 => Self::GST,
9 => Self::BDT,
10 => Self::QZSS,
11 => Self::TCG,
12 => Self::TCB,
13 => Self::LTC,
14 => Self::TCL,
_ => Self::Custom,
}
}
#[inline]
pub const fn to_wire_byte(self) -> u8 {
self as u8
}
}
impl fmt::Display for Scale {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.abbrev())
}
}