1use std::{
2 fmt::{Debug, Display},
3 str::Utf8Error,
4};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum WhileParsing {
9 ItemHeader,
10 HeaderValue,
11 ArrayItem,
12 DictItem,
13 BytesFragment,
14 BytesValue,
15 StringFragment,
16 StringValue,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21#[non_exhaustive]
22pub enum ErrorKind {
23 InvalidInfo,
25 TrailingGarbage,
27 InvalidStringFragment,
29 InvalidUtf8(Utf8Error),
31 UnexpectedEof(WhileParsing),
36}
37
38impl Display for ErrorKind {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 match self {
41 ErrorKind::InvalidInfo => write!(f, "invalid item header"),
42 ErrorKind::TrailingGarbage => write!(f, "trailing garbage"),
43 ErrorKind::InvalidStringFragment => write!(f, "string fragment of wrong major type"),
44 ErrorKind::InvalidUtf8(e) => write!(f, "UTF-8 error `{}`", e),
45 ErrorKind::UnexpectedEof(w) => write!(f, "ran out of bytes while parsing {:?}", w),
46 }
47 }
48}
49
50#[derive(Clone, PartialEq, Eq)]
52pub struct ParseError {
53 offset: usize,
54 kind: ErrorKind,
55}
56
57impl ParseError {
58 pub fn offset(&self) -> usize {
60 self.offset
61 }
62
63 pub fn kind(&self) -> ErrorKind {
65 self.kind.clone()
66 }
67}
68
69impl Display for ParseError {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 write!(f, "{} at offset {}", self.kind, self.offset)
72 }
73}
74
75impl std::error::Error for ParseError {}
76
77impl Debug for ParseError {
78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79 Display::fmt(self, f)
80 }
81}
82
83pub(crate) struct InternalError<'a> {
84 position: &'a [u8],
85 kind: ErrorKind,
86}
87
88impl<'a> InternalError<'a> {
89 pub fn new(position: &'a [u8], kind: ErrorKind) -> Self {
90 Self { position, kind }
91 }
92
93 pub fn offset(&self, base: &[u8]) -> usize {
94 let position = self.position as *const _ as *const u8;
95 let base = base as *const _ as *const u8;
96 unsafe { position.offset_from(base) as usize }
98 }
99
100 pub fn with_location(self, loc: &[u8]) -> InternalError<'_> {
101 InternalError {
102 position: loc,
103 kind: self.kind,
104 }
105 }
106
107 pub fn rebase(self, base: &[u8]) -> ParseError {
108 ParseError {
109 offset: self.offset(base),
110 kind: self.kind,
111 }
112 }
113}