diff --git a/Cargo.lock b/Cargo.lock index 040fcfe..e1311dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,6 +148,7 @@ dependencies = [ "reqwest", "serde", "serde_json", + "serde_yml", "tar", "thiserror", "tokio", @@ -478,9 +479,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "filetime" @@ -490,7 +491,7 @@ checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall", "windows-sys 0.48.0", ] @@ -885,9 +886,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -919,6 +920,12 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libyml" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e281a65eeba3d4503a2839252f86374528f9ceafe6fed97c1d3b52e1fb625c1" + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -927,9 +934,9 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lzma-sys" @@ -944,9 +951,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miette" @@ -1251,15 +1258,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex" version = "1.9.1" @@ -1441,9 +1439,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1539,6 +1537,23 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yml" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ce6afeda22f0b55dde2c34897bce76a629587348480384231205c14b59a01f" +dependencies = [ + "indexmap", + "itoa", + "libyml", + "log", + "memchr", + "ryu", + "serde", + "serde_json", + "tempfile", +] + [[package]] name = "sha1" version = "0.10.5" @@ -1637,15 +1652,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.7.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -2121,6 +2136,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.1" diff --git a/Cargo.toml b/Cargo.toml index 4d0fb2f..03ee8b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ toml-serde = ["toml", "serde"] json-serde = ["serde_json", "serde"] # Enable SourceFile support for deserializing using the "toml_edit" crate toml-edit = ["toml_edit"] +# Enable SourceFile support for deserializing using the "serde_yml" crate +yaml-serde = ["serde_yml", "serde"] # Enable reqwest-based http file fetching remote = ["reqwest", "image"] # On the off-chance native tls roots cause a problem, they can be opted out of @@ -37,6 +39,7 @@ miette = "7.0.0" camino = "1.1.9" toml = { version = "0.8.12", optional = true } serde_json = { version = "1.0.132", optional = true } +serde_yml = { version = "0.0.10", optional = true } serde = { version = "1.0.214", optional = true, features = ["derive"] } tar = { version = "0.4.42", optional = true } zip = { version = "0.6.4", optional = true } diff --git a/src/error.rs b/src/error.rs index 208abb8..6622f2d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -331,4 +331,20 @@ pub enum AxoassetError { #[source] details: toml_edit::TomlError, }, + + /// This error indicates we tried to deserialize some YAML with serde_yml + /// but failed. + #[cfg(feature = "yaml-serde")] + #[error("failed to parse YAML")] + Yaml { + /// The SourceFile we were try to parse + #[source_code] + source: crate::SourceFile, + /// The range the error was found on + #[label] + span: Option, + /// Details of the error + #[source] + details: serde_yml::Error, + }, } diff --git a/src/lib.rs b/src/lib.rs index d01a504..4effa20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,8 @@ pub use remote::AxoClient; pub use reqwest; #[cfg(feature = "json-serde")] pub use serde_json; +#[cfg(feature = "yaml-serde")] +pub use serde_yml; pub use source::SourceFile; pub use spanned::Spanned; #[cfg(feature = "toml-serde")] diff --git a/src/source.rs b/src/source.rs index a5abc29..5594653 100644 --- a/src/source.rs +++ b/src/source.rs @@ -14,6 +14,9 @@ use crate::toml_edit::DocumentMut; #[cfg(feature = "json-serde")] use crate::serde_json; +#[cfg(feature = "yaml-serde")] +use crate::serde_yml; + /// The inner contents of a [`SourceFile`][]. #[derive(Eq, PartialEq)] struct SourceFileInner { @@ -128,6 +131,22 @@ impl SourceFile { Ok(toml) } + /// Try to deserialize the contents of the SourceFile as yaml + #[cfg(feature = "yaml-serde")] + pub fn deserialize_yaml<'a, T: for<'de> serde::Deserialize<'de>>(&self) -> Result { + let yaml = serde_yml::from_str(self.contents()).map_err(|details| { + let span = details + .location() + .and_then(|location| self.span_for_line_col(location.line(), location.column())); + AxoassetError::Yaml { + source: self.clone(), + span, + details, + } + })?; + Ok(yaml) + } + /// Get the filename of a SourceFile pub fn filename(&self) -> &str { &self.inner.filename diff --git a/tests/source.rs b/tests/source.rs index 5f72c09..f944f0e 100644 --- a/tests/source.rs +++ b/tests/source.rs @@ -198,3 +198,53 @@ goodbye = panic!("span was invalid"); }; } + +#[test] +#[cfg(feature = "yaml-serde")] +fn yaml_valid() { + #[derive(serde::Deserialize, PartialEq, Eq, Debug)] + struct MyType { + hello: String, + goodbye: bool, + } + + // Make the file + let contents = String::from( + r##" +hello: "there" +goodbye: true +"##, + ); + let source = axoasset::SourceFile::new("file.yaml", contents); + + let res = source.deserialize_yaml::().unwrap(); + assert_eq!(res.hello, "there"); + assert_eq!(res.goodbye, true); +} + +#[test] +#[cfg(feature = "yaml-serde")] +fn yaml_invalid() { + use axoasset::AxoassetError; + + #[derive(serde::Deserialize, PartialEq, Eq, Debug)] + struct MyType { + hello: String, + goodbye: bool, + } + + // Make the file + let contents = String::from( + r##" +hello: "there" +goodbye: "this shouldn't be a string" +"##, + ); + let source = axoasset::SourceFile::new("file.yml", contents); + + let res = source.deserialize_yaml::(); + assert!(res.is_err()); + let Err(AxoassetError::Yaml { span: Some(_), .. }) = res else { + panic!("span was invalid"); + }; +}