serde feature and support

This commit is contained in:
Rowan 2024-10-06 03:00:17 -05:00
parent 3db326a40f
commit 8e97870352
4 changed files with 135 additions and 1 deletions

56
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -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<Self, Self::Error> {
let (algo, hash) = Self::split(value)?;
println!("{algo} {hash}");
Self::from_base64(Algorithm::try_from(algo)?, hash)
}
}

73
src/serialization.rs Normal file
View file

@ -0,0 +1,73 @@
use serde::Serialize;
use crate::Integrity;
impl Serialize for Integrity {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.to_string().as_str())
}
}
impl<'de> serde::Deserialize<'de> for Integrity {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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 <hash-algo>-<base64-hash>")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Integrity::try_from(v).map_err(|_| E::custom("invalid sri"))
}
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Integrity::try_from(v).map_err(|_| E::custom("invalid sri"))
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
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<ValueError> =
"sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO"
.into_deserializer();
let result = Integrity::deserialize(de).unwrap();
assert!(result.verify("alert(\'Hello, world.\');"));
}
}