use std::fmt;
use std::ops;
use hex::{FromHex, FromHexError, ToHex};
use serde::de::{self, Deserialize, Deserializer, Visitor};
use serde::ser::{self, Serialize, Serializer};
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Default)]
pub struct Oid([u8; 20]);
impl Oid {
pub fn from_hex(s: &str) -> Result<Self, ()> {
Ok(Oid(<[u8; 20]>::from_hex(s).map_err(|_| ())?))
}
pub fn empty_tree() -> Oid {
Oid([
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60, 0xe5,
0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
])
}
pub fn zero() -> Oid {
Oid([
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
])
}
}
impl fmt::UpperHex for Oid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.write_hex_upper(f)
}
}
impl fmt::LowerHex for Oid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.write_hex(f)
}
}
impl fmt::Display for Oid {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<Self as fmt::LowerHex>::fmt(self, f)
}
}
impl fmt::Debug for Oid {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<Self as fmt::Display>::fmt(self, f)
}
}
impl ops::Deref for Oid {
type Target = [u8; 20];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Serialize for Oid {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
let mut hex = String::new();
self.0
.as_ref()
.write_hex(&mut hex)
.map_err(ser::Error::custom)?;
serializer.serialize_str(&hex)
} else {
serializer.serialize_bytes(self.0.as_ref())
}
}
}
impl<'de> Deserialize<'de> for Oid {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct OidVisitor;
impl<'de> Visitor<'de> for OidVisitor {
type Value = Oid;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "hex string or 20 bytes")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
let v = <[u8; 20]>::from_hex(v).map_err(|e| match e {
FromHexError::InvalidHexCharacter { c, .. } => {
E::invalid_value(
de::Unexpected::Char(c),
&"string with only hexadecimal characters",
)
}
FromHexError::InvalidStringLength => E::invalid_length(
v.len(),
&"hex string with a valid length",
),
FromHexError::OddLength => E::invalid_length(
v.len(),
&"hex string with an even length",
),
})?;
Ok(Oid(v))
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
if v.len() != 20 {
return Err(E::invalid_length(v.len(), &"20 bytes"));
}
let mut inner = <[u8; 20]>::default();
inner.copy_from_slice(v);
Ok(Oid(inner))
}
}
if deserializer.is_human_readable() {
deserializer.deserialize_str(OidVisitor)
} else {
deserializer.deserialize_bytes(OidVisitor)
}
}
}