use crate::{
multibase::Multibase,
multicodec::{self, Multicodec},
multihash::Multihash,
Error, Result,
};
pub enum Multiformat {
Multibase(Multicodec, Multibase),
Multihash(Multicodec, Multihash),
}
impl Multiformat {
pub fn from_multibase(value: Multibase) -> Result<Multiformat> {
let codec: Multicodec = multicodec::MULTIBASE.into();
Ok(Multiformat::Multibase(codec, value))
}
pub fn from_multihash(value: Multihash) -> Result<Multiformat> {
let codec = value.to_codec();
Ok(Multiformat::Multihash(codec, value))
}
pub fn encode(&self) -> Result<Vec<u8>> {
use Multiformat::*;
let data = match self {
Multibase(codec, mb) => {
let mut out = codec.encode()?;
out.extend(mb.encode()?.as_bytes());
out
}
Multihash(_codec, mh) => {
mh.encode()?
}
};
Ok(data)
}
pub fn decode(buf: &[u8]) -> Result<(Multiformat, &[u8])> {
use std::str::from_utf8;
let (codec, rem) = Multicodec::decode(buf)?;
let (val, rem) = match codec.to_code() {
multicodec::MULTIBASE => {
let val = {
let text = err_at!(BadInput, from_utf8(rem))?;
Multibase::decode(text)?
};
(Multiformat::Multibase(codec, val), &buf[buf.len()..])
}
_ => {
if let Ok((val, rem)) = Multihash::decode(buf) {
(Multiformat::Multihash(codec, val), rem)
} else {
err_at!(BadInput, msg: format!("{}", codec))?
}
}
};
Ok((val, rem))
}
}