structural/field/errors.rs
1/*!
2Field-accessor-related error types and traits
3*/
4
5use std_::fmt::{self, Display};
6
7use core_extensions::collection_traits::Cloned;
8
9mod sealed {
10 pub trait Sealed {}
11}
12use self::sealed::Sealed;
13
14/// Marker trait for the errors that can be returned from the `RevGetField` trait and subtraits.
15///
16/// The errors can be:
17///
18/// - [InfallibleAccess](./enum.InfallibleAccess.html):
19/// For `Rev*` accessors that return a field that always exists,
20/// most often in a struct.
21/// Because the field always exists this error is never actually returned.
22///
23/// - [FailedAccess](./struct.FailedAccess.html):
24/// For `Rev*` accessors that failed to return a field that may not exist,
25/// most often inside an enum.
26///
27/// This trait is sealed,and cannot be implemented outside of the `structural` crate.
28pub trait IsFieldErr: Sealed + 'static + Copy + Cloned {}
29
30/// The error type for accesses to fields that always exist,most often in a struct.
31///
32/// Because the fields always exist,this error is never actually returned,
33/// and `Result<T, InfallibleAccess>` has the same size as `T` (as of Rust 1.42).
34///
35/// This is used as the `Err` associated type for `Rev*Field*` implementors,
36/// which return a `Result<_,InfallibleAccess>`,
37/// then [StructuralExt](../../trait.StructuralExt.html) methods use
38/// [NormalizeFields](../trait.NormalizeFields.html) to turn
39/// `Ok(foo)` into `foo` (which can be safely done,since this type can't be constructed).
40#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
41pub enum InfallibleAccess {}
42
43/// The error type for accesses to fields that may not exist,most often inside an enum.
44///
45/// This is used as the `Err` associated type for `Rev*Field*` implementors,
46/// which return a `Result<_,FailedAccess>`,
47/// then [StructuralExt](../../trait.StructuralExt.html) methods use
48/// [NormalizeFields](../trait.NormalizeFields.html) to turn
49/// `Ok(foo)` into `Some(foo)`,and `Err(FailedAccess)` into `None`.
50#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
51pub struct FailedAccess;
52
53impl Cloned for FailedAccess {
54 type Cloned = Self;
55
56 #[inline(always)]
57 fn cloned_(&self) -> Self {
58 *self
59 }
60}
61
62impl Cloned for InfallibleAccess {
63 type Cloned = Self;
64
65 #[inline(always)]
66 fn cloned_(&self) -> Self {
67 *self
68 }
69}
70
71impl Sealed for FailedAccess {}
72impl IsFieldErr for FailedAccess {}
73
74impl Sealed for InfallibleAccess {}
75impl IsFieldErr for InfallibleAccess {}
76
77#[cfg(feature = "std")]
78mod std_impls {
79 use super::{FailedAccess, InfallibleAccess};
80
81 use std::error::Error;
82
83 impl Error for FailedAccess {
84 #[inline(always)]
85 fn description(&self) -> &str {
86 "Some field could not be accessed"
87 }
88 }
89 impl Error for InfallibleAccess {
90 #[inline(always)]
91 fn description(&self) -> &str {
92 "The field isn't optional,this function is uncallable"
93 }
94 }
95}
96
97////////////////////////////////////////////////////////////////////////////////
98
99impl Display for FailedAccess {
100 #[inline(always)]
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 f.write_str("Some field could not be accessed")
103 }
104}
105
106impl From<InfallibleAccess> for FailedAccess {
107 #[inline(always)]
108 fn from(_: InfallibleAccess) -> Self {
109 FailedAccess
110 }
111}
112
113////////////////////////////////////////////////////////////////////////////////
114
115impl Display for InfallibleAccess {
116 #[inline(always)]
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.write_str("This field can always be accessed.")
119 }
120}
121
122////////////////////////////////////////////////////////////////////////////////
123
124/// A specialized conversion trait,to convert field accessor error types to other
125/// field accessor error types.
126pub trait IntoFieldErr<T>: IsFieldErr {
127 /// Performs the conversion
128 fn into_field_err(self) -> T
129 where
130 T: IsFieldErr;
131}
132
133impl<T> IntoFieldErr<T> for T
134where
135 T: IsFieldErr,
136{
137 #[inline(always)]
138 fn into_field_err(self) -> T {
139 self
140 }
141}
142
143impl IntoFieldErr<FailedAccess> for InfallibleAccess {
144 #[inline(always)]
145 fn into_field_err(self) -> FailedAccess {
146 match self {}
147 }
148}
149
150////////////////////////////////////////////////////////////////////////////////
151
152/// Combines multiple error types into one.
153///
154/// A tuple of errors is combined into a `InfallibleAccess` so long as all of them are,
155/// otherwise they're combined into an `FailedAccess` .
156///
157/// This is used by the `Rev*Field*` impls for [NestedFieldPath](../../struct.NestedFieldPath.html) to
158/// determine whether a nested field access is optional or not.
159pub trait CombinedErrs {
160 /// The error type after combining all errors.
161 ///
162 /// In the impls from the structural crate,
163 /// if all errors are `InfallibleAccess`,then `Combined` is `InfallibleAccess`,
164 /// otherwise `Combined` is `FailedAccess`.
165 type Combined: IsFieldErr;
166}
167
168/// The combination of all the error types in `This`.
169///
170/// A tuple of errors is combined into a `InfallibleAccess` so long as all of them are,
171/// otherwise they're combined into an `FailedAccess` .
172pub type CombinedErrsOut<This> = <This as CombinedErrs>::Combined;
173
174mod impl_combine_errs {
175 use super::{
176 CombinedErrs, CombinedErrsOut, FailedAccess as OF, InfallibleAccess as IF, IsFieldErr,
177 };
178
179 macro_rules! combined_err_impls {
180 (small=>
181 $( $ty:ty = $output:ty ,)*
182 ) => {
183 $(
184 impl CombinedErrs for $ty {
185 type Combined=$output;
186 }
187 )*
188 };
189 (large=>
190 $((
191 $( ($t0:ident,$t1:ident,$t2:ident,$t3:ident,), )*
192 $($trailing:ident,)*
193 ))*
194 )=>{
195 $(
196 #[allow(non_camel_case_types)]
197 impl< $($t0,$t1,$t2,$t3,)* $($trailing,)* CombTuples,CombTrail >
198 CombinedErrs
199 for ($($t0,$t1,$t2,$t3,)* $($trailing,)*)
200 where
201 $( ($t0,$t1,$t2,$t3): CombinedErrs, )*
202 (
203 $( CombinedErrsOut<($t0,$t1,$t2,$t3)>, )*
204 ):CombinedErrs<Combined=CombTuples>,
205 CombTuples:IsFieldErr,
206 ($($trailing,)*):CombinedErrs<Combined=CombTrail>,
207 CombTrail:IsFieldErr,
208 (CombTuples,CombTrail):CombinedErrs,
209 {
210 type Combined=CombinedErrsOut<(CombTuples,CombTrail)>;
211 }
212 )*
213 };
214 }
215
216 /*
217 fn main() {
218 fn as_ty(b:bool)->&'static str{
219 if b {"OF"}else{"IF"}
220 }
221
222 for elem_count in 0..=4 {
223 for bits in 0..1<<elem_count {
224 let is_optional=(0..elem_count)
225 .map(|i| (bits>>i)&1!=0 )
226 .collect::<Vec<bool>>();
227
228 let tup=is_optional.iter().copied().map(as_ty).collect::<Vec<_>>();
229 let any_optional=is_optional.iter().cloned().any(|x|x);
230
231 println!(
232 "({tup})={output},",
233 tup=tup.join(","),
234 output=as_ty(any_optional),
235 )
236 }
237 }
238 }
239 */
240
241 combined_err_impls! {
242 small=>
243 ()=IF,
244 (IF,)=IF,
245 (OF,)=OF,
246 (IF,IF)=IF,
247 (OF,IF)=OF,
248 (IF,OF)=OF,
249 (OF,OF)=OF,
250 (IF,IF,IF)=IF,
251 (OF,IF,IF)=OF,
252 (IF,OF,IF)=OF,
253 (OF,OF,IF)=OF,
254 (IF,IF,OF)=OF,
255 (OF,IF,OF)=OF,
256 (IF,OF,OF)=OF,
257 (OF,OF,OF)=OF,
258 (IF,IF,IF,IF)=IF,
259 (OF,IF,IF,IF)=OF,
260 (IF,OF,IF,IF)=OF,
261 (OF,OF,IF,IF)=OF,
262 (IF,IF,OF,IF)=OF,
263 (OF,IF,OF,IF)=OF,
264 (IF,OF,OF,IF)=OF,
265 (OF,OF,OF,IF)=OF,
266 (IF,IF,IF,OF)=OF,
267 (OF,IF,IF,OF)=OF,
268 (IF,OF,IF,OF)=OF,
269 (OF,OF,IF,OF)=OF,
270 (IF,IF,OF,OF)=OF,
271 (OF,IF,OF,OF)=OF,
272 (IF,OF,OF,OF)=OF,
273 (OF,OF,OF,OF)=OF,
274 }
275
276 /*
277 fn main() {
278 fn as_ty(b:bool)->&'static str{
279 if b {"OF"}else{"IF"}
280 }
281 let tup_size=4;
282
283 for elem_count in 5..=12 {
284 print!("(");
285 for which_tup in 0..elem_count/tup_size {
286 let start=which_tup*tup_size;
287 print!("(");
288 for e in start..start+tup_size{
289 print!("e{},",e);
290 }
291 print!("),");
292 }
293 for e in elem_count/tup_size*tup_size..elem_count{
294 print!("e{},",e);
295 }
296 println!(")");
297 }
298 }
299
300 */
301
302 combined_err_impls! {
303 large=>
304 ((e0,e1,e2,e3,),e4,)
305 ((e0,e1,e2,e3,),e4,e5,)
306 ((e0,e1,e2,e3,),e4,e5,e6,)
307 ((e0,e1,e2,e3,),(e4,e5,e6,e7,),)
308 ((e0,e1,e2,e3,),(e4,e5,e6,e7,),e8,)
309 ((e0,e1,e2,e3,),(e4,e5,e6,e7,),e8,e9,)
310 ((e0,e1,e2,e3,),(e4,e5,e6,e7,),e8,e9,e10,)
311 ((e0,e1,e2,e3,),(e4,e5,e6,e7,),(e8,e9,e10,e11,),)
312 }
313}