#[serde_with::serde_as]
#[derive(Clone,Copy,PartialEq,Eq,PartialOrd,Ord,serde::Deserialize,serde::Serialize)]
#[serde(transparent)]
pub struct InfoHash(
#[serde_as(as="serde_with::hex::Hex")] [u8; 20],
);
impl InfoHash {
#[cfg(test)]
pub fn example() -> Self {
Self([0u8; 20])
}
}
impl std::str::FromStr for InfoHash {
type Err = anyhow::Error;
fn from_str(s: &str) -> anyhow::Result<Self> {
anyhow::ensure!(
s.len() == 40 && s.is_ascii(),
"info hash must be 40 ASCII hex chars, got {:?}", s);
let mut bytes = [0u8; 20];
for (i, byte) in bytes.iter_mut().enumerate() {
*byte = u8::from_str_radix(&s[i*2..i*2+2], 16)?;
}
Ok(InfoHash(bytes))
}
}
impl std::fmt::Display for InfoHash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for b in self.0 {
write!(f, "{:02x}", b)?;
}
Ok(())
}
}
impl std::fmt::Debug for InfoHash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "InfoHash({})", self)
}
}