diff --git a/Cargo.lock b/Cargo.lock index 496b1335..fb94cf3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -290,6 +290,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +[[package]] +name = "erased-serde" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4adbf0983fe06bd3a5c19c8477a637c2389feb0994eca7a59e3b961054aa7c0a" +dependencies = [ + "serde", +] + [[package]] name = "errno" version = "0.3.1" @@ -649,9 +658,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -734,22 +743,32 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-untagged" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c38885c2d9d8f038478583b7acf8f6029d020ba4b20e9dcaeb8799d67a04aae7" +dependencies = [ + "erased-serde", + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.41", ] [[package]] @@ -768,6 +787,9 @@ name = "serde_spanned" version = "0.6.4" dependencies = [ "serde", + "serde-untagged", + "serde_derive", + "toml 0.8.8", ] [[package]] @@ -829,9 +851,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", diff --git a/crates/serde_spanned/Cargo.toml b/crates/serde_spanned/Cargo.toml index f1a578dc..421dbbf8 100644 --- a/crates/serde_spanned/Cargo.toml +++ b/crates/serde_spanned/Cargo.toml @@ -26,3 +26,9 @@ pre-release-replacements = [ [dependencies] serde = { version = "1.0.145", optional = true } + +[dev-dependencies] +serde = "1" +serde_derive = "1" +serde-untagged = "0.1" +toml = { path = "../toml" } diff --git a/crates/serde_spanned/src/spanned.rs b/crates/serde_spanned/src/spanned.rs index ac351ca8..f4042a86 100644 --- a/crates/serde_spanned/src/spanned.rs +++ b/crates/serde_spanned/src/spanned.rs @@ -35,6 +35,63 @@ pub struct Spanned { } impl Spanned { + /// Create a spanned value encompassing the given byte range. + /// + /// # Example + /// + /// Transposing a `Spanned>` into `Enum>`: + /// + /// ``` + /// use serde::de::{Deserialize, Deserializer}; + /// use serde_untagged::UntaggedEnumVisitor; + /// use toml::Spanned; + /// + /// pub enum Dependency { + /// Simple(Spanned), + /// Detailed(Spanned), + /// } + /// + /// impl<'de> Deserialize<'de> for Dependency { + /// fn deserialize(deserializer: D) -> Result + /// where + /// D: Deserializer<'de>, + /// { + /// enum DependencyKind { + /// Simple(String), + /// Detailed(DetailedDependency), + /// } + /// + /// impl<'de> Deserialize<'de> for DependencyKind { + /// fn deserialize(deserializer: D) -> Result + /// where + /// D: Deserializer<'de>, + /// { + /// UntaggedEnumVisitor::new() + /// .expecting( + /// "a version string like \"0.9.8\" or a \ + /// detailed dependency like { version = \"0.9.8\" }", + /// ) + /// .string(|value| Ok(DependencyKind::Simple(value.to_owned()))) + /// .map(|value| value.deserialize().map(DependencyKind::Detailed)) + /// .deserialize(deserializer) + /// } + /// } + /// + /// let spanned: Spanned = Deserialize::deserialize(deserializer)?; + /// let range = spanned.span(); + /// Ok(match spanned.into_inner() { + /// DependencyKind::Simple(simple) => Dependency::Simple(Spanned::new(range, simple)), + /// DependencyKind::Detailed(detailed) => Dependency::Detailed(Spanned::new(range, detailed)), + /// }) + /// } + /// } + /// # + /// # type DetailedDependency = std::collections::BTreeMap; + /// ``` + pub fn new(range: std::ops::Range, value: T) -> Self { + Spanned { span: range, value } + } + /// Byte range pub fn span(&self) -> std::ops::Range { self.span.clone()