changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate rust/lib/sxp/src/err.rs

changeset 698: 96958d3eb5b0
parent: 3d78bed56188
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
1
 //! err.rs --- When serializing or deserializing SXP goes wrong...
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
2
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
3
 use crate::io;
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
4
 use alloc::{
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
5
   boxed::Box,
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
6
   string::{String, ToString},
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
7
 };
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
8
 use core::{
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
9
   fmt::{self, Debug, Display},
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
10
   result,
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
11
   str::FromStr,
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
12
 };
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
13
 use serde::{de, ser};
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
14
 #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
15
 use std::error;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
16
 #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
17
 use std::io::ErrorKind;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
18
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
19
 pub type Result<T> = result::Result<T, Error>;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
20
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
21
 /// This type represents all possible errors that can occur when serializing or
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
22
 /// deserializing SXP data.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
23
 pub struct Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
24
   /// This `Box` allows us to keep the size of `Error` as small as possible. A
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
25
   /// larger `Error` type was substantially slower due to all the functions
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
26
   /// that pass around `Result<T, Error>`.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
27
   err: Box<ErrorImpl>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
28
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
29
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
30
 impl Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
31
   /// One-based line number at which the error was detected.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
32
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
33
   /// Characters in the first line of the input (before the first newline
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
34
   /// character) are in line 1.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
