diff --git a/Cargo.toml b/Cargo.toml index e1939ac..2f25f76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsondb" -version = "0.3.1" +version = "0.3.2" edition = "2021" authors = ["xenofem "] license = "MIT" diff --git a/src/lib.rs b/src/lib.rs index 2b2b3e2..fd53ff2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,8 +100,10 @@ impl Schema for T { if version != 0 { return Err(Error::UnknownVersion(version)); } + Ok(serde_json::from_str::>(s)?.data) + } else { + Ok(serde_json::from_str(s)?) } - Ok(serde_json::from_str(s)?) } } @@ -297,7 +299,7 @@ impl JsonDb { #[cfg(test)] mod tests { - use std::fs::File; + use std::{collections::HashMap, fs::File}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -520,4 +522,97 @@ mod tests { assert_eq!(&value["last_updated"], "2022-08-15T17:47:18Z"); } } + + #[test] + fn catchall_schema_v0() { + #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)] + struct Catchall(HashMap); + impl SchemaV0 for Catchall {} + + let mut data = HashMap::new(); + data.insert("hello".into(), "world".into()); + data.insert("catch".into(), "all".into()); + + assert_eq!( + Catchall::parse(r#"{"version":0,"hello":"world","catch":"all"}"#).unwrap(), + Catchall(data) + ) + } + + #[test] + fn catchall_schema_v1_v2() { + #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)] + struct Catchall0(HashMap); + impl SchemaV0 for Catchall0 {} + + #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)] + struct Catchall1 { + count: usize, + #[serde(flatten)] + data: HashMap, + } + impl Schema for Catchall1 { + type Prev = Catchall0; + } + impl From for Catchall1 { + fn from(old: Catchall0) -> Self { + Catchall1 { + data: old.0, + count: 0, + } + } + } + + #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)] + struct Catchall2 { + count: usize, + name: String, + #[serde(flatten)] + data: HashMap, + } + impl Schema for Catchall2 { + type Prev = Catchall1; + } + impl From for Catchall2 { + fn from(old: Catchall1) -> Self { + Catchall2 { + data: old.data, + count: old.count, + name: String::new(), + } + } + } + + let mut data = HashMap::new(); + data.insert("hello".into(), "world".into()); + data.insert("catch".into(), "all".into()); + + assert_eq!( + Catchall2::parse(r#"{"version":1,"count":42,"hello":"world","catch":"all"}"#).unwrap(), + Catchall2 { + data, + count: 42, + name: String::new(), + }, + ) + } + + #[test] + fn unversioned() { + #[derive(Debug, PartialEq, Eq, Deserialize, Serialize)] + struct Data { + number: usize, + truth: bool, + } + impl SchemaV0 for Data { + const EXPECT_VERSION_NUMBER: bool = false; + } + assert_eq!( + Data::parse(r#"{"number":42,"truth":true}"#).unwrap(), + Data { + number: 42, + truth: true, + }, + ); + } }