zakura_chain/serialization/
error.rs1use std::{array::TryFromSliceError, io, num::TryFromIntError, str::Utf8Error, sync::Arc};
4
5use bounded_vec::BoundedVecOutOfBounds;
6use hex::FromHexError;
7use thiserror::Error;
8
9#[derive(Clone, Error, Debug)]
12pub enum SerializationError {
13 #[error("io error: {0}")]
15 Io(#[from] Arc<io::Error>),
16
17 #[error("parse error: {0}")]
20 Parse(&'static str),
21
22 #[error("non-canonical shielded protocol proof size")]
25 NonCanonicalShieldedProofSize,
26
27 #[error("string was not UTF-8: {0}")]
31 Utf8Error(#[from] Utf8Error),
32
33 #[error("slice was the wrong length: {0}")]
35 TryFromSliceError(#[from] TryFromSliceError),
36
37 #[error("CompactSize too large: {0}")]
39 TryFromIntError(#[from] TryFromIntError),
40
41 #[error("string was not hex: {0}")]
43 FromHexError(#[from] FromHexError),
44
45 #[error("input couldn't be parsed as a zatoshi `Amount`: {source}")]
47 Amount {
48 #[from]
50 source: crate::amount::Error,
51 },
52
53 #[error("transaction balance is non-zero but doesn't have Sapling shielded spends or outputs")]
58 BadTransactionBalance,
59
60 #[error("script error: {0}")]
62 Script(#[from] zcash_script::script::Error),
63
64 #[error("script opcode error: {0}")]
66 Opcode(#[from] zcash_script::opcode::Error),
67
68 #[error("script number error: {0}")]
70 Num(#[from] zcash_script::num::Error),
71}
72
73impl From<SerializationError> for io::Error {
74 fn from(e: SerializationError) -> Self {
75 match e {
76 SerializationError::Io(e) => {
77 Arc::try_unwrap(e).unwrap_or_else(|e| io::Error::new(e.kind(), e.to_string()))
78 }
79 SerializationError::Parse(msg) => io::Error::new(io::ErrorKind::InvalidData, msg),
80 error @ SerializationError::NonCanonicalShieldedProofSize => {
81 io::Error::new(io::ErrorKind::InvalidData, error)
82 }
83 SerializationError::Utf8Error(e) => io::Error::new(io::ErrorKind::InvalidData, e),
84 SerializationError::TryFromSliceError(e) => {
85 io::Error::new(io::ErrorKind::InvalidData, e)
86 }
87 SerializationError::TryFromIntError(e) => io::Error::new(io::ErrorKind::InvalidData, e),
88 SerializationError::FromHexError(e) => io::Error::new(io::ErrorKind::InvalidData, e),
89 SerializationError::Amount { source } => {
90 io::Error::new(io::ErrorKind::InvalidData, source)
91 }
92 SerializationError::BadTransactionBalance => io::Error::new(
93 io::ErrorKind::InvalidData,
94 "bad transaction balance: non-zero with no Sapling shielded spends or outputs",
95 ),
96 SerializationError::Script(e) => io::Error::new(io::ErrorKind::InvalidData, e),
97 SerializationError::Opcode(e) => io::Error::new(io::ErrorKind::InvalidData, e),
98 SerializationError::Num(e) => io::Error::new(io::ErrorKind::InvalidData, e),
99 }
100 }
101}
102
103impl From<crate::Error> for SerializationError {
104 fn from(e: crate::Error) -> Self {
105 match e {
106 crate::Error::InvalidConsensusBranchId => Self::Parse("invalid consensus branch id"),
107 crate::Error::Io(e) => Self::Io(e),
108 crate::Error::MissingNetworkUpgrade => Self::Parse("missing network upgrade"),
109 crate::Error::Amount(_) => Self::BadTransactionBalance,
110 crate::Error::Conversion(_) => {
111 Self::Parse("Zakura's type could not be converted to its librustzcash equivalent")
112 }
113 }
114 }
115}
116
117impl From<io::Error> for SerializationError {
120 fn from(value: io::Error) -> Self {
121 Arc::new(value).into()
122 }
123}
124
125impl From<BoundedVecOutOfBounds> for SerializationError {
126 fn from(_: BoundedVecOutOfBounds) -> Self {
127 SerializationError::Parse("vector length out of bounds")
128 }
129}