Skip to content

Commit

Permalink
Deduplicate Visitor code
Browse files Browse the repository at this point in the history
  • Loading branch information
sgeisler committed May 15, 2020
1 parent 88bf5b3 commit 6356ba4
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 140 deletions.
107 changes: 14 additions & 93 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,54 +215,14 @@ impl ::serde::Serialize for SecretKey {
impl<'de> ::serde::Deserialize<'de> for SecretKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
struct HexVisitor;

impl<'de> ::serde::de::Visitor<'de> for HexVisitor {
type Value = SecretKey;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a hex string representing 32 byte SecretKey")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
if let Ok(hex) = str::from_utf8(v) {
str::FromStr::from_str(hex).map_err(E::custom)
} else {
Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
}
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
str::FromStr::from_str(v).map_err(E::custom)
}
}

d.deserialize_str(HexVisitor)
d.deserialize_str(crate::serde_util::HexVisitor::new(
"a hex string representing 32 byte SecretKey"
))
} else {
struct BytesVisitor;

impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
type Value = SecretKey;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("raw 32 bytes SecretKey")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
SecretKey::from_slice(v).map_err(E::custom)
}
}

d.deserialize_bytes(BytesVisitor)
d.deserialize_bytes(crate::serde_util::BytesVisitor::new(
"raw 32 bytes SecretKey",
SecretKey::from_slice
))
}
}
}
Expand Down Expand Up @@ -459,53 +419,14 @@ impl ::serde::Serialize for PublicKey {
impl<'de> ::serde::Deserialize<'de> for PublicKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
if d.is_human_readable() {
struct HexVisitor;

impl<'de> ::serde::de::Visitor<'de> for HexVisitor {
type Value = PublicKey;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an ASCII hex string")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
if let Ok(hex) = str::from_utf8(v) {
str::FromStr::from_str(hex).map_err(E::custom)
} else {
Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
}
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
str::FromStr::from_str(v).map_err(E::custom)
}
}
d.deserialize_str(HexVisitor)
d.deserialize_str(crate::serde_util::HexVisitor::new(
"an ASCII hex string representing a public key"
))
} else {
struct BytesVisitor;

impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
type Value = PublicKey;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a bytestring")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
PublicKey::from_slice(v).map_err(E::custom)
}
}

d.deserialize_bytes(BytesVisitor)
d.deserialize_bytes(crate::serde_util::BytesVisitor::new(
"a bytestring representing a public key",
PublicKey::from_slice
))
}
}
}
Expand Down
56 changes: 9 additions & 47 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ pub mod ecdh;
pub mod key;
#[cfg(feature = "recovery")]
pub mod recovery;
#[cfg(feature = "serde")]
mod serde_util;

pub use key::SecretKey;
pub use key::PublicKey;
Expand Down Expand Up @@ -434,54 +436,14 @@ impl ::serde::Serialize for Signature {
impl<'de> ::serde::Deserialize<'de> for Signature {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
struct HexVisitor;

impl<'de> ::serde::de::Visitor<'de> for HexVisitor {
type Value = Signature;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a hex string representing a DER encoded Signature")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
if let Ok(hex) = str::from_utf8(v) {
str::FromStr::from_str(hex).map_err(E::custom)
} else {
Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
}
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
str::FromStr::from_str(v).map_err(E::custom)
}
}

d.deserialize_str(HexVisitor)
d.deserialize_str(crate::serde_util::HexVisitor::new(
"a hex string representing a DER encoded Signature"
))
} else {
struct BytesVisitor;

impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
type Value = Signature;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("raw byte stream, that represents a DER encoded Signature")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
Signature::from_der(v).map_err(E::custom)
}
}

d.deserialize_bytes(BytesVisitor)
d.deserialize_bytes(crate::serde_util::BytesVisitor::new(
"raw byte stream, that represents a DER encoded Signature",
Signature::from_der
))
}
}
}
Expand Down
78 changes: 78 additions & 0 deletions src/serde_util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use core::fmt;
use core::marker::PhantomData;
use core::str;

pub struct HexVisitor<T> {
expectation: &'static str,
_pd: PhantomData<T>,
}

impl<T> HexVisitor<T> {
pub fn new(expectation: &'static str) -> Self {
HexVisitor {
expectation,
_pd: PhantomData
}
}
}

impl<'de, T: str::FromStr> ::serde::de::Visitor<'de> for HexVisitor<T>
where <T as str::FromStr>::Err: fmt::Display
{
type Value = T;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.expectation)
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
if let Ok(hex) = str::from_utf8(v) {
str::FromStr::from_str(hex).map_err(E::custom)
} else {
Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
}
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
str::FromStr::from_str(v).map_err(E::custom)
}
}

pub struct BytesVisitor<F> {
expectation: &'static str,
parse_fn: F,
}

impl<F> BytesVisitor<F> {
pub fn new(expectation: &'static str, parse_fn: F) -> Self {
BytesVisitor {
expectation,
parse_fn
}
}
}

impl<'de, F, T, Err> ::serde::de::Visitor<'de> for BytesVisitor<F>
where F: Fn(&[u8]) -> Result<T, Err>,
Err: fmt::Display
{
type Value = T;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.expectation)
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
(self.parse_fn)(v).map_err(E::custom)
}
}

0 comments on commit 6356ba4

Please sign in to comment.