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#[derive(Debug, Clone, Copy, Builder, Derivative)]
22#[derivative(Default)]
23#[cfg_attr(feature = "cli", derive(clap::Args))]
24pub struct Config {
25 #[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 #[builder(default = "LeafPolicy::Raw")]
32 #[cfg_attr(feature = "cli", arg(long, value_name = "LEAF", default_value = "raw"))]
33 pub leaf_policy: LeafPolicy,
34
35 #[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
50pub trait HasherAndWrite: Hasher + Write + Send {}
52impl<T: Hasher + Write + Send> HasherAndWrite for T {}
53
54impl Config {
55 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#[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#[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}