rocket_community/form/error.rs
1//! Form error types.
2
3use std::borrow::Cow;
4use std::char::ParseCharError;
5use std::net::AddrParseError;
6use std::num::{ParseFloatError, ParseIntError};
7use std::str::{ParseBoolError, Utf8Error};
8use std::{fmt, io};
9
10use serde::{
11 ser::{SerializeStruct, Serializer},
12 Serialize,
13};
14
15use crate::data::ByteUnit;
16use crate::form::name::{Name, NameBuf};
17use crate::http::Status;
18
19/// A collection of [`Error`]s.
20///
21/// `Errors` is a thin wrapper around a `Vec<Error>` with convenient methods for
22/// modifying the internal `Error`s. It `Deref`s and `DerefMut`s to
23/// `Vec<Error>` for transparent access to the underlying vector.
24///
25/// # Matching Errors to Fields
26///
27/// To find the errors that correspond to a given field, use
28/// [`Error::is_for()`]. For example, to get all of the errors that correspond
29/// to the field `foo.bar`, you might write the following:
30///
31/// ```rust
32/// # extern crate rocket_community as rocket;
33/// use rocket::form::Errors;
34///
35/// let errors = Errors::new();
36/// let errors_for_foo = errors.iter().filter(|e| e.is_for("foo.bar"));
37/// ```
38///
39/// ## Constructing
40///
41/// An `Errors` can be constructed from anything that an `Error` can be
42/// constructed from. This includes [`Error`], [`ErrorKind`], and all of the
43/// types an `ErrorKind` can be constructed from. See
44/// [`ErrorKind`](ErrorKind#constructing) for the full list.
45///
46/// ```rust
47/// # extern crate rocket_community as rocket;
48/// use rocket::form;
49///
50/// fn at_most_10() -> form::Result<'static, usize> {
51/// // Using `From<PartIntError> => ErrorKind::Int => Errors`.
52/// let i: usize = "foo".parse()?;
53///
54/// if i > 10 {
55/// // `(Option<isize>, Option<isize>) => ErrorKind::OutOfRange => Errors`
56/// return Err((None, Some(10isize)).into());
57/// }
58///
59/// Ok(i)
60/// }
61/// ```
62#[derive(Default, Debug, PartialEq, Serialize)]
63#[serde(transparent)]
64pub struct Errors<'v>(Vec<Error<'v>>);
65
66/// A form error, potentially tied to a specific form field.
67///
68/// An `Error` is returned by [`FromForm`], [`FromFormField`], and [`validate`]
69/// procedures, typically as a collection of [`Errors`]. It potentially
70/// identifies a specific field that triggered the error via [`Error::name`] and
71/// the field's value via [`Error::value`].
72///
73/// An `Error` can occur because of a field's value that failed to parse or
74/// because other parts of a field or form were malformed; the [`Error::entity`]
75/// identifies the part of the form that resulted in the error.
76///
77/// [`FromForm`]: crate::form::FromForm
78/// [`FromFormField`]: crate::form::FromFormField
79/// [`validate`]: crate::form::validate
80///
81/// # Constructing
82///
83/// An `Error` can be constructed via [`Error::validation()`],
84/// [`Error::custom()`], or anything that an [`ErrorKind`] can be constructed
85/// from. See [`ErrorKind`](ErrorKind#constructing).
86///
87/// ```rust
88/// # extern crate rocket_community as rocket;
89/// use rocket::form::Error;
90///
91/// fn at_most_10_not_even() -> Result<usize, Error<'static>> {
92/// // Using `From<PartIntError> => ErrorKind::Int`.
93/// let i: usize = "foo".parse()?;
94///
95/// if i > 10 {
96/// // `From<(Option<isize>, Option<isize>)> => ErrorKind::OutOfRange`
97/// return Err((None, Some(10isize)).into());
98/// } else if i % 2 == 0 {
99/// return Err(Error::validation("integer cannot be even"));
100/// }
101///
102/// Ok(i)
103/// }
104/// ```
105///
106/// # Setting Field Metadata
107///
108/// When implementing [`FromFormField`], nothing has to be done for a field's
109/// metadata to be set: the blanket [`FromForm`] implementation sets it
110/// automatically.
111///
112/// When constructed from an `ErrorKind`, the entity is set to
113/// [`Entity::default_for()`] by default. Occasionally, the error's `entity` may
114/// need to be set manually. Return what would be useful to the end-consumer.
115///
116/// # Matching Errors to Fields
117///
118/// To determine whether an error corresponds to a given field, use
119/// [`Error::is_for()`]. For example, to get all of the errors that correspond
120/// to the field `foo.bar`, you might write the following:
121///
122/// ```rust
123/// # extern crate rocket_community as rocket;
124/// use rocket::form::Errors;
125///
126/// let errors = Errors::new();
127/// let errors_for_foo = errors.iter().filter(|e| e.is_for("foo.bar"));
128/// ```
129///
130/// # Serialization
131///
132/// When a value of this type is serialized, a `struct` or map with the
133/// following fields is emitted:
134///
135/// | field | type | description |
136/// |----------|----------------|--------------------------------------------------|
137/// | `name` | `Option<&str>` | the erroring field's name, if known |
138/// | `value` | `Option<&str>` | the erroring field's value, if known |
139/// | `entity` | `&str` | string representation of the erroring [`Entity`] |
140/// | `msg` | `&str` | concise message of the error |
141#[derive(Debug, PartialEq)]
142pub struct Error<'v> {
143 /// The name of the field, if it is known.
144 pub name: Option<NameBuf<'v>>,
145 /// The field's value, if it is known.
146 pub value: Option<Cow<'v, str>>,
147 /// The kind of error that occurred.
148 pub kind: ErrorKind<'v>,
149 /// The entity that caused the error.
150 pub entity: Entity,
151}
152
153/// The kind of form error that occurred.
154///
155/// ## Constructing
156///
157/// An `ErrorKind` can be constructed directly or via a `From` of the following
158/// types:
159///
160/// * `(Option<u64>, Option<u64>)` => [`ErrorKind::InvalidLength`]
161/// * `(Option<ByteUnit>, Option<ByteUnit>)` => [`ErrorKind::InvalidLength`]
162/// * `(Option<isize>, Option<isize>)` => [`ErrorKind::OutOfRange`]
163/// * `&[Cow<'_, str>]` or `Vec<Cow<'_, str>>` => [`ErrorKind::InvalidChoice`]
164/// * [`Utf8Error`] => [`ErrorKind::Utf8`]
165/// * [`ParseIntError`] => [`ErrorKind::Int`]
166/// * [`ParseFloatError`] => [`ErrorKind::Float`]
167/// * [`ParseBoolError`] => [`ErrorKind::Bool`]
168/// * [`AddrParseError`] => [`ErrorKind::Addr`]
169/// * [`io::Error`] => [`ErrorKind::Io`]
170/// * `Box<dyn std::error::Error + Send` => [`ErrorKind::Custom`]
171/// * `(Status, Box<dyn std::error::Error + Send)` => [`ErrorKind::Custom`]
172#[derive(Debug)]
173#[non_exhaustive]
174pub enum ErrorKind<'v> {
175 /// The value's length, in bytes, was outside the range `[min, max]`.
176 InvalidLength {
177 /// The minimum length required, inclusive.
178 min: Option<u64>,
179 /// The maximum length required, inclusive.
180 max: Option<u64>,
181 },
182 /// The value wasn't one of the valid `choices`.
183 InvalidChoice {
184 /// The choices that were expected.
185 choices: Cow<'v, [Cow<'v, str>]>,
186 },
187 /// The integer value was outside the range `[start, end]`.
188 OutOfRange {
189 /// The start of the acceptable range, inclusive.
190 start: Option<isize>,
191 /// The end of the acceptable range, inclusive.
192 end: Option<isize>,
193 },
194 /// A custom validation routine failed with message `.0`.
195 Validation(Cow<'v, str>),
196 /// One entity was expected but more than one was received.
197 Duplicate,
198 /// An entity was expected but was not received.
199 Missing,
200 /// An unexpected entity was received.
201 Unexpected,
202 /// An unknown entity was received.
203 Unknown,
204 /// A custom error occurred. Status defaults to
205 /// [`Status::UnprocessableEntity`] if one is not directly specified.
206 Custom(Status, Box<dyn std::error::Error + Send>),
207 /// An error while parsing a multipart form occurred.
208 Multipart(multer::Error),
209 /// A string was invalid UTF-8.
210 Utf8(Utf8Error),
211 /// A value failed to parse as a char.
212 Char(ParseCharError),
213 /// A value failed to parse as an integer.
214 Int(ParseIntError),
215 /// A value failed to parse as a boolean.
216 Bool(ParseBoolError),
217 /// A value failed to parse as a float.
218 Float(ParseFloatError),
219 /// A value failed to parse as an IP or socket address.
220 Addr(AddrParseError),
221 /// An I/O error occurred.
222 Io(io::Error),
223}
224
225/// The erroneous form entity or form component.
226#[derive(Debug, Copy, Clone, PartialEq, Eq)]
227pub enum Entity {
228 /// The form itself.
229 Form,
230 /// A field.
231 Field,
232 /// A [`ValueField`](crate::form::ValueField).
233 ValueField,
234 /// A [`DataField`](crate::form::DataField).
235 DataField,
236 /// A field name.
237 Name,
238 /// A field value.
239 Value,
240 /// A field name key.
241 Key,
242 /// A field name key index at index `.0`.
243 Index(usize),
244}
245
246impl<'v> Errors<'v> {
247 /// Create an empty collection of errors.
248 ///
249 /// # Example
250 ///
251 /// ```rust
252 /// # extern crate rocket_community as rocket;
253 /// use rocket::form::Errors;
254 ///
255 /// let errors = Errors::new();
256 /// assert!(errors.is_empty());
257 /// ```
258 pub fn new() -> Self {
259 Errors(vec![])
260 }
261
262 /// Consumes `self` and returns a new `Errors` with each field name set to
263 /// `name` if it was not already set.
264 ///
265 /// # Example
266 ///
267 /// ```rust
268 /// # extern crate rocket_community as rocket;
269 /// use rocket::form::error::{Errors, ErrorKind};
270 ///
271 /// let mut errors = Errors::from(ErrorKind::Missing);
272 /// assert!(errors[0].name.is_none());
273 ///
274 /// let mut errors = errors.with_name("foo");
275 /// assert_eq!(errors[0].name.as_ref().unwrap(), "foo");
276 ///
277 /// errors.push(ErrorKind::Duplicate.into());
278 /// let errors = errors.with_name("bar");
279 /// assert_eq!(errors[0].name.as_ref().unwrap(), "foo");
280 /// assert_eq!(errors[1].name.as_ref().unwrap(), "bar");
281 /// ```
282 pub fn with_name<N: Into<NameBuf<'v>>>(mut self, name: N) -> Self {
283 self.set_name(name);
284 self
285 }
286
287 /// Set the field name of each error in `self` to `name` if it is not
288 /// already set.
289 ///
290 /// # Example
291 ///
292 /// ```rust
293 /// # extern crate rocket_community as rocket;
294 /// use rocket::form::error::{Errors, ErrorKind};
295 ///
296 /// let mut errors = Errors::from(ErrorKind::Missing);
297 /// assert!(errors[0].name.is_none());
298 ///
299 /// errors.set_name("foo");
300 /// assert_eq!(errors[0].name.as_ref().unwrap(), "foo");
301 ///
302 /// errors.push(ErrorKind::Duplicate.into());
303 /// let errors = errors.with_name("bar");
304 /// assert_eq!(errors[0].name.as_ref().unwrap(), "foo");
305 /// assert_eq!(errors[1].name.as_ref().unwrap(), "bar");
306 /// ```
307 pub fn set_name<N: Into<NameBuf<'v>>>(&mut self, name: N) {
308 let name = name.into();
309 for error in self.iter_mut() {
310 if error.name.is_none() {
311 error.set_name(name.clone());
312 }
313 }
314 }
315
316 /// Consumes `self` and returns a new `Errors` with each field value set to
317 /// `value` if it was not already set.
318 ///
319 /// # Example
320 ///
321 /// ```rust
322 /// # extern crate rocket_community as rocket;
323 /// use rocket::form::error::{Errors, ErrorKind};
324 ///
325 /// let mut errors = Errors::from(ErrorKind::Missing);
326 /// assert!(errors[0].value.is_none());
327 ///
328 /// let mut errors = errors.with_value("foo");
329 /// assert_eq!(errors[0].value.as_ref().unwrap(), "foo");
330 ///
331 /// errors.push(ErrorKind::Duplicate.into());
332 /// let errors = errors.with_value("bar");
333 /// assert_eq!(errors[0].value.as_ref().unwrap(), "foo");
334 /// assert_eq!(errors[1].value.as_ref().unwrap(), "bar");
335 /// ```
336 pub fn with_value(mut self, value: &'v str) -> Self {
337 self.set_value(value);
338 self
339 }
340
341 /// Set the field value of each error in `self` to `value` if it is not
342 /// already set.
343 ///
344 /// # Example
345 ///
346 /// ```rust
347 /// # extern crate rocket_community as rocket;
348 /// use rocket::form::error::{Errors, ErrorKind};
349 ///
350 /// let mut errors = Errors::from(ErrorKind::Missing);
351 /// assert!(errors[0].value.is_none());
352 ///
353 /// errors.set_value("foo");
354 /// assert_eq!(errors[0].value.as_ref().unwrap(), "foo");
355 ///
356 /// errors.push(ErrorKind::Duplicate.into());
357 /// let errors = errors.with_value("bar");
358 /// assert_eq!(errors[0].value.as_ref().unwrap(), "foo");
359 /// assert_eq!(errors[1].value.as_ref().unwrap(), "bar");
360 /// ```
361 pub fn set_value(&mut self, value: &'v str) {
362 self.iter_mut().for_each(|e| e.set_value(value));
363 }
364
365 /// Returns the highest [`Error::status()`] of all of the errors in `self`
366 /// or [`Status::InternalServerError`] if `self` is empty. This is the
367 /// status that is set by the [`Form`](crate::form::Form) data guard on
368 /// error.
369 ///
370 /// See [`Error::status()`] for the corresponding status code of each
371 /// [`Error`] variant.
372 ///
373 /// # Example
374 ///
375 /// ```rust
376 /// # extern crate rocket_community as rocket;
377 /// use rocket::form::error::{Error, Errors, ErrorKind};
378 /// use rocket::http::Status;
379 ///
380 /// let mut errors = Errors::new();
381 /// assert_eq!(errors.status(), Status::InternalServerError);
382 ///
383 /// errors.push(Error::from((None, Some(10u64))));
384 /// assert_eq!(errors.status(), Status::PayloadTooLarge);
385 ///
386 /// errors.push(Error::from(ErrorKind::Missing));
387 /// assert_eq!(errors.status(), Status::UnprocessableEntity);
388 /// ```
389 pub fn status(&self) -> Status {
390 let max = self.iter().map(|e| e.status()).max();
391 max.unwrap_or(Status::InternalServerError)
392 }
393}
394
395impl crate::http::ext::IntoOwned for Errors<'_> {
396 type Owned = Errors<'static>;
397
398 fn into_owned(self) -> Self::Owned {
399 Errors(self.0.into_owned())
400 }
401}
402
403impl fmt::Display for Errors<'_> {
404 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405 write!(f, "{} error(s):", self.len())?;
406 for error in self.iter() {
407 write!(f, "\n{}", error)?;
408 }
409
410 Ok(())
411 }
412}
413
414impl<'v> std::ops::Deref for Errors<'v> {
415 type Target = Vec<Error<'v>>;
416
417 fn deref(&self) -> &Self::Target {
418 &self.0
419 }
420}
421
422impl<'v> std::ops::DerefMut for Errors<'v> {
423 fn deref_mut(&mut self) -> &mut Self::Target {
424 &mut self.0
425 }
426}
427
428impl<'v, T: Into<Error<'v>>> From<T> for Errors<'v> {
429 #[inline(always)]
430 fn from(e: T) -> Self {
431 Errors(vec![e.into()])
432 }
433}
434
435impl<'v> From<Vec<Error<'v>>> for Errors<'v> {
436 #[inline(always)]
437 fn from(v: Vec<Error<'v>>) -> Self {
438 Errors(v)
439 }
440}
441
442impl<'v> IntoIterator for Errors<'v> {
443 type Item = Error<'v>;
444
445 type IntoIter = <Vec<Error<'v>> as IntoIterator>::IntoIter;
446
447 fn into_iter(self) -> Self::IntoIter {
448 self.0.into_iter()
449 }
450}
451
452impl<'v> Error<'v> {
453 /// Creates a new `Error` with `ErrorKind::Custom`.
454 ///
455 /// For validation errors, use [`Error::validation()`].
456 ///
457 /// # Example
458 ///
459 /// ```rust
460 /// # extern crate rocket_community as rocket;
461 /// use rocket::form::Error;
462 ///
463 /// fn from_fmt(error: std::fmt::Error) -> Error<'static> {
464 /// Error::custom(error)
465 /// }
466 /// ```
467 pub fn custom<E>(error: E) -> Self
468 where
469 E: std::error::Error + Send + 'static,
470 {
471 (Box::new(error) as Box<dyn std::error::Error + Send>).into()
472 }
473
474 /// Creates a new `Error` with `ErrorKind::Validation` and message `msg`.
475 ///
476 /// # Example
477 ///
478 /// ```rust
479 /// # extern crate rocket_community as rocket;
480 /// use rocket::form::error::{Error, ErrorKind, Entity};
481 ///
482 /// let error = Error::validation("invalid foo: need bar");
483 /// assert!(matches!(error.kind, ErrorKind::Validation(_)));
484 /// assert_eq!(error.entity, Entity::Value);
485 /// ```
486 pub fn validation<S: Into<Cow<'v, str>>>(msg: S) -> Self {
487 ErrorKind::Validation(msg.into()).into()
488 }
489
490 /// Consumes `self` and returns a new `Error` with the entity set to
491 /// `entity`.
492 ///
493 /// # Example
494 ///
495 /// ```rust
496 /// # extern crate rocket_community as rocket;
497 /// use rocket::form::error::{Error, ErrorKind, Entity};
498 ///
499 /// let error = Error::from(ErrorKind::Missing);
500 /// assert_eq!(error.entity, Entity::Field);
501 ///
502 /// let error = error.with_entity(Entity::Key);
503 /// assert_eq!(error.entity, Entity::Key);
504 /// ```
505 pub fn with_entity(mut self, entity: Entity) -> Self {
506 self.set_entity(entity);
507 self
508 }
509
510 /// Sets the error's entity to `entity.`
511 ///
512 /// # Example
513 ///
514 /// ```rust
515 /// # extern crate rocket_community as rocket;
516 /// use rocket::form::error::{Error, ErrorKind, Entity};
517 ///
518 /// let mut error = Error::from(ErrorKind::Missing);
519 /// assert_eq!(error.entity, Entity::Field);
520 ///
521 /// error.set_entity(Entity::Key);
522 /// assert_eq!(error.entity, Entity::Key);
523 /// ```
524 pub fn set_entity(&mut self, entity: Entity) {
525 self.entity = entity;
526 }
527
528 /// Consumes `self` and returns a new `Error` with the field name set to
529 /// `name` if it was not already set.
530 ///
531 /// # Example
532 ///
533 /// ```rust
534 /// # extern crate rocket_community as rocket;
535 /// use rocket::form::error::{Error, ErrorKind};
536 ///
537 /// let error = Error::from(ErrorKind::Missing);
538 /// assert!(error.name.is_none());
539 ///
540 /// let error = error.with_name("foo");
541 /// assert_eq!(error.name.as_ref().unwrap(), "foo");
542 ///
543 /// let error = error.with_name("bar");
544 /// assert_eq!(error.name.as_ref().unwrap(), "foo");
545 /// ```
546 pub fn with_name<N: Into<NameBuf<'v>>>(mut self, name: N) -> Self {
547 self.set_name(name);
548 self
549 }
550
551 /// Sets the field name of `self` to `name` if it is not already set.
552 ///
553 /// # Example
554 ///
555 /// ```rust
556 /// # extern crate rocket_community as rocket;
557 /// use rocket::form::error::{Error, ErrorKind};
558 ///
559 /// let mut error = Error::from(ErrorKind::Missing);
560 /// assert!(error.name.is_none());
561 ///
562 /// error.set_name("foo");
563 /// assert_eq!(error.name.as_ref().unwrap(), "foo");
564 ///
565 /// let error = error.with_name("bar");
566 /// assert_eq!(error.name.as_ref().unwrap(), "foo");
567 /// ```
568 pub fn set_name<N: Into<NameBuf<'v>>>(&mut self, name: N) {
569 if self.name.is_none() {
570 self.name = Some(name.into());
571 }
572 }
573
574 /// Consumes `self` and returns a new `Error` with the value set to `value`
575 /// if it was not already set.
576 ///
577 /// # Example
578 ///
579 /// ```rust
580 /// # extern crate rocket_community as rocket;
581 /// use rocket::form::error::{Error, ErrorKind};
582 ///
583 /// let error = Error::from(ErrorKind::Missing);
584 /// assert!(error.value.is_none());
585 ///
586 /// let error = error.with_value("foo");
587 /// assert_eq!(error.value.as_ref().unwrap(), "foo");
588 ///
589 /// let error = error.with_value("bar");
590 /// assert_eq!(error.value.as_ref().unwrap(), "foo");
591 /// ```
592 pub fn with_value(mut self, value: &'v str) -> Self {
593 self.set_value(value);
594 self
595 }
596
597 /// Set the field value of `self` to `value` if it is not already set.
598 ///
599 /// # Example
600 ///
601 /// ```rust
602 /// # extern crate rocket_community as rocket;
603 /// use rocket::form::error::{Error, ErrorKind};
604 ///
605 /// let mut error = Error::from(ErrorKind::Missing);
606 /// assert!(error.value.is_none());
607 ///
608 /// error.set_value("foo");
609 /// assert_eq!(error.value.as_ref().unwrap(), "foo");
610 ///
611 /// error.set_value("bar");
612 /// assert_eq!(error.value.as_ref().unwrap(), "foo");
613 /// ```
614 pub fn set_value(&mut self, value: &'v str) {
615 if self.value.is_none() {
616 self.value = Some(value.into());
617 }
618 }
619
620 /// Returns `true` if this error applies to a field named `name`. **This is
621 /// _different_ than simply comparing `name`.**
622 ///
623 /// Unlike [`Error::is_for_exactly()`], this method returns `true` if the
624 /// error's field name is a **prefix of `name`**. This is typically what is
625 /// desired as errors apply to a field and its children: `a.b` applies to
626 /// the nested fields `a.b.c`, `a.b.d` and so on.
627 ///
628 /// Returns `false` if `self` has no field name.
629 ///
630 /// # Example
631 ///
632 /// ```rust
633 /// # extern crate rocket_community as rocket;
634 /// use rocket::form::Error;
635 ///
636 /// // returns `false` without a field name
637 /// let error = Error::validation("bad `foo`");
638 /// assert!(!error.is_for_exactly("a.b"));
639 ///
640 /// // `a.b` is a prefix all of these field names
641 /// let error = error.with_name("a.b");
642 /// assert!(error.is_for("a.b"));
643 /// assert!(error.is_for("a[b]"));
644 /// assert!(error.is_for("a.b.c"));
645 /// assert!(error.is_for("a.b[c]"));
646 /// assert!(error.is_for("a.b.c[d]"));
647 /// assert!(error.is_for("a.b.c.d.foo"));
648 ///
649 /// // ...but not of these.
650 /// assert!(!error.is_for("a.c"));
651 /// assert!(!error.is_for("a"));
652 /// ```
653 pub fn is_for<N: AsRef<Name>>(&self, name: N) -> bool {
654 self.name
655 .as_ref()
656 .map(|e_name| {
657 if e_name.is_empty() != name.as_ref().is_empty() {
658 return false;
659 }
660
661 let mut e_keys = e_name.keys();
662 let mut n_keys = name.as_ref().keys();
663 loop {
664 match (e_keys.next(), n_keys.next()) {
665 (Some(e), Some(n)) if e == n => continue,
666 (Some(_), Some(_)) => return false,
667 (Some(_), None) => return false,
668 (None, _) => break,
669 }
670 }
671
672 true
673 })
674 .unwrap_or(false)
675 }
676
677 /// Returns `true` if this error applies to exactly the field named `name`.
678 /// Returns `false` if `self` has no field name.
679 ///
680 /// Unlike [`Error::is_for()`], this method returns `true` only when the
681 /// error's field name is exactly `name`. This is _not_ typically what is
682 /// desired.
683 ///
684 /// # Example
685 ///
686 /// ```rust
687 /// # extern crate rocket_community as rocket;
688 /// use rocket::form::Error;
689 ///
690 /// // returns `false` without a field name
691 /// let error = Error::validation("bad `foo`");
692 /// assert!(!error.is_for_exactly("a.b"));
693 ///
694 /// let error = error.with_name("a.b");
695 /// assert!(error.is_for_exactly("a.b"));
696 /// assert!(error.is_for_exactly("a[b]"));
697 ///
698 /// // does not return `true` when the name is a prefix
699 /// assert!(!error.is_for_exactly("a.b.c"));
700 /// assert!(!error.is_for_exactly("a.b[c]"));
701 /// assert!(!error.is_for_exactly("a.b.c[d]"));
702 /// assert!(!error.is_for_exactly("a.b.c.d.foo"));
703 ///
704 /// // does not return `true` when the name is different
705 /// assert!(!error.is_for("a.c"));
706 /// assert!(!error.is_for("a"));
707 /// ```
708 pub fn is_for_exactly<N: AsRef<Name>>(&self, name: N) -> bool {
709 self.name
710 .as_ref()
711 .map(|n| name.as_ref() == n)
712 .unwrap_or(false)
713 }
714
715 /// Returns the most reasonable [`Status`] associated with this error.
716 ///
717 /// For an [`ErrorKind::Custom`], this is the variant's `Status`, which
718 /// defaults to [`Status::UnprocessableEntity`]. For all others, it is:
719 ///
720 /// * **`PayloadTooLarge`** if the [error kind](ErrorKind) is:
721 /// - `InvalidLength` with min of `None`
722 /// - `Multipart(FieldSizeExceeded)` or `Multipart(StreamSizeExceeded)`
723 /// * **`InternalServerError`** if the [error kind](ErrorKind) is:
724 /// - `Unknown`
725 /// * **`BadRequest`** if the [error kind](ErrorKind) is:
726 /// - `Io` with an `entity` of `Form`
727 /// * **`UnprocessableEntity`** for all other variants
728 ///
729 /// # Example
730 ///
731 /// ```rust
732 /// # extern crate rocket_community as rocket;
733 /// use rocket::form::error::{Error, ErrorKind, Entity};
734 /// use rocket::http::Status;
735 ///
736 /// let error = Error::validation("bad `foo`");
737 /// assert_eq!(error.status(), Status::UnprocessableEntity);
738 ///
739 /// let error = Error::from((None, Some(10u64)));
740 /// assert_eq!(error.status(), Status::PayloadTooLarge);
741 ///
742 /// let error = Error::from(ErrorKind::Unknown);
743 /// assert_eq!(error.status(), Status::InternalServerError);
744 ///
745 /// // default entity for `io::Error` is `Form`.
746 /// let error = Error::from(std::io::Error::last_os_error());
747 /// assert_eq!(error.status(), Status::BadRequest);
748 ///
749 /// let error = error.with_entity(Entity::Value);
750 /// assert_eq!(error.status(), Status::UnprocessableEntity);
751 /// ```
752 pub fn status(&self) -> Status {
753 use multer::Error::*;
754 use ErrorKind::*;
755
756 match self.kind {
757 InvalidLength { min: None, .. }
758 | Multipart(FieldSizeExceeded { .. })
759 | Multipart(StreamSizeExceeded { .. }) => Status::PayloadTooLarge,
760 Unknown => Status::InternalServerError,
761 Io(_) if self.entity == Entity::Form => Status::BadRequest,
762 Custom(status, _) => status,
763 _ => Status::UnprocessableEntity,
764 }
765 }
766}
767
768impl<'v> Serialize for Error<'v> {
769 fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
770 let mut err = ser.serialize_struct("Error", 3)?;
771 err.serialize_field("name", &self.name)?;
772 err.serialize_field("value", &self.value)?;
773 err.serialize_field("entity", &self.entity.to_string())?;
774 err.serialize_field("msg", &self.to_string())?;
775 err.end()
776 }
777}
778
779impl crate::http::ext::IntoOwned for Error<'_> {
780 type Owned = Error<'static>;
781
782 fn into_owned(self) -> Self::Owned {
783 Error {
784 name: self.name.into_owned(),
785 value: self.value.into_owned(),
786 kind: self.kind.into_owned(),
787 entity: self.entity,
788 }
789 }
790}
791
792impl<'v> std::ops::Deref for Error<'v> {
793 type Target = ErrorKind<'v>;
794
795 fn deref(&self) -> &Self::Target {
796 &self.kind
797 }
798}
799
800impl fmt::Display for Error<'_> {
801 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
802 self.kind.fmt(f)
803 }
804}
805
806impl<'v, T: Into<ErrorKind<'v>>> From<T> for Error<'v> {
807 #[inline(always)]
808 fn from(k: T) -> Self {
809 let kind = k.into();
810 let entity = Entity::default_for(&kind);
811 Error {
812 name: None,
813 value: None,
814 kind,
815 entity,
816 }
817 }
818}
819
820impl<'a> From<multer::Error> for Error<'a> {
821 fn from(error: multer::Error) -> Self {
822 use self::ErrorKind::*;
823 use multer::Error::*;
824
825 let incomplete = Error::from(InvalidLength {
826 min: None,
827 max: None,
828 });
829 match error {
830 UnknownField {
831 field_name: Some(name),
832 } => Error::from(Unexpected).with_name(name),
833 UnknownField { field_name: None } => Error::from(Unexpected),
834 FieldSizeExceeded { limit, field_name } => {
835 let e = Error::from((None, Some(limit)));
836 match field_name {
837 Some(name) => e.with_name(name),
838 None => e,
839 }
840 }
841 StreamSizeExceeded { limit } => {
842 Error::from((None, Some(limit))).with_entity(Entity::Form)
843 }
844 IncompleteFieldData {
845 field_name: Some(name),
846 } => incomplete.with_name(name),
847 IncompleteFieldData { field_name: None } => incomplete,
848 IncompleteStream | IncompleteHeaders => incomplete.with_entity(Entity::Form),
849 e => Error::from(ErrorKind::Multipart(e)),
850 }
851 }
852}
853
854impl fmt::Display for ErrorKind<'_> {
855 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
856 match self {
857 ErrorKind::InvalidLength { min, max } => match (min, max) {
858 (None, None) => write!(f, "invalid length: incomplete")?,
859 (None, Some(k)) if *k < 1024 => write!(f, "length cannot exceed {}", k)?,
860 (None, Some(k)) => write!(f, "size must not exceed {}", ByteUnit::from(*k))?,
861 (Some(1), None) => write!(f, "cannot be empty")?,
862 (Some(k), None) if *k < 1024 => write!(f, "expected at least {}", k)?,
863 (Some(k), None) => write!(f, "size must be at least {}", ByteUnit::from(*k))?,
864 (Some(i), Some(j)) if *i < 1024 && *j < 1024 => {
865 write!(f, "length must be between {} and {}", i, j)?;
866 }
867 (Some(i), Some(j)) => {
868 let (i, j) = (ByteUnit::from(*i), ByteUnit::from(*j));
869 write!(f, "size must be between {} and {}", i, j)?;
870 }
871 },
872 ErrorKind::InvalidChoice { choices } => match *choices.as_ref() {
873 [] => write!(f, "invalid choice")?,
874 [ref choice] => write!(f, "expected {}", choice)?,
875 _ => {
876 write!(f, "expected one of ")?;
877 for (i, choice) in choices.iter().enumerate() {
878 if i != 0 {
879 write!(f, ", ")?;
880 }
881 write!(f, "`{}`", choice)?;
882 }
883 }
884 },
885 ErrorKind::OutOfRange { start, end } => match (start, end) {
886 (None, None) => write!(f, "value is out of range")?,
887 (None, Some(k)) => write!(f, "value cannot exceed {}", k)?,
888 (Some(k), None) => write!(f, "value must be at least {}", k)?,
889 (Some(i), Some(j)) => write!(f, "value must be between {} and {}", i, j)?,
890 },
891 ErrorKind::Validation(msg) => msg.fmt(f)?,
892 ErrorKind::Duplicate => "duplicate".fmt(f)?,
893 ErrorKind::Missing => "missing".fmt(f)?,
894 ErrorKind::Unexpected => "unexpected".fmt(f)?,
895 ErrorKind::Unknown => "unknown internal error".fmt(f)?,
896 ErrorKind::Custom(_, e) => e.fmt(f)?,
897 ErrorKind::Multipart(e) => write!(f, "invalid multipart: {}", e)?,
898 ErrorKind::Utf8(e) => write!(f, "invalid UTF-8: {}", e)?,
899 ErrorKind::Char(e) => write!(f, "invalid character: {}", e)?,
900 ErrorKind::Int(e) => write!(f, "invalid integer: {}", e)?,
901 ErrorKind::Bool(e) => write!(f, "invalid boolean: {}", e)?,
902 ErrorKind::Float(e) => write!(f, "invalid float: {}", e)?,
903 ErrorKind::Addr(e) => write!(f, "invalid address: {}", e)?,
904 ErrorKind::Io(e) => write!(f, "i/o error: {}", e)?,
905 }
906
907 Ok(())
908 }
909}
910
911impl crate::http::ext::IntoOwned for ErrorKind<'_> {
912 type Owned = ErrorKind<'static>;
913
914 fn into_owned(self) -> Self::Owned {
915 use ErrorKind::*;
916
917 match self {
918 InvalidLength { min, max } => InvalidLength { min, max },
919 OutOfRange { start, end } => OutOfRange { start, end },
920 Validation(s) => Validation(s.into_owned().into()),
921 Duplicate => Duplicate,
922 Missing => Missing,
923 Unexpected => Unexpected,
924 Unknown => Unknown,
925 Custom(s, e) => Custom(s, e),
926 Multipart(e) => Multipart(e),
927 Utf8(e) => Utf8(e),
928 Char(e) => Char(e),
929 Int(e) => Int(e),
930 Bool(e) => Bool(e),
931 Float(e) => Float(e),
932 Addr(e) => Addr(e),
933 Io(e) => Io(e),
934 InvalidChoice { choices } => InvalidChoice {
935 choices: choices
936 .iter()
937 .map(|s| Cow::Owned(s.to_string()))
938 .collect::<Vec<_>>()
939 .into(),
940 },
941 }
942 }
943}
944
945impl<'a, 'b> PartialEq<ErrorKind<'b>> for ErrorKind<'a> {
946 fn eq(&self, other: &ErrorKind<'b>) -> bool {
947 use ErrorKind::*;
948 match (self, other) {
949 (InvalidLength { min: a, max: b }, InvalidLength { min, max }) => min == a && max == b,
950 (InvalidChoice { choices: a }, InvalidChoice { choices }) => choices == a,
951 (OutOfRange { start: a, end: b }, OutOfRange { start, end }) => start == a && end == b,
952 (Validation(a), Validation(b)) => a == b,
953 (Duplicate, Duplicate) => true,
954 (Missing, Missing) => true,
955 (Unexpected, Unexpected) => true,
956 (Custom(a, _), Custom(b, _)) => a == b,
957 (Multipart(a), Multipart(b)) => a == b,
958 (Utf8(a), Utf8(b)) => a == b,
959 (Int(a), Int(b)) => a == b,
960 (Bool(a), Bool(b)) => a == b,
961 (Float(a), Float(b)) => a == b,
962 (Addr(a), Addr(b)) => a == b,
963 (Io(a), Io(b)) => a.kind() == b.kind(),
964 _ => false,
965 }
966 }
967}
968
969impl From<(Option<u64>, Option<u64>)> for ErrorKind<'_> {
970 fn from((min, max): (Option<u64>, Option<u64>)) -> Self {
971 ErrorKind::InvalidLength { min, max }
972 }
973}
974
975impl<'a, 'v: 'a> From<&'static [Cow<'v, str>]> for ErrorKind<'a> {
976 fn from(choices: &'static [Cow<'v, str>]) -> Self {
977 ErrorKind::InvalidChoice {
978 choices: choices.into(),
979 }
980 }
981}
982
983impl<'a, 'v: 'a> From<Vec<Cow<'v, str>>> for ErrorKind<'a> {
984 fn from(choices: Vec<Cow<'v, str>>) -> Self {
985 ErrorKind::InvalidChoice {
986 choices: choices.into(),
987 }
988 }
989}
990
991impl From<(Option<isize>, Option<isize>)> for ErrorKind<'_> {
992 fn from((start, end): (Option<isize>, Option<isize>)) -> Self {
993 ErrorKind::OutOfRange { start, end }
994 }
995}
996
997impl From<(Option<ByteUnit>, Option<ByteUnit>)> for ErrorKind<'_> {
998 fn from((start, end): (Option<ByteUnit>, Option<ByteUnit>)) -> Self {
999 ErrorKind::from((start.map(ByteUnit::as_u64), end.map(ByteUnit::as_u64)))
1000 }
1001}
1002
1003impl<'a, 'v: 'a, const N: usize> From<&'static [Cow<'v, str>; N]> for ErrorKind<'a> {
1004 fn from(choices: &'static [Cow<'v, str>; N]) -> Self {
1005 let choices = &choices[..];
1006 ErrorKind::InvalidChoice {
1007 choices: choices.into(),
1008 }
1009 }
1010}
1011
1012impl<'a> From<Box<dyn std::error::Error + Send>> for ErrorKind<'a> {
1013 fn from(e: Box<dyn std::error::Error + Send>) -> Self {
1014 ErrorKind::Custom(Status::UnprocessableEntity, e)
1015 }
1016}
1017
1018impl<'a> From<(Status, Box<dyn std::error::Error + Send>)> for ErrorKind<'a> {
1019 fn from((status, e): (Status, Box<dyn std::error::Error + Send>)) -> Self {
1020 ErrorKind::Custom(status, e)
1021 }
1022}
1023
1024macro_rules! impl_from_for {
1025 (<$l:lifetime> $T:ty => $V:ty as $variant:ident) => {
1026 impl<$l> From<$T> for $V {
1027 fn from(value: $T) -> Self {
1028 <$V>::$variant(value)
1029 }
1030 }
1031 };
1032}
1033
1034impl_from_for!(<'a> Utf8Error => ErrorKind<'a> as Utf8);
1035impl_from_for!(<'a> ParseIntError => ErrorKind<'a> as Int);
1036impl_from_for!(<'a> ParseCharError => ErrorKind<'a> as Char);
1037impl_from_for!(<'a> ParseFloatError => ErrorKind<'a> as Float);
1038impl_from_for!(<'a> ParseBoolError => ErrorKind<'a> as Bool);
1039impl_from_for!(<'a> AddrParseError => ErrorKind<'a> as Addr);
1040impl_from_for!(<'a> io::Error => ErrorKind<'a> as Io);
1041
1042impl fmt::Display for Entity {
1043 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1044 let string = match self {
1045 Entity::Form => "form",
1046 Entity::Field => "field",
1047 Entity::ValueField => "value field",
1048 Entity::DataField => "data field",
1049 Entity::Name => "name",
1050 Entity::Value => "value",
1051 Entity::Key => "key",
1052 Entity::Index(k) => return write!(f, "index {}", k),
1053 };
1054
1055 string.fmt(f)
1056 }
1057}
1058
1059impl Entity {
1060 /// The default entity for an [`Error`] created for `ErrorKind`.
1061 ///
1062 /// * **[`Field`]** if `Duplicate`, `Missing`, `Unexpected`, or `Unknown`
1063 /// * **[`Form`]** if `Multipart` or `Io`
1064 /// * **[`Value`]** otherwise
1065 ///
1066 /// [`Field`]: Entity::Field
1067 /// [`Form`]: Entity::Form
1068 /// [`Value`]: Entity::Value
1069 pub const fn default_for(kind: &ErrorKind<'_>) -> Self {
1070 match kind {
1071 ErrorKind::InvalidLength { .. }
1072 | ErrorKind::InvalidChoice { .. }
1073 | ErrorKind::OutOfRange { .. }
1074 | ErrorKind::Validation { .. }
1075 | ErrorKind::Utf8(_)
1076 | ErrorKind::Char(_)
1077 | ErrorKind::Int(_)
1078 | ErrorKind::Float(_)
1079 | ErrorKind::Bool(_)
1080 | ErrorKind::Custom(..)
1081 | ErrorKind::Addr(_) => Entity::Value,
1082
1083 ErrorKind::Duplicate
1084 | ErrorKind::Missing
1085 | ErrorKind::Unknown
1086 | ErrorKind::Unexpected => Entity::Field,
1087
1088 ErrorKind::Multipart(_) | ErrorKind::Io(_) => Entity::Form,
1089 }
1090 }
1091}