base_message/
field_error.rs1use crate::FieldValueError;
5use std::fmt;
6
7#[derive(Clone, Debug, PartialEq, Eq, Hash)]
11pub struct FieldError {
12 name: Option<&'static str>,
13 position: Option<usize>,
14 kind: FieldErrorKind,
15}
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
19#[non_exhaustive]
20pub enum FieldErrorKind {
21 Duplicate {
23 first: usize,
25 },
26 Missing,
28 Invalid(FieldValueError),
30 Forbidden,
32 Unknown,
34}
35
36impl FieldError {
37 pub fn name(&self) -> Option<&'static str> {
39 self.name
40 }
41
42 pub fn position(&self) -> Option<usize> {
44 self.position
45 }
46
47 pub fn kind(&self) -> FieldErrorKind {
49 self.kind
50 }
51
52 pub(crate) fn duplicate(name: &'static str, position: usize, first: usize) -> Self {
53 Self {
54 name: Some(name),
55 position: Some(position),
56 kind: FieldErrorKind::Duplicate { first },
57 }
58 }
59
60 pub(crate) fn invalid(name: &'static str, position: usize, error: FieldValueError) -> Self {
61 Self {
62 name: Some(name),
63 position: Some(position),
64 kind: FieldErrorKind::Invalid(error),
65 }
66 }
67
68 pub(crate) fn unknown(position: usize) -> Self {
69 Self {
70 name: None,
71 position: Some(position),
72 kind: FieldErrorKind::Unknown,
73 }
74 }
75
76 pub(crate) fn missing(name: &'static str) -> Self {
77 Self {
78 name: Some(name),
79 position: None,
80 kind: FieldErrorKind::Missing,
81 }
82 }
83
84 pub(crate) fn forbidden(name: &'static str, position: usize) -> Self {
85 Self {
86 name: Some(name),
87 position: Some(position),
88 kind: FieldErrorKind::Forbidden,
89 }
90 }
91}
92
93impl fmt::Display for FieldError {
94 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
95 let name = self.name.unwrap_or("unknown");
96 let position = self.position.unwrap_or_default();
97 match self.kind {
98 FieldErrorKind::Duplicate { first } => write!(
99 formatter,
100 "duplicate {name} field at position {position}, first at {first}"
101 ),
102 FieldErrorKind::Missing => write!(formatter, "missing required {name} field"),
103 FieldErrorKind::Invalid(error) => write!(
104 formatter,
105 "invalid {name} field at position {position}: {error}"
106 ),
107 FieldErrorKind::Forbidden => {
108 write!(formatter, "forbidden {name} field at position {position}")
109 }
110 FieldErrorKind::Unknown => write!(formatter, "unexpected field at position {position}"),
111 }
112 }
113}
114
115impl std::error::Error for FieldError {
116 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
117 match &self.kind {
118 FieldErrorKind::Invalid(error) => Some(error),
119 _ => None,
120 }
121 }
122}