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}