Skip to main content

co_primitives/types/
cid.rs

1// SPDX-License-Identifier: AGPL-3.0-only
2// Copyright (C) 2026 1io BRANDGUARDIAN GmbH
3
4use cid::Cid;
5use schemars::{
6	schema::{InstanceType, Metadata, ObjectValidation, Schema, SchemaObject, SingleOrVec},
7	JsonSchema, Map, Set,
8};
9use serde::{Deserialize, Serialize};
10use std::fmt::Display;
11
12#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Default, Copy)]
13#[serde(into = "Cid", from = "Cid")]
14#[repr(transparent)]
15pub struct CoCid(Cid);
16impl Display for CoCid {
17	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18		self.0.fmt(f)
19	}
20}
21impl JsonSchema for CoCid {
22	fn schema_name() -> String {
23		"Cid".to_owned()
24	}
25
26	fn json_schema(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
27		// cid only has one property which is a slash-key string
28		let mut properties = Map::new();
29		properties.insert(
30			"/".to_owned(),
31			Schema::Object(SchemaObject {
32				instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
33				..Default::default()
34			}),
35		);
36		// set property as required
37		let mut required = Set::new();
38		required.insert("/".to_owned());
39		// create schema
40		let cid_schema = SchemaObject {
41			// metadata containing title
42			metadata: Some(Box::new(Metadata { title: Some("Cid".to_owned()), ..Default::default() })),
43			// sets type to 'object'
44			instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Object))),
45			// inserts the 'properties' and 'required' props
46			object: Some(Box::new(ObjectValidation { properties, required, ..Default::default() })),
47			..Default::default()
48		};
49		Schema::Object(cid_schema)
50	}
51}
52
53impl From<Cid> for CoCid {
54	fn from(value: Cid) -> Self {
55		CoCid(value)
56	}
57}
58impl From<CoCid> for Cid {
59	fn from(value: CoCid) -> Self {
60		value.0
61	}
62}
63impl AsRef<Cid> for CoCid {
64	fn as_ref(&self) -> &Cid {
65		&self.0
66	}
67}
68
69#[cfg(test)]
70mod tests {
71	use super::CoCid;
72	use crate::BlockSerializer;
73
74	#[test]
75	fn test_serialize() {
76		let (cid, _block) = BlockSerializer::default().serialize(&"hello world").unwrap().into_inner();
77		let co_cid = CoCid::from(cid);
78		let json = serde_ipld_dagjson::to_vec(&co_cid).unwrap();
79		assert_eq!(
80			std::str::from_utf8(&json).unwrap(),
81			"{\"/\":\"bafyr4idksef7ir3qqvc5ilbddm4s3v3da7uedc6k4odiejquu5q3dh2i7e\"}"
82		);
83	}
84
85	#[test]
86	fn test_deserialize() {
87		let (cid, _block) = BlockSerializer::default().serialize(&"hello world").unwrap().into_inner();
88		let co_cid = CoCid::from(cid);
89		let json = serde_ipld_dagjson::to_vec(&co_cid).unwrap();
90		let co_cid_deserialize: CoCid = serde_ipld_dagjson::from_slice(&json).unwrap();
91		assert_eq!(co_cid_deserialize, co_cid);
92	}
93}