1use crate::{error::NumberOutOfRange, RawCborCodec};
3use byteorder::{BigEndian, ByteOrder};
4use libipld_core::{cid::Cid, codec::Encode, error::Result, ipld::Ipld};
5use std::{collections::BTreeMap, io::Write, ops::Deref, sync::Arc};
6
7pub fn write_null<W: Write>(w: &mut W) -> Result<()> {
9 w.write_all(&[0xf6])?;
10 Ok(())
11}
12
13pub fn write_u8<W: Write>(w: &mut W, major: u8, value: u8) -> Result<()> {
15 if value <= 0x17 {
16 let buf = [major << 5 | value];
17 w.write_all(&buf)?;
18 } else {
19 let buf = [major << 5 | 24, value];
20 w.write_all(&buf)?;
21 }
22 Ok(())
23}
24
25pub fn write_u16<W: Write>(w: &mut W, major: u8, value: u16) -> Result<()> {
27 if value <= u16::from(u8::max_value()) {
28 write_u8(w, major, value as u8)?;
29 } else {
30 let mut buf = [major << 5 | 25, 0, 0];
31 BigEndian::write_u16(&mut buf[1..], value);
32 w.write_all(&buf)?;
33 }
34 Ok(())
35}
36
37pub fn write_u32<W: Write>(w: &mut W, major: u8, value: u32) -> Result<()> {
39 if value <= u32::from(u16::max_value()) {
40 write_u16(w, major, value as u16)?;
41 } else {
42 let mut buf = [major << 5 | 26, 0, 0, 0, 0];
43 BigEndian::write_u32(&mut buf[1..], value);
44 w.write_all(&buf)?;
45 }
46 Ok(())
47}
48
49pub fn write_u64<W: Write>(w: &mut W, major: u8, value: u64) -> Result<()> {
51 if value <= u64::from(u32::max_value()) {
52 write_u32(w, major, value as u32)?;
53 } else {
54 let mut buf = [major << 5 | 27, 0, 0, 0, 0, 0, 0, 0, 0];
55 BigEndian::write_u64(&mut buf[1..], value);
56 w.write_all(&buf)?;
57 }
58 Ok(())
59}
60
61pub fn write_tag<W: Write>(w: &mut W, tag: u64) -> Result<()> {
63 write_u64(w, 6, tag)
64}
65
66impl Encode<RawCborCodec> for bool {
67 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
68 let buf = if *self { [0xf5] } else { [0xf4] };
69 w.write_all(&buf)?;
70 Ok(())
71 }
72}
73
74impl Encode<RawCborCodec> for u8 {
75 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
76 write_u8(w, 0, *self)
77 }
78}
79
80impl Encode<RawCborCodec> for u16 {
81 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
82 write_u16(w, 0, *self)
83 }
84}
85
86impl Encode<RawCborCodec> for u32 {
87 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
88 write_u32(w, 0, *self)
89 }
90}
91
92impl Encode<RawCborCodec> for u64 {
93 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
94 write_u64(w, 0, *self)
95 }
96}
97
98impl Encode<RawCborCodec> for i8 {
99 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
100 write_u8(w, 1, -(*self + 1) as u8)
101 }
102}
103
104impl Encode<RawCborCodec> for i16 {
105 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
106 write_u16(w, 1, -(*self + 1) as u16)
107 }
108}
109
110impl Encode<RawCborCodec> for i32 {
111 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
112 write_u32(w, 1, -(*self + 1) as u32)
113 }
114}
115
116impl Encode<RawCborCodec> for i64 {
117 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
118 write_u64(w, 1, -(*self + 1) as u64)
119 }
120}
121
122impl Encode<RawCborCodec> for f32 {
123 #[allow(clippy::float_cmp)]
124 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
125 if self.is_infinite() {
126 if self.is_sign_positive() {
127 w.write_all(&[0xf9, 0x7c, 0x00])?;
128 } else {
129 w.write_all(&[0xf9, 0xfc, 0x00])?;
130 }
131 } else if self.is_nan() {
132 w.write_all(&[0xf9, 0x7e, 0x00])?;
133 } else {
134 let mut buf = [0xfa, 0, 0, 0, 0];
135 BigEndian::write_f32(&mut buf[1..], *self);
136 w.write_all(&buf)?;
137 }
138 Ok(())
139 }
140}
141
142impl Encode<RawCborCodec> for f64 {
143 #[allow(clippy::float_cmp)]
144 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
145 if !self.is_finite() || f64::from(*self as f32) == *self {
146 let value = *self as f32;
147 value.encode(c, w)?;
148 } else {
149 let mut buf = [0xfb, 0, 0, 0, 0, 0, 0, 0, 0];
150 BigEndian::write_f64(&mut buf[1..], *self);
151 w.write_all(&buf)?;
152 }
153 Ok(())
154 }
155}
156
157impl Encode<RawCborCodec> for [u8] {
158 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
159 write_u64(w, 2, self.len() as u64)?;
160 w.write_all(self)?;
161 Ok(())
162 }
163}
164
165impl Encode<RawCborCodec> for Box<[u8]> {
166 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
167 self[..].encode(c, w)
168 }
169}
170
171impl Encode<RawCborCodec> for str {
172 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
173 write_u64(w, 3, self.len() as u64)?;
174 w.write_all(self.as_bytes())?;
175 Ok(())
176 }
177}
178
179impl Encode<RawCborCodec> for String {
180 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
181 self.as_str().encode(c, w)
182 }
183}
184
185impl Encode<RawCborCodec> for i128 {
186 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
187 if *self < 0 {
188 if -(*self + 1) > u64::max_value() as i128 {
189 return Err(NumberOutOfRange::new::<i128>().into());
190 }
191 write_u64(w, 1, -(*self + 1) as u64)?;
192 } else {
193 if *self > u64::max_value() as i128 {
194 return Err(NumberOutOfRange::new::<i128>().into());
195 }
196 write_u64(w, 0, *self as u64)?;
197 }
198 Ok(())
199 }
200}
201
202impl Encode<RawCborCodec> for Cid {
203 fn encode<W: Write>(&self, _: RawCborCodec, w: &mut W) -> Result<()> {
204 write_tag(w, 42)?;
205 let buf = self.to_bytes();
208 let len = buf.len();
209 write_u64(w, 2, len as u64 + 1)?;
210 w.write_all(&[0])?;
211 w.write_all(&buf[..len])?;
212 Ok(())
213 }
214}
215
216impl<T: Encode<RawCborCodec>> Encode<RawCborCodec> for Option<T> {
217 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
218 if let Some(value) = self {
219 value.encode(c, w)?;
220 } else {
221 write_null(w)?;
222 }
223 Ok(())
224 }
225}
226
227impl<T: Encode<RawCborCodec>> Encode<RawCborCodec> for Vec<T> {
228 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
229 write_u64(w, 4, self.len() as u64)?;
230 for value in self {
231 value.encode(c, w)?;
232 }
233 Ok(())
234 }
235}
236
237impl<K: Encode<RawCborCodec>, T: Encode<RawCborCodec> + 'static> Encode<RawCborCodec> for BTreeMap<K, T> {
238 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
239 write_u64(w, 5, self.len() as u64)?;
240 for (k, v) in self {
241 k.encode(c, w)?;
242 v.encode(c, w)?;
243 }
244 Ok(())
245 }
246}
247
248impl Encode<RawCborCodec> for Ipld {
249 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
250 match self {
251 Self::Null => write_null(w),
252 Self::Bool(b) => b.encode(c, w),
253 Self::Integer(i) => i.encode(c, w),
254 Self::Float(f) => f.encode(c, w),
255 Self::Bytes(b) => b.as_slice().encode(c, w),
256 Self::String(s) => s.encode(c, w),
257 Self::List(l) => l.encode(c, w),
258 Self::Map(m) => m.encode(c, w),
259 Self::Link(cid) => cid.encode(c, w),
260 }
261 }
262}
263
264impl<T: Encode<RawCborCodec>> Encode<RawCborCodec> for Arc<T> {
265 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
266 self.deref().encode(c, w)
267 }
268}
269
270impl Encode<RawCborCodec> for () {
271 fn encode<W: Write>(&self, _c: RawCborCodec, w: &mut W) -> Result<()> {
272 write_u8(w, 4, 0)?;
273 Ok(())
274 }
275}
276
277impl<A: Encode<RawCborCodec>> Encode<RawCborCodec> for (A,) {
278 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
279 write_u8(w, 4, 1)?;
280 self.0.encode(c, w)?;
281 Ok(())
282 }
283}
284
285impl<A: Encode<RawCborCodec>, B: Encode<RawCborCodec>> Encode<RawCborCodec> for (A, B) {
286 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
287 write_u8(w, 4, 2)?;
288 self.0.encode(c, w)?;
289 self.1.encode(c, w)?;
290 Ok(())
291 }
292}
293
294impl<A: Encode<RawCborCodec>, B: Encode<RawCborCodec>, C: Encode<RawCborCodec>> Encode<RawCborCodec>
295 for (A, B, C)
296{
297 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
298 write_u8(w, 4, 3)?;
299 self.0.encode(c, w)?;
300 self.1.encode(c, w)?;
301 self.2.encode(c, w)?;
302 Ok(())
303 }
304}
305
306impl<A: Encode<RawCborCodec>, B: Encode<RawCborCodec>, C: Encode<RawCborCodec>, D: Encode<RawCborCodec>>
307 Encode<RawCborCodec> for (A, B, C, D)
308{
309 fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
310 write_u8(w, 4, 4)?;
311 self.0.encode(c, w)?;
312 self.1.encode(c, w)?;
313 self.2.encode(c, w)?;
314 self.3.encode(c, w)?;
315 Ok(())
316 }
317}