Skip to main content

parcel_sourcemap/
sourcemap_error.rs

1use std::{convert::Infallible, io};
2
3// Errors that can occur during processing/modifying source map
4#[derive(Copy, Clone, Debug)]
5#[repr(u32)]
6pub enum SourceMapErrorType {
7    // NB: 0 is reserved for OK.
8    // The mappings contained a negative line, column, source index, or name index.
9    UnexpectedNegativeNumber = 1,
10
11    // The mappings contained a number larger than `u32::MAX`.
12    UnexpectedlyBigNumber = 2,
13
14    // Reached EOF while in the middle of parsing a VLQ.
15    VlqUnexpectedEof = 3,
16
17    // Encountered an invalid base 64 character while parsing a VLQ.
18    VlqInvalidBase64 = 4,
19
20    // VLQ encountered a number that, when decoded, would not fit in a u32.
21    VlqOverflow = 5,
22
23    // General IO Error
24    IOError = 6,
25
26    // Name out of range
27    NameOutOfRange = 7,
28
29    // Source out of range
30    SourceOutOfRange = 8,
31
32    // Failed to write buffer
33    BufferError = 9,
34
35    // FilePath is invalid
36    InvalidFilePath = 10,
37
38    // Failed to convert utf-8 to array
39    FromUtf8Error = 11,
40
41    // Failed to serialize to JSON
42    JSONError = 12,
43
44    // Failed to parse data url
45    #[cfg(feature = "json")]
46    DataUrlError = 13,
47}
48
49#[derive(Debug)]
50pub struct SourceMapError {
51    pub error_type: SourceMapErrorType,
52    pub reason: Option<String>,
53}
54
55impl SourceMapError {
56    pub fn new(error_type: SourceMapErrorType) -> Self {
57        Self {
58            error_type,
59            reason: None,
60        }
61    }
62
63    pub fn new_with_reason(error_type: SourceMapErrorType, reason: &str) -> Self {
64        Self {
65            error_type,
66            reason: Some(String::from(reason)),
67        }
68    }
69}
70
71impl std::error::Error for SourceMapError {}
72
73impl std::fmt::Display for SourceMapError {
74    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75        // Prefix all errors, so it's obvious they originate from this library
76        write!(f, "[parcel-sourcemap] ")?;
77
78        // Convert error type into an error message...
79        match self.error_type {
80            SourceMapErrorType::UnexpectedNegativeNumber => {
81                write!(f, "Unexpected Negative Number")?;
82            }
83            SourceMapErrorType::UnexpectedlyBigNumber => {
84                write!(f, "Unexpected Big Number")?;
85            }
86            SourceMapErrorType::VlqUnexpectedEof => {
87                write!(f, "VLQ Unexpected end of file")?;
88            }
89            SourceMapErrorType::VlqInvalidBase64 => {
90                write!(f, "VLQ Invalid Base 64 value")?;
91            }
92            SourceMapErrorType::VlqOverflow => {
93                write!(f, "VLQ Value overflowed, does not fit in u32")?;
94            }
95            SourceMapErrorType::IOError => {
96                write!(f, "IO Error")?;
97            }
98            SourceMapErrorType::NameOutOfRange => {
99                write!(f, "Name out of range")?;
100            }
101            SourceMapErrorType::SourceOutOfRange => {
102                write!(f, "Source out of range")?;
103            }
104            SourceMapErrorType::InvalidFilePath => {
105                write!(f, "Invalid FilePath")?;
106            }
107            SourceMapErrorType::BufferError => {
108                write!(
109                    f,
110                    "Something went wrong while writing/reading a sourcemap buffer"
111                )?;
112            }
113            SourceMapErrorType::FromUtf8Error => {
114                write!(f, "Could not convert utf-8 array to string")?;
115            }
116            SourceMapErrorType::JSONError => {
117                write!(f, "Error reading or writing to JSON")?;
118            }
119            #[cfg(feature = "json")]
120            SourceMapErrorType::DataUrlError => {
121                write!(f, "Error parsing data url")?;
122            }
123        }
124
125        // Add reason to error string if there is one
126
127        if let Some(r) = &self.reason {
128            write!(f, ", ")?;
129            write!(f, "{}", &r[..])?;
130        }
131
132        Ok(())
133    }
134}
135
136impl From<vlq::Error> for SourceMapError {
137    #[inline]
138    fn from(e: vlq::Error) -> SourceMapError {
139        match e {
140            vlq::Error::UnexpectedEof => SourceMapError::new(SourceMapErrorType::VlqUnexpectedEof),
141            vlq::Error::InvalidBase64(_) => {
142                SourceMapError::new(SourceMapErrorType::VlqInvalidBase64)
143            }
144            vlq::Error::Overflow => SourceMapError::new(SourceMapErrorType::VlqOverflow),
145        }
146    }
147}
148
149impl From<io::Error> for SourceMapError {
150    #[inline]
151    fn from(_err: io::Error) -> SourceMapError {
152        SourceMapError::new(SourceMapErrorType::IOError)
153    }
154}
155
156impl From<Infallible> for SourceMapError {
157    #[inline]
158    fn from(_err: Infallible) -> SourceMapError {
159        SourceMapError::new(SourceMapErrorType::BufferError)
160    }
161}
162
163impl From<rkyv::rancor::Error> for SourceMapError {
164    #[inline]
165    fn from(_err: rkyv::rancor::Error) -> SourceMapError {
166        SourceMapError::new(SourceMapErrorType::BufferError)
167    }
168}
169
170impl From<std::string::FromUtf8Error> for SourceMapError {
171    #[inline]
172    fn from(_err: std::string::FromUtf8Error) -> SourceMapError {
173        SourceMapError::new(SourceMapErrorType::FromUtf8Error)
174    }
175}
176
177#[cfg(feature = "json")]
178impl From<serde_json::Error> for SourceMapError {
179    #[inline]
180    fn from(_err: serde_json::Error) -> SourceMapError {
181        SourceMapError::new(SourceMapErrorType::JSONError)
182    }
183}
184
185#[cfg(feature = "json")]
186impl From<data_url::DataUrlError> for SourceMapError {
187    #[inline]
188    fn from(_err: data_url::DataUrlError) -> SourceMapError {
189        SourceMapError::new(SourceMapErrorType::DataUrlError)
190    }
191}