use serde::{Deserialize, Serialize};
pub trait CoMetadata: Serialize {
fn metadata() -> Vec<Metadata>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Metadata {
#[serde(rename = "ext")]
External(Vec<String>),
}
#[derive(Clone, Serialize)]
pub struct WithCoMetadata<T: CoMetadata + Serialize> {
#[serde(rename = "$co", skip_serializing_if = "Vec::is_empty")]
co: Vec<Metadata>,
#[serde(flatten)]
value: T,
}
impl<T> WithCoMetadata<T>
where
T: CoMetadata + Serialize,
{
pub fn new(value: T) -> Self {
Self { co: T::metadata(), value }
}
}
impl<T: CoMetadata + Serialize> From<T> for WithCoMetadata<T> {
fn from(value: T) -> Self {
WithCoMetadata::new(value)
}
}
#[cfg(test)]
mod tests {
use super::WithCoMetadata;
use crate::{CoMetadata, Metadata};
use cid::Cid;
use co_macros::TaggedFields;
use serde::{Deserialize, Serialize};
#[test]
fn metadata() {
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Test {
hello: i32,
world: Cid,
}
impl CoMetadata for Test {
fn metadata() -> Vec<crate::Metadata> {
vec![Metadata::External(vec!["world".to_owned()])]
}
}
let json = serde_json::to_string_pretty(&WithCoMetadata::new(Test {
hello: 1,
world: Cid::try_from("bafyr4igf663hpuvdpvque42uxmkbacg5ubd4cgageulmwmqo33g2tpod7e").unwrap(),
}))
.unwrap();
println!("{json}");
}
#[test]
fn metadata_derive() {
#[derive(Debug, Clone, Serialize, Deserialize, TaggedFields)]
struct Test {
hello: i32,
#[tagged(external)]
world: Cid,
}
let json = serde_json::to_string_pretty(&WithCoMetadata::new(Test {
hello: 1,
world: Cid::try_from("bafyr4igf663hpuvdpvque42uxmkbacg5ubd4cgageulmwmqo33g2tpod7e").unwrap(),
}))
.unwrap();
println!("{json}");
}
}