Skip to main content

ipld_car/
config.rs

1use crate::error::{Error, InvalidErr};
2
3use derivative::Derivative;
4use derive_builder::Builder;
5use libipld::{
6	multihash::{
7		self, Blake2b256, Blake2b512, Blake2s128, Blake2s256, Blake3_256, Hasher, Keccak224, Keccak256, Keccak384,
8		Keccak512, Sha2_256, Sha2_512, Sha3_224, Sha3_256, Sha3_384, Sha3_512,
9	},
10	Cid,
11};
12use std::io::Write;
13use strum::FromRepr;
14
15mod chunck_policy;
16pub use chunck_policy::{ChunkPolicy, WellKnownChunkSize};
17mod dag_layout;
18pub use dag_layout::{DAGLayout, LayerRepeats, MaxChildren};
19
20/// Configuration of CID generation.
21#[derive(Debug, Clone, Copy, Builder, Derivative)]
22#[derivative(Default)]
23#[cfg_attr(feature = "cli", derive(clap::Args))]
24pub struct Config {
25	/// Chunk policy
26	#[builder(default = "ChunkPolicy::FixedSize(WellKnownChunkSize::F256KiB)")]
27	#[cfg_attr(feature = "cli", arg(long, value_name = "SIZE", default_value = "256KiB"))]
28	pub chunk_policy: ChunkPolicy,
29
30	/// Leaf encoding policy
31	#[builder(default = "LeafPolicy::Raw")]
32	#[cfg_attr(feature = "cli", arg(long, value_name = "LEAF", default_value = "raw"))]
33	pub leaf_policy: LeafPolicy,
34
35	/// DAG layout strategy (flat, balanced, trickle)
36	#[builder(default = "DAGLayout::Flat")]
37	#[cfg_attr(feature = "cli", arg(skip))]
38	pub layout: DAGLayout,
39
40	#[builder(default = "multihash::Code::Sha2_256")]
41	#[derivative(Default(value = "multihash::Code::Sha2_256"))]
42	#[cfg_attr(feature = "cli", arg(skip = multihash::Code::Sha2_256))]
43	pub hash_code: multihash::Code,
44
45	#[builder(default = "CidCodec::DagPb")]
46	#[cfg_attr(feature = "cli", arg(long, value_name = "CID_CODEC", default_value = "dag-pb"))]
47	pub cid_codec: CidCodec,
48}
49
50/// Trait combining hasher and write capabilities for streaming CID calculation.
51pub trait HasherAndWrite: Hasher + Write + Send {}
52impl<T: Hasher + Write + Send> HasherAndWrite for T {}
53
54impl Config {
55	/// Returns a hasher instance for the configured hash code.
56	pub fn hasher(&self) -> Result<Box<dyn HasherAndWrite>, Error> {
57		let hasher: Box<dyn HasherAndWrite> = match self.hash_code {
58			multihash::Code::Sha2_256 => Box::new(Sha2_256::default()),
59			multihash::Code::Sha2_512 => Box::new(Sha2_512::default()),
60			multihash::Code::Sha3_224 => Box::new(Sha3_224::default()),
61			multihash::Code::Sha3_256 => Box::new(Sha3_256::default()),
62			multihash::Code::Sha3_384 => Box::new(Sha3_384::default()),
63			multihash::Code::Sha3_512 => Box::new(Sha3_512::default()),
64			multihash::Code::Keccak224 => Box::new(Keccak224::default()),
65			multihash::Code::Keccak256 => Box::new(Keccak256::default()),
66			multihash::Code::Keccak384 => Box::new(Keccak384::default()),
67			multihash::Code::Keccak512 => Box::new(Keccak512::default()),
68			multihash::Code::Blake2b256 => Box::new(Blake2b256::default()),
69			multihash::Code::Blake2b512 => Box::new(Blake2b512::default()),
70			multihash::Code::Blake2s128 => Box::new(Blake2s128::default()),
71			multihash::Code::Blake2s256 => Box::new(Blake2s256::default()),
72			multihash::Code::Blake3_256 => Box::new(Blake3_256::default()),
73		};
74		Ok(hasher)
75	}
76}
77
78impl TryFrom<&Cid> for Config {
79	type Error = Error;
80
81	fn try_from(cid: &Cid) -> Result<Self, Self::Error> {
82		let cid_codec_repr = cid.codec();
83		let cid_codec = CidCodec::from_repr(cid_codec_repr).ok_or(Error::CodecNotSupported(cid_codec_repr))?;
84		let hash_codec = multihash::Code::try_from(cid.hash().code())?;
85
86		ConfigBuilder::default()
87			.cid_codec(cid_codec)
88			.hash_code(hash_codec)
89			.build()
90			.map_err(|build_err| Error::from(InvalidErr::ConfigBuilder(build_err.to_string())))
91	}
92}
93
94/// CID codec identifiers for IPLD content encoding.
95#[cfg_attr(feature = "std", derive(Debug))]
96#[derive(Default, Clone, Copy, PartialEq, Eq, FromRepr)]
97#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
98#[repr(u64)]
99pub enum CidCodec {
100	Raw = 0x55,
101	#[default]
102	#[cfg_attr(feature = "cli", value(name = "dag-pb"))]
103	DagPb = 0x70,
104	#[cfg_attr(feature = "cli", value(name = "dag-cbor"))]
105	DagCbor = 0x71,
106	#[cfg_attr(feature = "cli", value(name = "dag-json"))]
107	DagJson = 0x0129,
108}
109
110/// Defines the configuration of leaf in a DAG.
111#[derive(Clone, Copy, PartialEq, Eq, Default)]
112#[cfg_attr(feature = "std", derive(Debug))]
113#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
114pub enum LeafPolicy {
115	#[default]
116	Raw,
117	UnixFs,
118}