chiark / gitweb /
materials format: Introduce version type
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 4 May 2022 21:20:40 +0000 (22:20 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 4 May 2022 21:49:04 +0000 (22:49 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/lib.rs
src/materials-format.rs [new file with mode: 0644]
src/prelude.rs

index 4dd7b557f8d83ecb921dafb9b303971e4f166291..3c6b129e8c22686e61718779318b4fe2d5368395 100644 (file)
@@ -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 (file)
index 0000000..84abe90
--- /dev/null
@@ -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<Raw> 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<i32> 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<Ordering>; }
+}
+
+#[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<Version, Unsupported>) {
+      let got = raw.try_into();
+      assert_eq!(&got,&exp);
+
+      let json_r = serde_json::to_string(&R { mformat: raw }).unwrap();
+      let deser: Result<S,_> = 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 ) }
+  }
+}
index b2587aa04d2f3ace395c64a82de297d1b5942f88..37e78ec8b5502252606b1787c683e75435e70414 100644 (file)
@@ -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;