use core::fmt;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum Code {
E0001,
E0002,
E0003,
E0004,
E0005,
E0006,
E0007,
E0010,
E0011,
E0012,
E0013,
E0020,
E0021,
E0022,
E0023,
E0024,
E0025,
E0030,
E0031,
E0032,
E0040,
E0041,
E0042,
E0043,
E0050,
E0060,
E0061,
E0062,
E0063,
E0064,
E0065,
E0070,
E0071,
E0080,
}
impl Code {
pub const fn as_str(self) -> &'static str {
match self {
Code::E0001 => "UCAL-E0001",
Code::E0002 => "UCAL-E0002",
Code::E0003 => "UCAL-E0003",
Code::E0004 => "UCAL-E0004",
Code::E0005 => "UCAL-E0005",
Code::E0006 => "UCAL-E0006",
Code::E0007 => "UCAL-E0007",
Code::E0010 => "UCAL-E0010",
Code::E0011 => "UCAL-E0011",
Code::E0012 => "UCAL-E0012",
Code::E0013 => "UCAL-E0013",
Code::E0020 => "UCAL-E0020",
Code::E0021 => "UCAL-E0021",
Code::E0022 => "UCAL-E0022",
Code::E0023 => "UCAL-E0023",
Code::E0024 => "UCAL-E0024",
Code::E0025 => "UCAL-E0025",
Code::E0030 => "UCAL-E0030",
Code::E0031 => "UCAL-E0031",
Code::E0032 => "UCAL-E0032",
Code::E0040 => "UCAL-E0040",
Code::E0041 => "UCAL-E0041",
Code::E0042 => "UCAL-E0042",
Code::E0043 => "UCAL-E0043",
Code::E0050 => "UCAL-E0050",
Code::E0060 => "UCAL-E0060",
Code::E0061 => "UCAL-E0061",
Code::E0062 => "UCAL-E0062",
Code::E0063 => "UCAL-E0063",
Code::E0064 => "UCAL-E0064",
Code::E0065 => "UCAL-E0065",
Code::E0070 => "UCAL-E0070",
Code::E0071 => "UCAL-E0071",
Code::E0080 => "UCAL-E0080",
}
}
pub const fn describe(self) -> &'static str {
match self {
Code::E0001 => "malformed timestamp",
Code::E0002 => "unknown profile tag",
Code::E0003 => "mixed text forms in one string",
Code::E0004 => "group value out of range (> 3124)",
Code::E0005 => "invalid base-5 digit",
Code::E0006 => "non-contiguous tier sequence",
Code::E0007 => "calendar rendering without a kind/id qualifier",
Code::E0010 => "locale table load failure",
Code::E0011 => "duplicate name in the active locale table",
Code::E0012 => "unknown key in HJSON data file",
Code::E0013 => "profile lacks a datum_provenance record",
Code::E0020 => "result precedes the datum",
Code::E0021 => "result exceeds DOMAIN",
Code::E0022 => "window inversion, lo > hi",
Code::E0023 => "comparison indeterminate at stated precision",
Code::E0024 => "lossy rendering requested without a rounding mode",
Code::E0025 => "BIG_BANG_CLAIM used as a computational operand",
Code::E0030 => "binary form is not 64 bytes",
Code::E0031 => "instant outside UCID range",
Code::E0032 => "invalid Crockford base-32",
Code::E0040 => "civil date outside renderable range",
Code::E0041 => "invalid civil date for the stated calendar",
Code::E0042 => "second = 60 outside a leap-second instant",
Code::E0043 => "foreign-unit input finer than the bridge constant permits",
Code::E0050 => "profile mismatch",
Code::E0060 => "body parameter missing required provenance or as-measured value",
Code::E0061 => "leap-rule derivation cannot meet the requested drift bound",
Code::E0062 => "calendar has no anchor; local fields cannot be produced",
Code::E0063 => "anchor phase definition not evaluable for this body",
Code::E0064 => "grouping cycle requested but none derivable from any satellite",
Code::E0065 => "legacy calendar supplied where a derived calendar is required",
Code::E0070 => "division by zero or by an interval containing zero",
Code::E0071 => "requested enclosure width unreachable at the permitted depth",
Code::E0080 => "tier index outside the profile grid",
}
}
pub const fn exit_code(self) -> u8 {
match self {
Code::E0001
| Code::E0002
| Code::E0003
| Code::E0004
| Code::E0005
| Code::E0006
| Code::E0007
| Code::E0032 => 2,
Code::E0020 | Code::E0021 | Code::E0022 | Code::E0030 | Code::E0031
| Code::E0080 => 3,
Code::E0023 | Code::E0024 | Code::E0043 => 4,
Code::E0040 | Code::E0041 | Code::E0042 => 2,
Code::E0050 => 5,
Code::E0060 | Code::E0061 | Code::E0062 | Code::E0063 | Code::E0064
| Code::E0065 => 7,
Code::E0070 | Code::E0071 => 8,
Code::E0010 | Code::E0011 | Code::E0012 | Code::E0013 => 6,
Code::E0025 => 9,
}
}
}
impl fmt::Display for Code {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.as_str(), self.describe())
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct TimeError {
pub code: Code,
pub context: Option<&'static str>,
}
impl TimeError {
pub const fn new(code: Code) -> Self {
TimeError {
code,
context: None,
}
}
pub const fn with_context(code: Code, context: &'static str) -> Self {
TimeError {
code,
context: Some(context),
}
}
}
impl fmt::Display for TimeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.context {
None => write!(f, "{}", self.code),
Some(c) => write!(f, "{} ({c})", self.code),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for TimeError {}
pub type Result<T> = core::result::Result<T, TimeError>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum Warning {
W0001,
W0002,
W0003,
W0004,
W0005,
W0006,
}
impl Warning {
pub const fn as_str(self) -> &'static str {
match self {
Warning::W0001 => "UCAL-W0001",
Warning::W0002 => "UCAL-W0002",
Warning::W0003 => "UCAL-W0003",
Warning::W0004 => "UCAL-W0004",
Warning::W0005 => "UCAL-W0005",
Warning::W0006 => "UCAL-W0006",
}
}
pub const fn describe(self) -> &'static str {
match self {
Warning::W0001 => "precision loss in the requested rendering",
Warning::W0002 => "leap-second table may be stale; bounded error reported",
Warning::W0003 => "body parameter evaluated outside its validity window",
Warning::W0004 => "cosmology enclosure width exceeds one tick",
Warning::W0005 => "value produced by a legacy (non-derived) calendar",
Warning::W0006 => "quantity comparable to or smaller than BIG_BANG_CLAIM",
}
}
}
impl fmt::Display for Warning {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.as_str(), self.describe())
}
}