1use core::fmt;
2use std::{num::ParseIntError, str::Utf8Error};
3
4use fluent_uri::{resolve::ResolveError, ParseError, Uri};
5
6#[derive(Debug)]
8pub enum Error {
9 Unretrievable {
11 uri: String,
12 source: Box<dyn std::error::Error + Send + Sync>,
13 },
14 PointerToNowhere { pointer: String },
16 InvalidPercentEncoding { pointer: String, source: Utf8Error },
18 InvalidArrayIndex {
20 pointer: String,
21 index: String,
22 source: ParseIntError,
23 },
24 NoSuchAnchor { anchor: String },
26 InvalidAnchor { anchor: String },
28 InvalidUri(UriError),
30 UnknownSpecification { specification: String },
32 CircularMetaschema { uri: String },
34}
35
36impl Error {
37 pub(crate) fn pointer_to_nowhere(pointer: impl Into<String>) -> Error {
38 Error::PointerToNowhere {
39 pointer: pointer.into(),
40 }
41 }
42 pub(crate) fn invalid_percent_encoding(pointer: impl Into<String>, source: Utf8Error) -> Error {
43 Error::InvalidPercentEncoding {
44 pointer: pointer.into(),
45 source,
46 }
47 }
48 pub(crate) fn invalid_array_index(
49 pointer: impl Into<String>,
50 index: impl Into<String>,
51 source: ParseIntError,
52 ) -> Error {
53 Error::InvalidArrayIndex {
54 pointer: pointer.into(),
55 index: index.into(),
56 source,
57 }
58 }
59 pub(crate) fn invalid_anchor(anchor: impl Into<String>) -> Error {
60 Error::InvalidAnchor {
61 anchor: anchor.into(),
62 }
63 }
64 pub(crate) fn no_such_anchor(anchor: impl Into<String>) -> Error {
65 Error::NoSuchAnchor {
66 anchor: anchor.into(),
67 }
68 }
69
70 pub fn unknown_specification(specification: impl Into<String>) -> Error {
71 Error::UnknownSpecification {
72 specification: specification.into(),
73 }
74 }
75
76 pub fn circular_metaschema(uri: impl Into<String>) -> Error {
77 Error::CircularMetaschema { uri: uri.into() }
78 }
79
80 pub fn unretrievable(
81 uri: impl Into<String>,
82 source: Box<dyn std::error::Error + Send + Sync>,
83 ) -> Error {
84 Error::Unretrievable {
85 uri: uri.into(),
86 source,
87 }
88 }
89
90 pub(crate) fn uri_parsing_error(uri: impl Into<String>, error: ParseError) -> Error {
91 Error::InvalidUri(UriError::Parse {
92 uri: uri.into(),
93 is_reference: false,
94 error,
95 })
96 }
97
98 pub(crate) fn uri_reference_parsing_error(uri: impl Into<String>, error: ParseError) -> Error {
99 Error::InvalidUri(UriError::Parse {
100 uri: uri.into(),
101 is_reference: true,
102 error,
103 })
104 }
105
106 pub(crate) fn uri_resolving_error(
107 uri: impl Into<String>,
108 base: Uri<&str>,
109 error: ResolveError,
110 ) -> Error {
111 Error::InvalidUri(UriError::Resolve {
112 uri: uri.into(),
113 base: base.to_owned(),
114 error,
115 })
116 }
117}
118
119impl fmt::Display for Error {
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 match self {
122 Error::Unretrievable { uri, source } => {
123 f.write_fmt(format_args!("Resource '{uri}' is not present in a registry and retrieving it failed: {source}"))
124 },
125 Error::PointerToNowhere { pointer } => {
126 f.write_fmt(format_args!("Pointer '{pointer}' does not exist"))
127 }
128 Error::InvalidPercentEncoding { pointer, .. } => {
129 f.write_fmt(format_args!("Invalid percent encoding in pointer '{pointer}': the decoded bytes do not represent valid UTF-8"))
130 }
131 Error::InvalidArrayIndex { pointer, index, .. } => {
132 f.write_fmt(format_args!("Failed to parse array index '{index}' in pointer '{pointer}'"))
133 }
134 Error::NoSuchAnchor { anchor } => {
135 f.write_fmt(format_args!("Anchor '{anchor}' does not exist"))
136 }
137 Error::InvalidAnchor { anchor } => {
138 f.write_fmt(format_args!("Anchor '{anchor}' is invalid"))
139 }
140 Error::InvalidUri(error) => error.fmt(f),
141 Error::UnknownSpecification { specification } => {
142 write!(f, "Unknown meta-schema: '{specification}'. Custom meta-schemas must be registered in the registry before use")
143 }
144 Error::CircularMetaschema { uri } => {
145 write!(f, "Circular meta-schema reference detected at '{uri}'")
146 }
147 }
148 }
149}
150
151impl std::error::Error for Error {
152 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
153 match self {
154 Error::Unretrievable { source, .. } => Some(&**source),
155 Error::InvalidUri(error) => Some(error),
156 Error::InvalidPercentEncoding { source, .. } => Some(source),
157 Error::InvalidArrayIndex { source, .. } => Some(source),
158 _ => None,
159 }
160 }
161}
162
163#[derive(Debug)]
165pub enum UriError {
166 Parse {
167 uri: String,
168 is_reference: bool,
169 error: ParseError,
170 },
171 Resolve {
172 uri: String,
173 base: Uri<String>,
174 error: ResolveError,
175 },
176}
177
178impl fmt::Display for UriError {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 match self {
181 UriError::Parse {
182 uri,
183 is_reference,
184 error,
185 } => {
186 if *is_reference {
187 f.write_fmt(format_args!("Invalid URI reference '{uri}': {error}"))
188 } else {
189 f.write_fmt(format_args!("Invalid URI '{uri}': {error}"))
190 }
191 }
192 UriError::Resolve { uri, base, error } => f.write_fmt(format_args!(
193 "Failed to resolve '{uri}' against '{base}': {error}"
194 )),
195 }
196 }
197}
198
199impl std::error::Error for UriError {
200 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
201 match self {
202 UriError::Parse { error, .. } => Some(error),
203 UriError::Resolve { error, .. } => Some(error),
204 }
205 }
206}