From 8e978703528187520005b0f5062b8f24a8613190 Mon Sep 17 00:00:00 2001 From: kitsunecafe Date: Sun, 6 Oct 2024 03:00:17 -0500 Subject: [PATCH] serde feature and support --- Cargo.lock | 56 +++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ src/lib.rs | 5 ++- src/serialization.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/serialization.rs diff --git a/Cargo.lock b/Cargo.lock index ff734a7..3c4fd98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,6 +68,44 @@ version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sha2" version = "0.10.8" @@ -84,15 +122,33 @@ name = "subresource_integrity" version = "0.1.0" dependencies = [ "base64", + "serde", "sha2", ] +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + [[package]] name = "version_check" version = "0.9.5" diff --git a/Cargo.toml b/Cargo.toml index 100ee93..4d799f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,9 @@ edition = "2021" [features] default = [] +serde = ["dep:serde"] [dependencies] base64 = "0.22.1" +serde = { version = "1.0.210", features = ["derive"], optional = true } sha2 = "0.10.8" diff --git a/src/lib.rs b/src/lib.rs index 4861751..08472ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "serde")] +pub mod serialization; + use core::fmt; use base64::{prelude::BASE64_STANDARD, Engine}; @@ -11,6 +14,7 @@ pub enum Error { } #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Algorithm { SHA256, SHA384, @@ -102,7 +106,6 @@ impl TryFrom<&str> for Integrity { fn try_from(value: &str) -> Result { let (algo, hash) = Self::split(value)?; - println!("{algo} {hash}"); Self::from_base64(Algorithm::try_from(algo)?, hash) } } diff --git a/src/serialization.rs b/src/serialization.rs new file mode 100644 index 0000000..f490d65 --- /dev/null +++ b/src/serialization.rs @@ -0,0 +1,73 @@ +use serde::Serialize; + +use crate::Integrity; + +impl Serialize for Integrity { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.to_string().as_str()) + } +} + +impl<'de> serde::Deserialize<'de> for Integrity { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_string(IntegrityVisitor) + } +} + +struct IntegrityVisitor; +impl<'de> serde::de::Visitor<'de> for IntegrityVisitor { + type Value = Integrity; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a string with the format of -") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Integrity::try_from(v).map_err(|_| E::custom("invalid sri")) + } + + fn visit_borrowed_str(self, v: &'de str) -> Result + where + E: serde::de::Error, + { + Integrity::try_from(v).map_err(|_| E::custom("invalid sri")) + } + + fn visit_string(self, v: String) -> Result + where + E: serde::de::Error, + { + Integrity::try_from(v).map_err(|_| E::custom("invalid sri")) + } +} + +#[cfg(test)] +mod tests { + use serde::{ + de::{ + value::{Error as ValueError, StrDeserializer}, + IntoDeserializer, + }, + Deserialize, + }; + + use crate::Integrity; + + #[test] + fn serde_deserialization() { + let de: StrDeserializer = + "sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO" + .into_deserializer(); + let result = Integrity::deserialize(de).unwrap(); + assert!(result.verify("alert(\'Hello, world.\');")); + } +}