From af1f95c88bcc5dbbab2ab2867f7e8d4a36df151b Mon Sep 17 00:00:00 2001 From: xenofem Date: Mon, 15 Aug 2022 17:02:33 -0400 Subject: [PATCH] more clever version number handling --- src/lib.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f8dd7ad..af5e749 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,9 +47,12 @@ pub struct JsonDb { /// other fields of the corresponding schema version; earlier versions /// will be migrated to the current version automatically. pub trait Schema: DeserializeOwned + Serialize { - const VERSION: u32; + /// Previous schema that can be migrated into the new schema type Prev: Schema + Into; + /// Schema version number + const VERSION: u32 = Self::Prev::VERSION + 1; + fn parse(s: &str) -> Result { let Version { version } = serde_json::from_str(s)?; match version.cmp(&Self::VERSION) { @@ -64,11 +67,25 @@ pub trait Schema: DeserializeOwned + Serialize { /// /// Implementing this will automatically implement [`Schema`], with /// version number `0` and `Self` as the previous version. -pub trait SchemaV0: DeserializeOwned + Serialize {} +pub trait SchemaV0: DeserializeOwned + Serialize { + /// Set this to false if your version 0 is a pre-`JsonDb` schema + /// that does not include a version number. + const EXPECT_VERSION_NUMBER: bool = true; +} impl Schema for T { - const VERSION: u32 = 0; type Prev = Self; + const VERSION: u32 = 0; + + fn parse(s: &str) -> Result { + if Self::EXPECT_VERSION_NUMBER { + let Version { version } = serde_json::from_str(s)?; + if version != 0 { + return Err(Error::UnknownVersion(version)); + } + } + Ok(serde_json::from_str(s)?) + } } #[derive(Deserialize)] @@ -216,7 +233,6 @@ mod tests { last_updated: i64, } impl Schema for V1 { - const VERSION: u32 = 1; type Prev = V0; } impl From for V1 { @@ -248,7 +264,6 @@ mod tests { } } impl Schema for V2 { - const VERSION: u32 = 2; type Prev = V1; } impl From for V2 {