aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml6
-rw-r--r--src/lib.rs7
-rw-r--r--src/test.rs28
3 files changed, 37 insertions, 4 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 036a39b..3ce2454 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -42,6 +42,8 @@ mmap = ["std", "dep:memmap2"]
# Implement the zeroize::Zeroize trait for types in this crate.
zeroize = ["dep:zeroize", "arrayvec/zeroize"]
+serde = ["dep:serde", "dep:serde_bytes"]
+
# This crate implements traits from the RustCrypto project, exposed here as the
# "traits-preview" feature. However, these traits aren't stable, and they're
# expected to change in incompatible ways before they reach 1.0. For that
@@ -49,7 +51,7 @@ zeroize = ["dep:zeroize", "arrayvec/zeroize"]
# who use it should expect breaking changes between patch versions of this
# crate. (The "*-preview" feature name follows the conventions of the RustCrypto
# "signature" crate.)
-traits-preview = ["digest"]
+traits-preview = ["dep:digest"]
# ---------- Features below this line are undocumented and unstable. ----------
# The following features are mainly intended for testing and benchmarking, and
@@ -103,6 +105,7 @@ digest = { version = "0.10.1", features = [ "mac" ], optional = true }
memmap2 = { version = "0.9", optional = true }
rayon-core = { version = "1.12.1", optional = true }
serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }
+serde_bytes = { version = "0.11.15", optional = true }
zeroize = { version = "1", default-features = false, features = ["zeroize_derive"], optional = true }
[dev-dependencies]
@@ -114,6 +117,7 @@ rand_chacha = "0.3.0"
reference_impl = { path = "./reference_impl" }
tempfile = "3.8.0"
serde_json = "1.0.107"
+ciborium = "0.2.2"
[build-dependencies]
cc = "1.0.4"
diff --git a/src/lib.rs b/src/lib.rs
index d64e18f..e6a9d67 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -219,7 +219,12 @@ fn counter_high(counter: u64) -> u32 {
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Copy, Hash)]
-pub struct Hash([u8; OUT_LEN]);
+pub struct Hash(
+ #[rustfmt::skip]
+ // In formats like CBOR, bytestrings are more compact than lists of ints.
+ #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
+ [u8; OUT_LEN],
+);
impl Hash {
/// The raw bytes of the `Hash`. Note that byte arrays don't provide
diff --git a/src/test.rs b/src/test.rs
index c76cbbc..b5bd4dc 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -809,14 +809,38 @@ fn test_mmap_rayon() -> Result<(), std::io::Error> {
#[cfg(feature = "std")]
#[cfg(feature = "serde")]
fn test_serde() {
- let hash: crate::Hash = [7; 32].into();
+ let hash: crate::Hash = [255; 32].into();
+
let json = serde_json::to_string(&hash).unwrap();
assert_eq!(
json,
- "[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7]",
+ "[255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255]",
);
let hash2: crate::Hash = serde_json::from_str(&json).unwrap();
assert_eq!(hash, hash2);
+
+ let mut cbor = Vec::<u8>::new();
+ ciborium::into_writer(&hash, &mut cbor).unwrap();
+ assert_eq!(
+ cbor,
+ [
+ 88, 32, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
+ ]
+ );
+ let hash_from_cbor: crate::Hash = ciborium::from_reader(&cbor[..]).unwrap();
+ assert_eq!(hash_from_cbor, hash);
+
+ // Before we used serde_bytes, the hash [255; 32] would serialize as an array instead of a
+ // byte string, like this. Make sure we can still deserialize this representation.
+ let old_cbor: &[u8] = &[
+ 152, 32, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255,
+ 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255,
+ 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255, 24, 255,
+ 24, 255, 24, 255, 24, 255,
+ ];
+ let hash_from_old_cbor: crate::Hash = ciborium::from_reader(old_cbor).unwrap();
+ assert_eq!(hash_from_old_cbor, hash);
}
// `cargo +nightly miri test` currently works, but it takes forever, because some of our test