scale_decode/error/
mod.rs1mod context;
18
19pub use context::{Context, Location};
20
21use crate::visitor::DecodeError;
22use alloc::{borrow::Cow, boxed::Box, string::String, vec::Vec};
23use core::fmt::Display;
24
25#[derive(Debug)]
27pub struct Error {
28 context: Context,
29 kind: ErrorKind,
30}
31
32impl core::error::Error for Error {}
33
34impl Error {
35 pub fn new(kind: ErrorKind) -> Error {
37 Error { context: Context::new(), kind }
38 }
39 pub fn custom(error: impl core::error::Error + Send + Sync + 'static) -> Error {
41 Error::new(ErrorKind::Custom(Box::new(error)))
42 }
43 pub fn custom_str(error: &'static str) -> Error {
45 #[derive(Debug, thiserror::Error)]
46 #[error("{0}")]
47 pub struct StrError(pub &'static str);
48
49 Error::new(ErrorKind::Custom(Box::new(StrError(error))))
50 }
51 pub fn custom_string(error: String) -> Error {
53 #[derive(Debug, thiserror::Error)]
54 #[error("{0}")]
55 pub struct StringError(String);
56
57 Error::new(ErrorKind::Custom(Box::new(StringError(error))))
58 }
59 pub fn kind(&self) -> &ErrorKind {
61 &self.kind
62 }
63 pub fn context(&self) -> &Context {
65 &self.context
66 }
67 pub fn at(mut self, loc: Location) -> Self {
69 self.context.push(loc);
70 Error { context: self.context, kind: self.kind }
71 }
72 pub fn at_idx(mut self, idx: usize) -> Self {
74 self.context.push(Location::idx(idx));
75 Error { context: self.context, kind: self.kind }
76 }
77 pub fn at_field(mut self, field: impl Into<Cow<'static, str>>) -> Self {
79 self.context.push(Location::field(field));
80 Error { context: self.context, kind: self.kind }
81 }
82 pub fn at_variant(mut self, variant: impl Into<Cow<'static, str>>) -> Self {
84 self.context.push(Location::variant(variant));
85 Error { context: self.context, kind: self.kind }
86 }
87}
88
89impl Display for Error {
90 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91 let path = self.context.path();
92 let kind = &self.kind;
93 write!(f, "Error at {path}: {kind}")
94 }
95}
96
97impl From<DecodeError> for Error {
98 fn from(err: DecodeError) -> Error {
99 Error::new(err.into())
100 }
101}
102
103impl From<codec::Error> for Error {
104 fn from(err: codec::Error) -> Error {
105 let err: DecodeError = err.into();
106 Error::new(err.into())
107 }
108}
109
110#[derive(Debug, thiserror::Error)]
112pub enum ErrorKind {
113 #[error("Error decoding bytes given the type ID and registry provided: {_0}")]
116 VisitorDecodeError(#[from] DecodeError),
117 #[error("Number {value} is out of range")]
119 NumberOutOfRange {
120 value: String,
122 },
123 #[error("Cannot find variant {got}; expects one of {expected:?}")]
125 CannotFindVariant {
126 got: String,
128 expected: Vec<&'static str>,
130 },
131 #[error("Cannot decode from type; expected length {expected_len} but got length {actual_len}")]
133 WrongLength {
134 actual_len: usize,
136 expected_len: usize,
138 },
139 #[error("Field {name} does not exist in our encoded data")]
141 CannotFindField {
142 name: String,
144 },
145 #[error("Custom error: {0}")]
147 Custom(Box<dyn core::error::Error + Send + Sync + 'static>),
148}