1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//! `Ipld` error definitions.
#[cfg(feature = "serde-codec")]
use alloc::string::ToString;
use alloc::{string::String, vec::Vec};

use crate::cid::Cid;
use crate::ipld::{Ipld, IpldIndex};
pub use anyhow::{Error, Result};
#[cfg(feature = "std")]
use thiserror::Error;

/// Block exceeds 1MiB.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "std", derive(Error), error("Block size {0} exceeds 1MiB."))]
pub struct BlockTooLarge(pub usize);

/// The codec is unsupported.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "std", derive(Error), error("Unsupported codec {0:?}."))]
pub struct UnsupportedCodec(pub u64);

/// The multihash is unsupported.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "std", derive(Error), error("Unsupported multihash {0:?}."))]
pub struct UnsupportedMultihash(pub u64);

/// Hash does not match the CID.
#[derive(Clone, Debug)]
#[cfg_attr(
    feature = "std",
    derive(Error),
    error("Hash of data does not match the CID.")
)]
pub struct InvalidMultihash(pub Vec<u8>);

/// The block wasn't found. The supplied string is a CID.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "std", derive(Error), error("Failed to retrieve block {0}."))]
pub struct BlockNotFound(pub Cid);

/// Error during Serde operations.
#[cfg(feature = "serde-codec")]
#[derive(Clone, Debug)]
pub struct SerdeError(String);

#[cfg(feature = "serde-codec")]
impl core::fmt::Display for SerdeError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "Serde error: {}", self.0)
    }
}

#[cfg(feature = "serde-codec")]
impl serde::de::Error for SerdeError {
    fn custom<T: core::fmt::Display>(msg: T) -> Self {
        Self(msg.to_string())
    }
}

#[cfg(feature = "serde-codec")]
impl serde::ser::Error for SerdeError {
    fn custom<T: core::fmt::Display>(msg: T) -> Self {
        Self(msg.to_string())
    }
}

#[cfg(feature = "serde-codec")]
impl serde::ser::StdError for SerdeError {}

/// Type error.
#[derive(Clone, Debug)]
#[cfg_attr(
    feature = "std",
    derive(Error),
    error("Expected {expected:?} but found {found:?}")
)]
pub struct TypeError {
    /// The expected type.
    pub expected: TypeErrorType,
    /// The actual type.
    pub found: TypeErrorType,
}

impl TypeError {
    /// Creates a new type error.
    pub fn new<A: Into<TypeErrorType>, B: Into<TypeErrorType>>(expected: A, found: B) -> Self {
        Self {
            expected: expected.into(),
            found: found.into(),
        }
    }
}

#[cfg(not(feature = "std"))]
impl core::fmt::Display for TypeError {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        write!(f, "Expected {:?} but found {:?}", self.expected, self.found)
    }
}

/// Type error type.
#[derive(Clone, Debug)]
pub enum TypeErrorType {
    /// Null type.
    Null,
    /// Boolean type.
    Bool,
    /// Integer type.
    Integer,
    /// Float type.
    Float,
    /// String type.
    String,
    /// Bytes type.
    Bytes,
    /// List type.
    List,
    /// Map type.
    Map,
    /// Link type.
    Link,
    /// Key type.
    Key(String),
    /// Index type.
    Index(usize),
}

impl From<Ipld> for TypeErrorType {
    fn from(ipld: Ipld) -> Self {
        Self::from(&ipld)
    }
}

impl From<&Ipld> for TypeErrorType {
    fn from(ipld: &Ipld) -> Self {
        match ipld {
            Ipld::Null => Self::Null,
            Ipld::Bool(_) => Self::Bool,
            Ipld::Integer(_) => Self::Integer,
            Ipld::Float(_) => Self::Float,
            Ipld::String(_) => Self::String,
            Ipld::Bytes(_) => Self::Bytes,
            Ipld::List(_) => Self::List,
            Ipld::Map(_) => Self::Map,
            Ipld::Link(_) => Self::Link,
        }
    }
}

impl From<IpldIndex<'_>> for TypeErrorType {
    fn from(index: IpldIndex<'_>) -> Self {
        match index {
            IpldIndex::List(i) => Self::Index(i),
            IpldIndex::Map(s) => Self::Key(s),
            IpldIndex::MapRef(s) => Self::Key(s.into()),
        }
    }
}