From 100414bfb345dd6239a08aeeb437884c9616ece6 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 4 May 2022 22:20:40 +0100 Subject: [PATCH] materials format: Introduce version type Signed-off-by: Ian Jackson --- src/lib.rs | 1 + src/materials-format.rs | 117 ++++++++++++++++++++++++++++++++++++++++ src/prelude.rs | 5 ++ 3 files changed, 123 insertions(+) create mode 100644 src/materials-format.rs diff --git a/src/lib.rs b/src/lib.rs index 4dd7b557..3c6b129e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,6 +62,7 @@ pub mod utils; #[path = "fake-rng.rs"] pub mod fake_rng; #[path = "fake-time.rs"] pub mod fake_time; +#[path = "materials-format.rs"] pub mod materials_format; #[path = "shapelib-toml.rs"] pub mod shapelib_toml; #[path = "slotmap-slot-idx.rs"] pub mod slotmap_slot_idx; #[path = "toml-de.rs"] pub mod toml_de; diff --git a/src/materials-format.rs b/src/materials-format.rs new file mode 100644 index 00000000..84abe90b --- /dev/null +++ b/src/materials-format.rs @@ -0,0 +1,117 @@ +// Copyright 2020-2021 Ian Jackson and contributors to Otter +// SPDX-License-Identifier: AGPL-3.0-or-later +// There is NO WARRANTY. + +use crate::prelude::*; + +#[derive(Debug,Copy,Clone,Display,Deref,Serialize,Deserialize,Into)] +#[derive(Eq,PartialEq,Ord,PartialOrd)] +#[display(fmt="{}", _0)] +#[serde(try_from="Raw", into="Raw")] +pub struct Version(Raw); + +pub type Raw = u32; + +impl Version { + pub const MIN: Raw = 1; + pub const MAX: Raw = 1; + pub const CURRENT: Raw = 1; +} + +// The version from before we invented this versioning scheme +impl Default for Version { + fn default() -> Self { Self(1) } +} + +#[derive(Error,Debug,Copy,Clone,Serialize,Deserialize)] +#[derive(Eq,PartialEq,Ord,PartialOrd)] +#[error(r#"unsupported bundle, library or spec format version "format={0}""#)] +pub struct Unsupported(u32); + +#[derive(Error,Debug,Clone,Copy,Serialize,Deserialize)] +#[derive(Eq,PartialEq)] +pub enum VersionError { + #[error("{0}")] + Unsupported(#[from] Unsupported), + #[error("bad format version (must be a reasonable integer): {0}")] + Other(&'static str), +} + +impl TryFrom for Version { + type Error = Unsupported; + #[throws(Unsupported)] + fn try_from(raw: Raw) -> Self { + if raw >= Self::MIN && raw <= Self::MAX { + Version(raw) + } else { + throw!(Unsupported(raw)); + } + } +} + +macro_rules! impl_compar_i32 { { + $( + impl $Trait:ident { fn $method:ident -> $out:ty; } + )* +} => { + $( + impl $Trait for Version { + fn $method(&self, rhs: &i32) -> $out { + let lhs = i64::from(self.0); + let rhs = i64::from(*rhs); + lhs.$method(&rhs) + } + } + )* +} } +impl_compar_i32! { + impl PartialEq { fn eq -> bool; } + impl PartialOrd { fn partial_cmp -> Option; } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn ser_deser() { + #[derive(Debug,Deserialize,Serialize,Eq,PartialEq,Copy,Clone)] + struct S { + mformat: Version, + } + #[derive(Debug,Deserialize,Serialize,Eq,PartialEq,Copy,Clone)] + struct R { + mformat: Raw, + } + + fn check(raw: Raw, exp: Result) { + let got = raw.try_into(); + assert_eq!(&got,&exp); + + let json_r = serde_json::to_string(&R { mformat: raw }).unwrap(); + let deser: Result = serde_json::from_str(&json_r); + assert_eq!{ exp.ok().map(|e| S { mformat: e }), deser.ok() } + + if let Ok(got) = got { + let json_s = serde_json::to_string(&S { mformat: got }).unwrap(); + assert_eq!{ json_s, json_r } + } + } + + let eus = |raw| Err(Unsupported(raw)); + + check(0, eus(0)); + check(1, Ok(Version(1))); + check(2, eus(02)); + } + + #[test] + fn compar() { + let one = Version::try_from(1).unwrap(); + assert!{ one > 0 } assert!{ !( one <= 0 ) } + assert!{ one >= 1 } assert!{ !( one < 1 ) } + assert!{ one == 1 } assert!{ !( one != 1 ) } + assert!{ one <= 1 } assert!{ !( one > 1 ) } + assert!{ one < 2 } assert!{ !( one >= 2 ) } + } +} diff --git a/src/prelude.rs b/src/prelude.rs index b2587aa0..37e78ec8 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -165,6 +165,7 @@ pub use crate::global::*; pub use crate::hidden::*; pub use crate::keydata::*; pub use crate::nwtemplates; +pub use crate::materials_format; pub use crate::mgmtchannel::*; pub use crate::occultilks::*; pub use crate::organise; @@ -230,6 +231,10 @@ pub type OccK = OccultationKind; pub use OccultationKindGeneral as OccKG; pub use OccultationKindAlwaysOk as OccKA; +// materials-format.rs + +pub use materials_format::VersionError as MFVE; + // occultilks.rs pub type LOI = LOccultIlk; pub type IOI = IOccultIlk; -- 2.30.2