1use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
8#[non_exhaustive]
9pub enum FieldRuleFault {
10 UnorderedBound(String),
14 InvalidPattern(String),
18 EmptyRange,
22 RefusedDefault(String),
26 UnparsedDefault(String),
31 NotText(&'static str),
34 NotCheckbox,
36 SingleValue,
38 FewerOptions(usize),
40 TagsOverRecords,
44 AboveRowCap(usize),
47 RefusedBlank,
50 UnplacedComparedField(String),
54 IncomparableField(String),
58 UnorderedComparison(String),
62 SelfComparison,
67 NoExtension,
71 InvalidExtension(String),
76 SingleFile,
80 AboveFormCap {
86 max: usize,
88 cap: usize,
90 },
91}
92
93pub(super) fn fmt_field_rule(
95 f: &mut fmt::Formatter<'_>,
96 field: &str,
97 fault: &FieldRuleFault,
98) -> fmt::Result {
99 match fault {
100 FieldRuleFault::UnorderedBound(bound) => write!(
101 f,
102 "field '{field}' is bounded by '{bound}', which is no value of a type that orders: \
103 bound a number, date, time or timestamp field by a value of its type"
104 ),
105 FieldRuleFault::InvalidPattern(error) => write!(
106 f,
107 "field '{field}' has a pattern that does not compile: {error}"
108 ),
109 FieldRuleFault::EmptyRange => write!(
110 f,
111 "field '{field}' declares a minimum above its maximum, so it refuses every value"
112 ),
113 FieldRuleFault::RefusedDefault(value) => write!(
114 f,
115 "field '{field}' defaults to '{value}', which its own rules refuse: change the default \
116 or the rule"
117 ),
118 FieldRuleFault::UnparsedDefault(value) => write!(
119 f,
120 "field '{field}' defaults to '{value}', which is no value of its type: spell the \
121 default as the type does, or pass a value of the type"
122 ),
123 FieldRuleFault::NotText(input) => write!(
124 f,
125 "field '{field}' is a rich text editor over a field its form edits as '{input}' \
126 input, but rich text stores HTML: make the field a `String` or `Option<String>`"
127 ),
128 FieldRuleFault::NotCheckbox => write!(
129 f,
130 "field '{field}' is `accepted` but is not the built-in checkbox or switch: declare \
131 it with `Field::toggle` or `Field::toggle_input`"
132 ),
133 FieldRuleFault::SingleValue => write!(
134 f,
135 "field '{field}' bounds how many options it takes, but takes one: make it `multiple` \
136 or drop `min_items` and `max_items`"
137 ),
138 FieldRuleFault::FewerOptions(options) => write!(
139 f,
140 "field '{field}' needs more options chosen than the {options} it offers, so it \
141 refuses every value"
142 ),
143 FieldRuleFault::TagsOverRecords => write!(
144 f,
145 "field '{field}' takes tags over a relationship's records, whose values a user \
146 cannot type: drop `tags`, or offer static options as its suggestions"
147 ),
148 FieldRuleFault::AboveRowCap(max) => write!(
149 f,
150 "field '{field}' takes up to {max} rows, more than any repeater takes \
151 (`MAX_REPEATER_ROWS`): lower `max_items`"
152 ),
153 FieldRuleFault::RefusedBlank => write!(
154 f,
155 "field '{field}' is disabled and has no default, but its own rules refuse its blank \
156 answer, so every create is refused: give it a default or drop the rule"
157 ),
158 FieldRuleFault::UnplacedComparedField(other) => write!(
159 f,
160 "field '{field}' compares with field '{other}', which the schema does not place: \
161 place it in the same schema, or in the same repeater row"
162 ),
163 FieldRuleFault::IncomparableField(other) => write!(
164 f,
165 "field '{field}' compares with field '{other}', which is not a text field of the same \
166 type: compare two fields of one type"
167 ),
168 FieldRuleFault::UnorderedComparison(other) => write!(
169 f,
170 "field '{field}' orders against field '{other}', but its type has no order: compare \
171 a number, date, time or timestamp field, or use `different`"
172 ),
173 FieldRuleFault::SelfComparison => write!(
174 f,
175 "field '{field}' compares with itself: compare it with another field"
176 ),
177 FieldRuleFault::NoExtension => write!(
178 f,
179 "field '{field}' lists no extension it takes, so it refuses every file: list one, or \
180 drop `extensions`"
181 ),
182 FieldRuleFault::InvalidExtension(extension) => write!(
183 f,
184 "field '{field}' takes the extension '{extension}', but a file's extension is the \
185 last one alone, in letters and digits: list that one"
186 ),
187 FieldRuleFault::SingleFile => write!(
188 f,
189 "field '{field}' bounds how many files it takes, but stores one path: bind a \
190 `Vec<String>` with `Field::files`, or drop `max_files`"
191 ),
192 FieldRuleFault::AboveFormCap { max, cap } => write!(
193 f,
194 "field '{field}' takes files up to {max} bytes, but the panel's form body holds at \
195 most {cap} bytes: lower `max_bytes` below it, or raise `Limits::body_bytes`"
196 ),
197 }
198}