glean_core/
error.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use std::ffi::OsString;
6use std::fmt::{self, Display};
7use std::io;
8use std::result;
9
10use rkv::StoreError;
11
12/// A specialized [`Result`] type for this crate's operations.
13///
14/// This is generally used to avoid writing out [`Error`] directly and
15/// is otherwise a direct mapping to [`Result`].
16///
17/// [`Result`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html
18/// [`Error`]: std.struct.Error.html
19pub type Result<T, E = Error> = result::Result<T, E>;
20
21/// A list enumerating the categories of errors in this crate.
22///
23/// [`Error`]: https://doc.rust-lang.org/stable/std/error/trait.Error.html
24///
25/// This list is intended to grow over time and it is not recommended to
26/// exhaustively match against it.
27#[derive(Debug)]
28#[non_exhaustive]
29pub enum ErrorKind {
30    /// Lifetime conversion failed
31    Lifetime(i32),
32
33    /// IO error
34    IoError(io::Error),
35
36    /// IO error
37    Rkv(StoreError),
38
39    /// JSON error
40    Json(serde_json::error::Error),
41
42    /// TimeUnit conversion failed
43    TimeUnit(i32),
44
45    /// MemoryUnit conversion failed
46    MemoryUnit(i32),
47
48    /// HistogramType conversion failed
49    HistogramType(i32),
50
51    /// [`OsString`] conversion failed
52    OsString(OsString),
53
54    /// Unknown error
55    Utf8Error,
56
57    /// Glean initialization was attempted with an invalid configuration
58    InvalidConfig,
59
60    /// Glean not initialized
61    NotInitialized,
62
63    /// Ping request body size overflowed
64    PingBodyOverflow(usize),
65}
66
67/// A specialized [`Error`] type for this crate's operations.
68///
69/// [`Error`]: https://doc.rust-lang.org/stable/std/error/trait.Error.html
70#[derive(Debug)]
71pub struct Error {
72    kind: ErrorKind,
73}
74
75impl Error {
76    /// Returns a new UTF-8 error
77    ///
78    /// This is exposed in order to expose conversion errors on the FFI layer.
79    pub fn utf8_error() -> Error {
80        Error {
81            kind: ErrorKind::Utf8Error,
82        }
83    }
84
85    /// Indicates an error that no requested global object is initialized
86    pub fn not_initialized() -> Error {
87        Error {
88            kind: ErrorKind::NotInitialized,
89        }
90    }
91
92    /// Returns the kind of the current error instance.
93    pub fn kind(&self) -> &ErrorKind {
94        &self.kind
95    }
96}
97
98impl std::error::Error for Error {}
99
100impl Display for Error {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        use ErrorKind::*;
103        match self.kind() {
104            Lifetime(l) => write!(f, "Lifetime conversion from {} failed", l),
105            IoError(e) => write!(f, "An I/O error occurred: {}", e),
106            Rkv(e) => write!(f, "An Rkv error occurred: {}", e),
107            Json(e) => write!(f, "A JSON error occurred: {}", e),
108            TimeUnit(t) => write!(f, "TimeUnit conversion from {} failed", t),
109            MemoryUnit(m) => write!(f, "MemoryUnit conversion from {} failed", m),
110            HistogramType(h) => write!(f, "HistogramType conversion from {} failed", h),
111            OsString(s) => write!(f, "OsString conversion from {:?} failed", s),
112            Utf8Error => write!(f, "Invalid UTF-8 byte sequence in string"),
113            InvalidConfig => write!(f, "Invalid Glean configuration provided"),
114            NotInitialized => write!(f, "Global Glean object missing"),
115            PingBodyOverflow(s) => write!(
116                f,
117                "Ping request body size exceeded maximum size allowed: {}kB.",
118                s / 1024
119            ),
120        }
121    }
122}
123
124impl From<ErrorKind> for Error {
125    fn from(kind: ErrorKind) -> Error {
126        Error { kind }
127    }
128}
129
130impl From<io::Error> for Error {
131    fn from(error: io::Error) -> Error {
132        Error {
133            kind: ErrorKind::IoError(error),
134        }
135    }
136}
137
138impl From<StoreError> for Error {
139    fn from(error: StoreError) -> Error {
140        Error {
141            kind: ErrorKind::Rkv(error),
142        }
143    }
144}
145
146impl From<serde_json::error::Error> for Error {
147    fn from(error: serde_json::error::Error) -> Error {
148        Error {
149            kind: ErrorKind::Json(error),
150        }
151    }
152}
153
154impl From<OsString> for Error {
155    fn from(error: OsString) -> Error {
156        Error {
157            kind: ErrorKind::OsString(error),
158        }
159    }
160}
161
162/// To satisfy integer conversion done by the macros on the FFI side, we need to be able to turn
163/// something infallible into an error.
164/// This will never actually be reached, as an integer-to-integer conversion is infallible.
165impl From<std::convert::Infallible> for Error {
166    fn from(_: std::convert::Infallible) -> Error {
167        unreachable!()
168    }
169}