35
   pub fn line(&self) -> usize {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
36
     self.err.line
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
37
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
38
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
39
   //  TODO 2023-07-14: I kinda want to change this to Zero-based, as
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
40
   //  I'm pretty sure that's the default functionality of emacs (with
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
41
   //  cursor at '(point-min)' the position is '(:line 1 :col 0)'..
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
42
   /// One-based column number at which the error was detected.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
43
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
44
   /// The first character in the input and any characters immediately
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
45
   /// following a newline character are in column 1.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
46
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
47
   /// Note that errors may occur in column 0, for example if a read from an
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
48
   /// I/O stream fails immediately following a previously read newline
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
49
   /// character.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
50
   pub fn column(&self) -> usize {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
51
     self.err.column
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
52
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
53
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
54
   /// Categorizes the cause of this error.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
55
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
56
   /// - `Category::Io` - failure to read or write bytes on an I/O stream
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
57
   /// - `Category::Syntax` - input that is not syntactically valid SXP
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
58
   /// - `Category::Data` - input data that is semantically incorrect
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
59
   /// - `Category::Eof` - unexpected end of the input data
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
60
   pub fn classify(&self) -> Category {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
61
     match self.err.code {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
62
       ErrorCode::Message(_) => Category::Data,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
63
       ErrorCode::Io(_) => Category::Io,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
64
       ErrorCode::EofWhileParsingList
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
65
       | ErrorCode::EofWhileParsingObject
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
66
       | ErrorCode::EofWhileParsingString
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
67
       | ErrorCode::EofWhileParsingValue => Category::Eof,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
68
       ErrorCode::ExpectedListEnd
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
69
       | ErrorCode::ExpectedSomeSymbol
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
70
       | ErrorCode::ExpectedSomeValue
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
71
       | ErrorCode::ExpectedDoubleQuote
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
72
       | ErrorCode::InvalidEscape
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
73
       | ErrorCode::InvalidNumber
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
74
       | ErrorCode::NumberOutOfRange
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
75
       | ErrorCode::InvalidUnicodeCodePoint
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
76
       | ErrorCode::ControlCharacterWhileParsingString
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
77
       | ErrorCode::KeyMustBeASymbol
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
78
       | ErrorCode::LoneLeadingSurrogateInHexEscape
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
79
       | ErrorCode::TrailingCharacters
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
80
       | ErrorCode::UnexpectedEndOfHexEscape
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
81
       | ErrorCode::RecursionLimitExceeded => Category::Syntax,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
82
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
83
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
84
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
85
   /// Returns true if this error was caused by a failure to read or write
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
86
   /// bytes on an I/O stream.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
87
   pub fn is_io(&self) -> bool {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
88
     self.classify() == Category::Io
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
89
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
90
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
91
   /// Returns true if this error was caused by input that was not
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
92
   /// syntactically valid SXP.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
93
   pub fn is_syntax(&self) -> bool {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
94
     self.classify() == Category::Syntax
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
95
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
96
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
97
   /// Returns true if this error was caused by input data that was
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
98
   /// semantically incorrect.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
99
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
100
   /// For example, SXP containing a number is semantically incorrect when the
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
101
   /// type being deserialized into holds a String.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
102
   pub fn is_data(&self) -> bool {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
103
     self.classify() == Category::Data
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
104
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
105
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
106
   /// Returns true if this error was caused by prematurely reaching the end of
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
107
   /// the input data.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
108
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
109
   /// Callers that process streaming input may be interested in retrying the
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
110
   /// deserialization once more data is available.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
111
   pub fn is_eof(&self) -> bool {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
112
     self.classify() == Category::Eof
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
113
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
114
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
115
   /// The kind reported by the underlying standard library I/O error, if this
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
116
   /// error was caused by a failure to read or write bytes on an I/O stream.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
117
   #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
118
   pub fn io_error_kind(&self) -> Option<ErrorKind> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
119
     if let ErrorCode::Io(io_error) = &self.err.code {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
120
       Some(io_error.kind())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
121
     } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
122
       None
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
123
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
124
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
125
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
126
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
127
 /// Categorizes the cause of a `sxp::Error`.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
128
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
129
 pub enum Category {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
130
   /// The error was caused by a failure to read or write bytes on an I/O
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
131
   /// stream.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
132
   Io,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
133
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
134
   /// The error was caused by input that was not syntactically valid SXP.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
135
   Syntax,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
136
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
137
   /// The error was caused by input data that was semantically incorrect.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
138
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
139
   /// For example, SXP containing a number is semantically incorrect when the
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
140
   /// type being deserialized into holds a String.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
141
   Data,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
142
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
143
   /// The error was caused by prematurely reaching the end of the input data.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
144
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
145
   /// Callers that process streaming input may be interested in retrying the
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
146
   /// deserialization once more data is available.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
147
   Eof,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
148
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
149
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
150
 #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
151
 #[allow(clippy::fallible_impl_from)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
152
 impl From<Error> for io::Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
153
   /// Convert a `sxp::Error` into an `io::Error`.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
154
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
155
   /// SXP syntax and data errors are turned into `InvalidData` I/O errors.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
156
   /// EOF errors are turned into `UnexpectedEof` I/O errors.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
157
   fn from(j: Error) -> Self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
158
     if let ErrorCode::Io(err) = j.err.code {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
159
       err
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
160
     } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
161
       match j.classify() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
162
         Category::Io => unreachable!(),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
163
         Category::Syntax | Category::Data => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
164
           io::Error::new(ErrorKind::InvalidData, j)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
165
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
166
         Category::Eof => io::Error::new(ErrorKind::UnexpectedEof, j),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
167
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
168
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
169
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
170
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
171
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
172
 struct ErrorImpl {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
173
   code: ErrorCode,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
174
   line: usize,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
175
   column: usize,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
176
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
177
 
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
178
 #[allow(dead_code)]
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
179
 pub(crate) enum ErrorCode {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
180
   /// Catchall for syntax error messages
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
181
   Message(Box<str>),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
182
   /// Some I/O error occurred while serializing or deserializing.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
183
   Io(io::Error),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
184
   /// EOF while parsing a list.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
185
   EofWhileParsingList,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
186
   /// EOF while parsing an object.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
187
   EofWhileParsingObject,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
188
   /// EOF while parsing a string.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
189
   EofWhileParsingString,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
190
   /// EOF while parsing a SXP value.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
191
   EofWhileParsingValue,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
192
   /// Expected this character to be ')'.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
193
   ExpectedListEnd,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
194
   /// Expected to parse a symbol.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
195
   ExpectedSomeSymbol,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
196
   /// Expected this character to start a SXP value.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
197
   ExpectedSomeValue,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
198
   /// Expected this character to be '"'.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
199
   ExpectedDoubleQuote,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
200
   /// Invalid hex escape code.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
201
   InvalidEscape,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
202
   /// Invalid number.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
203
   InvalidNumber,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
204
   /// Number is bigger than the maximum value of its type.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
205
   NumberOutOfRange,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
206
   /// Invalid unicode code point.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
207
   InvalidUnicodeCodePoint,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
208
   /// Control character found while parsing a string.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
209
   ControlCharacterWhileParsingString,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
210
   /// Object key is not a symbol.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
211
   KeyMustBeASymbol,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
212
   /// Lone leading surrogate in hex escape.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
213
   LoneLeadingSurrogateInHexEscape,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
214
   /// SXP has non-whitespace trailing characters after the value.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
215
   TrailingCharacters,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
216
   /// Unexpected end of hex escape.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
217
   UnexpectedEndOfHexEscape,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
218
   /// Encountered nesting of SXP maps and arrays more than 128 layers deep.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
219
   RecursionLimitExceeded,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
220
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
221
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
222
 impl Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
223
   #[cold]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
224
   pub(crate) fn syntax(code: ErrorCode, line: usize, column: usize) -> Self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
225
     Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
226
       err: Box::new(ErrorImpl { code, line, column }),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
227
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
228
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
229
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
230
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
231
   #[cold]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
232
   pub fn io(error: io::Error) -> Self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
233
     Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
234
       err: Box::new(ErrorImpl {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
235
         code: ErrorCode::Io(error),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
236
         line: 0,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
237
         column: 0,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
238
       }),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
239
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
240
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
241
 
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
242
   //   #[cold]
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
243
   //   pub(crate) fn fix_position<F>(self, f: F) -> Self
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
244
   //   where
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
245
   //     F: FnOnce(ErrorCode) -> Error,
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
246
   //   {
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
247
   //     if self.err.line == 0 {
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
248
   //       f(self.err.code)
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
249
   //     } else {
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
250
   //       self
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
251
   //     }
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
252
   //   }
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
253
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
254
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
255
 impl Display for ErrorCode {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
256
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
257
     match self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
258
       ErrorCode::Message(msg) => f.write_str(msg),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
259
       ErrorCode::Io(err) => Display::fmt(err, f),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
260
       ErrorCode::EofWhileParsingList => f.write_str("EOF while parsing a list"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
261
       ErrorCode::EofWhileParsingObject => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
262
         f.write_str("EOF while parsing an object")
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
263
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
264
       ErrorCode::EofWhileParsingString => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
265
         f.write_str("EOF while parsing a string")
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
266
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
267
       ErrorCode::EofWhileParsingValue => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
268
         f.write_str("EOF while parsing a value")
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
269
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
270
       ErrorCode::ExpectedListEnd => f.write_str("expected `)`"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
271
       ErrorCode::ExpectedSomeSymbol => f.write_str("expected symbol"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
272
       ErrorCode::ExpectedSomeValue => f.write_str("expected value"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
273
       ErrorCode::ExpectedDoubleQuote => f.write_str("expected `\"`"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
274
       ErrorCode::InvalidEscape => f.write_str("invalid escape"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
275
       ErrorCode::InvalidNumber => f.write_str("invalid number"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
276
       ErrorCode::NumberOutOfRange => f.write_str("number out of range"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
277
       ErrorCode::InvalidUnicodeCodePoint => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
278
         f.write_str("invalid unicode code point")
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
279
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
280
       ErrorCode::ControlCharacterWhileParsingString => f.write_str(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
281
         "control character (\\u0000-\\u001F) found while parsing a string",
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
282
       ),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
283
       ErrorCode::KeyMustBeASymbol => f.write_str("key must be a symbol"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
284
       ErrorCode::LoneLeadingSurrogateInHexEscape => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
285
         f.write_str("lone leading surrogate in hex escape")
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
286
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
287
       ErrorCode::TrailingCharacters => f.write_str("trailing characters"),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
288
       ErrorCode::UnexpectedEndOfHexEscape => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
289
         f.write_str("unexpected end of hex escape")
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
290
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
291
       ErrorCode::RecursionLimitExceeded => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
292
         f.write_str("recursion limit exceeded")
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
293
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
294
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
295
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
296
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
297
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
298
 impl serde::de::StdError for Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
299
   #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
300
   fn source(&self) -> Option<&(dyn error::Error + 'static)> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
301
     match &self.err.code {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
302
       ErrorCode::Io(err) => err.source(),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
303
       _ => None,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
304
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
305
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
306
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
307
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
308
 impl Display for Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
309
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
310
     Display::fmt(&*self.err, f)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
311
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
312
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
313
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
314
 impl Display for ErrorImpl {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
315
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
316
     if self.line == 0 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
317
       Display::fmt(&self.code, f)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
318
     } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
319
       write!(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
320
         f,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
321
         "{} at line {} column {}",
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
322
         self.code, self.line, self.column
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
323
       )
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
324
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
325
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
326
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
327
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
328
 // Remove two layers of verbosity from the debug representation. Humans often
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
329
 // end up seeing this representation because it is what unwrap() shows.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
330
 impl Debug for Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
331
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
332
     write!(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
333
       f,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
334
       "(error {:?} (:line {} :column {}))",
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
335
       self.err.code.to_string(),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
336
       self.err.line,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
337
       self.err.column
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
338
     )
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
339
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
340
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
341
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
342
 impl de::Error for Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
343
   #[cold]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
344
   fn custom<T: Display>(msg: T) -> Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
345
     make_error(msg.to_string())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
346
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
347
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
348
   #[cold]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
349
   fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
350
     if let de::Unexpected::Unit = unexp {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
351
       Error::custom(format_args!("(:invalid-type nil :expected {})", exp))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
352
     } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
353
       Error::custom(format_args!("(:invalid-type {} :expected {})", unexp, exp))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
354
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
355
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
356
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
357
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
358
 impl ser::Error for Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
359
   #[cold]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
360
   fn custom<T: Display>(msg: T) -> Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
361
     make_error(msg.to_string())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
362
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
363
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
364
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
365
 // Parse our own error message that looks like "{} at line {} column {}" to work
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
366
 // around erased-serde round-tripping the error through de::Error::custom.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
367
 fn make_error(mut msg: String) -> Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
368
   let (line, column) = parse_line_col(&mut msg).unwrap_or((0, 0));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
369
   Error {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
370
     err: Box::new(ErrorImpl {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
371
       code: ErrorCode::Message(msg.into_boxed_str()),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
372
       line,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
373
       column,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
374
     }),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
375
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
376
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
377
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
378
 fn parse_line_col(msg: &mut String) -> Option<(usize, usize)> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
379
   let start_of_suffix = match msg.rfind(" at line ") {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
380
     Some(index) => index,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
381
     None => return None,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
382
   };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
383
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
384
   // Find start and end of line number.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
385
   let start_of_line = start_of_suffix + " at line ".len();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
386
   let mut end_of_line = start_of_line;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
387
   while starts_with_digit(&msg[end_of_line..]) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
388
     end_of_line += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
389
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
390
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
391
   if !msg[end_of_line..].starts_with(" column ") {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
392
     return None;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
393
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
394
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
395
   // Find start and end of column number.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
396
   let start_of_column = end_of_line + " column ".len();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
397
   let mut end_of_column = start_of_column;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
398
   while starts_with_digit(&msg[end_of_column..]) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
399
     end_of_column += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
400
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
401
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
402
   if end_of_column < msg.len() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
403
     return None;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
404
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
405
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
406
   // Parse numbers.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
407
   let line = match usize::from_str(&msg[start_of_line..end_of_line]) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
408
     Ok(line) => line,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
409
     Err(_) => return None,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
410
   };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
411
   let column = match usize::from_str(&msg[start_of_column..end_of_column]) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
412
     Ok(column) => column,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
413
     Err(_) => return None,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
414
   };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
415
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
416
   msg.truncate(start_of_suffix);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
417
   Some((line, column))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
418
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
419
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
420
 fn starts_with_digit(slice: &str) -> bool {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
421
   match slice.as_bytes().first() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
422
     None => false,
189
3d78bed56188 apply clippy fixes
Richard Westhaver <ellis@rwest.io>
parents: 67
diff changeset
423
     Some(&byte) => byte.is_ascii_digit(),
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
424
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
425
 }