use std::{
convert::{TryFrom, TryInto},
str::FromStr,
};
use dasl::{
cid::Cid,
drisl::{Value, from_slice, to_vec},
};
use serde::{Deserialize, Serialize, de};
use serde_bytes::ByteBuf;
#[test]
fn test_cid_struct() {
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct MyStruct {
cid: Cid,
data: bool,
}
let cid = Cid::from_str("bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy").unwrap();
let cid_encoded = to_vec(&cid).unwrap();
assert_eq!(
cid_encoded,
[
0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68,
0xff, 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d,
0x70, 0x64, 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
]
);
let cid_decoded_as_cid: Cid = from_slice(&cid_encoded).unwrap();
assert_eq!(cid_decoded_as_cid, cid);
let cid_decoded_as_drisl: Value = from_slice(&cid_encoded).unwrap();
assert_eq!(cid_decoded_as_drisl, Value::Cid(cid));
let mystruct = MyStruct { cid, data: true };
let mystruct_encoded = to_vec(&mystruct).unwrap();
assert_eq!(
mystruct_encoded,
[
0xa2, 0x63, 0x63, 0x69, 0x64, 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20,
0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff, 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30,
0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64, 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88,
0x62, 0x66, 0xe7, 0xae, 0x64, 0x64, 0x61, 0x74, 0x61, 0xf5
]
);
let mystruct_decoded_as_mystruct: MyStruct = from_slice(&mystruct_encoded).unwrap();
assert_eq!(mystruct_decoded_as_mystruct, mystruct);
let mystruct_decoded_as_drisl: Value = from_slice(&mystruct_encoded).unwrap();
let mut expected_map = std::collections::BTreeMap::new();
expected_map.insert("cid".to_string(), Value::Cid(cid));
expected_map.insert("data".to_string(), Value::Bool(true));
assert_eq!(mystruct_decoded_as_drisl, Value::Map(expected_map));
}
#[test]
fn test_binary_not_as_cid() {
let bytes = [0x42, 0xaf, 0xfe];
let bytes_as_drisl: Value = from_slice(&bytes).unwrap();
assert_eq!(bytes_as_drisl, Value::Bytes(vec![0xaf, 0xfe]));
}
#[test]
fn test_cid_not_as_bytes() {
let cbor_cid = [
0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
];
from_slice::<Vec<u8>>(&cbor_cid).expect_err("shouldn't have parsed a tagged CID as a sequence");
from_slice::<serde_bytes::ByteBuf>(&cbor_cid)
.expect_err("shouldn't have parsed a tagged CID as a byte array");
from_slice::<serde_bytes::ByteBuf>(&cbor_cid[2..])
.expect("should have parsed an untagged CID as a byte array");
#[derive(Debug, Deserialize, PartialEq)]
struct NewType(ByteBuf);
#[derive(Debug, Deserialize, PartialEq)]
#[serde(untagged)]
enum BytesInEnum {
MyCid(NewType),
}
let cid_without_tag = &cbor_cid[5..];
assert_eq!(
from_slice::<BytesInEnum>(&cbor_cid).unwrap(),
BytesInEnum::MyCid(NewType(ByteBuf::from(cid_without_tag)))
);
}
#[test]
fn test_cid_bytes_without_tag() {
let cbor_cid = [
0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
];
let decoded_cbor_cid: Cid = from_slice(&cbor_cid).unwrap();
assert_eq!(decoded_cbor_cid.as_bytes(), &cbor_cid[5..]);
let cbor_bytes = &cbor_cid[2..];
from_slice::<Cid>(cbor_bytes).expect_err("should have failed to decode bytes as cid");
}
#[test]
fn test_cid_in_kinded_enum() {
#[derive(Debug, PartialEq)]
pub enum Kinded {
Bytes(ByteBuf),
Link(Cid),
}
let cbor_cid = [
0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
];
impl TryFrom<Value> for Kinded {
type Error = ();
fn try_from(drisl: Value) -> Result<Self, Self::Error> {
match drisl {
Value::Bytes(bytes) => Ok(Self::Bytes(ByteBuf::from(bytes))),
Value::Cid(cid) => Ok(Self::Link(cid)),
_ => Err(()),
}
}
}
impl<'de> de::Deserialize<'de> for Kinded {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
Value::deserialize(deserializer).and_then(|drisl| {
drisl
.try_into()
.map_err(|_| de::Error::custom("No matching enum variant found"))
})
}
}
let decoded_cid: Kinded = from_slice(&cbor_cid).unwrap();
let cid = Cid::from_bytes_raw(&cbor_cid[5..]).unwrap();
assert_eq!(decoded_cid, Kinded::Link(cid));
let cbor_bytes = &cbor_cid[2..];
let decoded_bytes: Kinded = from_slice(cbor_bytes).unwrap();
let bytes = cbor_bytes[2..].to_vec();
assert_eq!(decoded_bytes, Kinded::Bytes(ByteBuf::from(bytes)));
let random_bytes = &cbor_cid[10..];
let decoded_random_bytes: Result<Kinded, _> = from_slice(random_bytes);
assert!(decoded_random_bytes.is_err());
}
#[test]
fn test_cid_in_kinded_enum_with_newtype() {
#[derive(Debug, Deserialize, PartialEq)]
pub struct Foo(#[serde(with = "serde_bytes")] Vec<u8>);
#[derive(Debug, PartialEq)]
pub enum Kinded {
MyBytes(Foo),
Link(Cid),
}
let cbor_cid = [
0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
];
impl TryFrom<Value> for Kinded {
type Error = ();
fn try_from(drisl: Value) -> Result<Self, Self::Error> {
match drisl {
Value::Bytes(bytes) => Ok(Self::MyBytes(Foo(bytes))),
Value::Cid(cid) => Ok(Self::Link(cid)),
_ => Err(()),
}
}
}
impl<'de> de::Deserialize<'de> for Kinded {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
Value::deserialize(deserializer).and_then(|drisl| {
drisl
.try_into()
.map_err(|_| de::Error::custom("No matching enum variant found"))
})
}
}
let decoded_cid: Kinded = from_slice(&cbor_cid).unwrap();
let cid = Cid::from_bytes_raw(&cbor_cid[5..]).unwrap();
assert_eq!(decoded_cid, Kinded::Link(cid));
let cbor_bytes = &cbor_cid[2..];
let decoded_bytes: Kinded = from_slice(cbor_bytes).unwrap();
let bytes = cbor_bytes[2..].to_vec();
assert_eq!(decoded_bytes, Kinded::MyBytes(Foo(bytes)));
let random_bytes = &cbor_cid[10..];
let decoded_random_bytes: Result<Kinded, _> = from_slice(random_bytes);
assert!(decoded_random_bytes.is_err());
}
#[test]
fn test_cid_in_tagged_enum() {
#[derive(Debug, Deserialize, PartialEq)]
pub enum Externally {
Cid(Cid),
}
#[derive(Debug, Deserialize, PartialEq)]
#[serde(tag = "type")]
pub enum Internally {
Cid { cid: Cid },
}
#[derive(Debug, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum Untagged {
Cid(Cid),
}
let cbor_cid = [
0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
];
let cbor_map1 = [vec![0xa1, 0x63, 0x43, 0x69, 0x64], Vec::from(cbor_cid)].concat();
let cbor_map2 = [
vec![
0xa2, 0x64, 0x74, 0x79, 0x70, 0x65, 0x63, 0x43, 0x69, 0x64, 0x63, 0x63, 0x69, 0x64,
],
Vec::from(cbor_cid),
]
.concat();
let cid = Cid::from_bytes_raw(&cbor_cid[5..]).unwrap();
let decoded: Externally = from_slice(&cbor_map1).unwrap();
assert_eq!(decoded, Externally::Cid(cid));
let decoded: Internally = from_slice(&cbor_map2).unwrap();
assert_eq!(decoded, Internally::Cid { cid });
let decoded: Untagged = from_slice(&cbor_cid).unwrap();
assert_eq!(decoded, Untagged::Cid(cid));
}
#[test]
fn test_cid_empty_errors() {
let cbor_empty_cid = [0xd8, 0x2a, 0x40];
let decoded: Result<Cid, _> = from_slice(&cbor_empty_cid);
assert!(decoded.is_err());
}
#[test]
fn test_cid_decode_from_reader() {
let cid_encoded = hex::decode(
"d82a582500015512202c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
)
.unwrap();
let cid_decoded: Cid = from_slice(&cid_encoded).unwrap();
assert_eq!(&cid_encoded[5..], cid_decoded.as_bytes());
}