Skip to content

Commit

Permalink
Merge 0644ece into 87cc5af
Browse files Browse the repository at this point in the history
  • Loading branch information
Benno committed Aug 3, 2022
2 parents 87cc5af + 0644ece commit 7cad180
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Cargo.toml
Expand Up @@ -9,6 +9,10 @@ license = "MIT OR BSD-3-Clause"
readme = "README.md"
repository = "https://github.com/maidsafe/xor_name"

[features]
# Serialize `XorName` into a hex string if serializing into human-readable format
serialize-hex = ["hex"]

[dependencies]
rand_core = "0.6.3"

Expand All @@ -26,6 +30,10 @@ rand_core = "0.6.3"
default-features = false
features = [ "derive" ]

[dependencies.hex]
version = "0.4"
optional = true

[dev-dependencies]
bincode = "1.2.1"

Expand Down
6 changes: 5 additions & 1 deletion src/lib.rs
Expand Up @@ -57,6 +57,7 @@ use core::{cmp::Ordering, fmt, ops};
pub use prefix::Prefix;
pub use rand;
use rand::distributions::{Distribution, Standard};
#[cfg(not(feature = "serialize-hex"))]
use serde::{Deserialize, Serialize};
use tiny_keccak::{Hasher, Sha3};

Expand Down Expand Up @@ -91,6 +92,8 @@ macro_rules! format {
}

mod prefix;
#[cfg(feature = "serialize-hex")]
mod serialize;

/// Constant byte length of `XorName`.
pub const XOR_NAME_LEN: usize = 32;
Expand All @@ -103,7 +106,8 @@ pub const XOR_NAME_LEN: usize = 32;
/// i. e. the points with IDs `x` and `y` are considered to have distance `x xor y`.
///
/// [1]: https://en.wikipedia.org/wiki/Kademlia#System_details
#[derive(Eq, Copy, Clone, Default, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
#[derive(Eq, Copy, Clone, Default, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(not(feature = "serialize-hex"), derive(Serialize, Deserialize))]
pub struct XorName(pub [u8; XOR_NAME_LEN]);

impl XorName {
Expand Down
75 changes: 75 additions & 0 deletions src/serialize.rs
@@ -0,0 +1,75 @@
use crate::XorName;
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::fmt;

impl Serialize for XorName {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// Return string with hexadecimal representation
if serializer.is_human_readable() {
return serializer.serialize_str(&hex::encode(self.0));
}

// Default serialization.
serializer.serialize_newtype_struct("XorName", &self.0)
}
}

impl<'de> Deserialize<'de> for XorName {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
if deserializer.is_human_readable() {
return deserializer.deserialize_str(HexStrOrNewtype);
}

deserializer.deserialize_newtype_struct("XorName", HexStrOrNewtype)
}
}

struct HexStrOrNewtype;
impl<'de> Visitor<'de> for HexStrOrNewtype {
type Value = XorName;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "tuple struct XorName")
}

fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
let buffer = <[u8; 32] as hex::FromHex>::from_hex(s)
.map_err(|e| E::custom(std::format!("hex decoding ({})", e)))?;
Ok(XorName(buffer))
}

fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
Ok(XorName(<[u8; 32] as Deserialize>::deserialize(
deserializer,
)?))
}

// A method like this was generated (August 2022) by #[derive(Deserialize)], so assumed to be of use
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: de::SeqAccess<'de>,
{
match seq.next_element::<[u8; 32]>()? {
Some(a) => Ok(XorName(a)),
None => Err(de::Error::invalid_length(
0,
&"tuple struct XorName with 1 element",
)),
}
}
}

0 comments on commit 7cad180

Please sign in to comment.