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
// Copyright 2020 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0

//! Error objects and codes

use std::fmt;
use std::fmt::Debug;
use std::io;
use std::result;

use serde::{de, ser};
use thiserror::Error;

/// A result whose error type is `Error`.
pub type Result<A> = result::Result<A, Error>;

#[derive(Debug, Error)]
/// Error type for BinProt serialization and deserialization
pub enum Error {
    /// Error in underlying IO
    #[error("io error")]
    Io(#[from] io::Error),

    /// The end of stream was reached unexpectedly.
    #[error("end of stream")]
    EndOfStream,

    /// Size not given when serializing a sequence
    #[error("Attempting to serialize a sequence but size not provided")]
    SeqSizeNotProvided,

    /// Size not given when serializing a sequence
    #[error("Attempting to serialize a map but size not provided")]
    MapSizeNotProvided,

    /// Invalid byte encountered when deserializing
    #[error(
        "Invalid byte for deserializing a {dtype}. Expected one of: {allowed:?}, found: {byte}"
    )]
    InvalidByte {
        /// The byte that is invalid
        byte: u8,
        /// The data type that the deserializer is attempting to deserialize
        dtype: String,
        /// Bytes that are allowed in this context
        allowed: Vec<u8>,
    },

    /// Invalid utf-8 char
    #[error("Invalid byte sequence when attempting to deserialize utf-8 char: {bytes:?}")]
    InvalidUtf8 {
        /// Invalid byte sequence encountered
        bytes: Vec<u8>,
    },

    /// Invalid byte encountered deserializing option
    #[error("Invalid byte when deserializing option. First byte must be 0 or 1, got {got}")]
    InvalidOptionByte {
        /// Invalid byte encountered
        got: u8,
    },

    /// Invalid integer prefix byte
    #[error("Invalid byte when deserializing an integer. First byte must be a size flag or a value < 0x80")]
    InvalidIntegerByte {
        /// Invalid byte encountered
        byte: u8,
    },

    /// Encountered a variant index larger than allowed
    #[error("Invalid variant index detected. Currently only supports enums with < 256 variants")]
    VariantIndexTooLarge {
        /// Invalid index encountered
        index: u32,
    },

    /// Destination integer type too small
    #[error("Attempted to deserialize an integer into a desgination type that is too small")]
    DestinationIntegerOverflow,

    /// Functionality will not be implemented. Probably it does not make sense for this format
    #[error(
        "Functionality will not be implemented. Probably it does not make sense for this format"
    )]
    WontImplement,

    /// The layout ended before the reader is empty
    #[error("Unexpected end of layout")]
    UnexpectedEndOfLayout,

    /// Layout iterator errored, can be due to invalid layout or mismatch between layout and input
    #[error("Layout iterator error")]
    LayoutIteratorError,

    /// Have not provided a layout
    #[error("Attempting to deserialize into a loose type without a layout")]
    DeserializingLooseTypeWithoutLayout,

    /// An unknown custom type found in layout that deserializer code does not know
    /// not to handle
    #[error("Unknown custom type {typ}")]
    UnknownCustomType {
        /// The custom type identifier
        typ: String,
    },

    /// There is no logic implemented to deserialize this rule yet
    #[error("Unimplemented rule")]
    UnimplementedRule,

    /// When deserializing a polyvar the tag does not match any known tags for the type
    #[error("Unrecognised Polyvar tag {0}")]
    UnknownPolyvarTag(u32),

    /// When deserializing a polyvar the tag does not match any known tags for the type
    #[error("Input stream has {0} unconsumed bytes")]
    StreamNotFullyConsumed(usize),

    //////////////////////////////////
    /// Some user-defined error occurred.
    #[error("{message}")]
    Custom {
        /// The user-defined error message.
        message: String,
    },
}

impl de::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Error {
        Error::Custom {
            message: msg.to_string(),
        }
    }
}

impl ser::Error for Error {
    fn custom<T: fmt::Display>(msg: T) -> Error {
        Error::Custom {
            message: msg.to_string(),
        }
    }
}