structural/
structural_ext.rs

1use crate::{
2    convert::{IntoStructural, TryFromError, TryIntoStructural},
3    enums::IsVariant,
4    field::{
5        NormalizeFields, NormalizeFieldsOut, RevGetFieldImpl, RevGetFieldMutImpl, RevGetMultiField,
6        RevGetMultiFieldMut, RevGetMultiFieldMutOut, RevGetMultiFieldOut, RevIntoFieldImpl,
7        RevIntoMultiField, RevIntoMultiFieldOut,
8    },
9    path::IsTStr,
10};
11
12use core_extensions::collection_traits::{Cloned, ClonedOut};
13
14/// A trait defining the primary way to call methods from structural traits.
15///
16/// For a wrapper type that defines inherent methods equivalent to the ones in this trait,
17/// you can use the [`StrucWrapper`] wrapper type.
18///
19/// [`StrucWrapper`]: ./struct.StrucWrapper.html
20pub trait StructuralExt {
21    /// Gets a reference to a field,determined by `path`.
22    ///
23    /// This is named `field_` instead of `field`
24    /// because `field` collides with the `DebugTuple`/`DebugStruct` method
25    ///
26    /// # Example
27    ///
28    /// ```
29    /// use structural::{StructuralExt,fp,structural_alias};
30    ///
31    /// structural_alias!{
32    ///     trait EvenFields<A,B,C>{
33    ///         0:A,
34    ///         2:B,
35    ///         4:C,
36    ///     }
37    /// }
38    ///
39    /// fn with_even<T>(this:&T)
40    /// where
41    ///     T:EvenFields<u32,u32,u32>
42    /// {
43    ///     assert_eq!( this.field_(fp!(0)), &1 );
44    ///     assert_eq!( this.field_(fp!(2)), &2 );
45    ///     assert_eq!( this.field_(fp!(4)), &5 );
46    /// }
47    ///
48    /// fn main(){
49    ///     with_even( &(1,0,2,0,5) );
50    ///     with_even( &(1,0,2,0,5,0) );
51    ///     with_even( &(1,0,2,0,5,0,0) );
52    ///     with_even( &(1,0,2,0,5,0,0,0) );
53    /// }
54    ///
55    /// ```
56    ///
57    /// # Enum Example
58    ///
59    /// ```
60    /// use structural::{StructuralExt,Structural,fp};
61    ///
62    /// with_circle( &Shape::Circle{ x:3, y:5, radius:8 } );
63    /// with_circle( &MoreShapes::Circle{ x:3, y:5, radius:8 } );
64    ///
65    /// fn with_circle<T>(circle:&T)
66    /// where
67    ///     // `Shape_SI` was generated for Shape by the `Structural` derive.
68    ///     T: Shape_SI
69    /// {
70    ///     assert_eq!( circle.field_(fp!(::Circle.x)), Some(&3) );
71    ///     assert_eq!( circle.field_(fp!(::Circle.y)), Some(&5) );
72    ///     assert_eq!( circle.field_(fp!(::Circle.radius)), Some(&8) );
73    ///
74    ///     // Constructing the variant proxy is the only Option we have to handle here,
75    ///     // instead of every access to the fields in the Circle variant being optional.
76    ///     //
77    ///     // For a more ergonomic alternative,
78    ///     // you can look at the example for the `fields` method
79    ///     let proxy=circle.field_(fp!(::Circle)).expect("Expected a circle");
80    ///     assert_eq!( proxy.field_(fp!(x)), &3 );
81    ///     assert_eq!( proxy.field_(fp!(y)), &5 );
82    ///     assert_eq!( proxy.field_(fp!(radius)), &8 );
83    /// }
84    ///
85    /// #[derive(Structural)]
86    /// enum Shape{
87    ///     Circle{x:u32,y:u32,radius:u32},
88    ///     Square{x:u32,y:u32,width:u32},
89    /// }
90    ///
91    /// #[derive(Structural)]
92    /// # #[struc(no_trait)]
93    /// enum MoreShapes{
94    ///     Circle{x:u32,y:u32,radius:u32},
95    ///     Square{x:u32,y:u32,width:u32},
96    ///     Rectangle{x:u32,y:u32,width:u32,height:u32},
97    /// }
98    ///
99    ///
100    /// ```
101    #[inline(always)]
102    fn field_<'a, P>(&'a self, path: P) -> NormalizeFieldsOut<Result<&'a P::Ty, P::Err>>
103    where
104        P: RevGetFieldImpl<'a, Self>,
105        Result<&'a P::Ty, P::Err>: NormalizeFields,
106    {
107        path.rev_get_field(self).normalize_fields()
108    }
109
110    /// Gets references to multiple fields,determined by `path`.
111    ///
112    /// # Access many fields
113    ///
114    /// If you pass a `path` that references over 8 fields,this will return a
115    /// tuple of tuples(each nested tuple with 8 elements) instead of
116    /// a singly nested tuple.
117    ///
118    /// For examples accessing over 8 field look at the docs for the [`field_pat`] macro
119    ///
120    /// [`field_pat`]: ./macro.field_pat.html#the-structuralext-example
121    ///
122    /// # Example
123    ///
124    /// ```
125    /// use structural::{StructuralExt,fp,structural_alias};
126    ///
127    /// structural_alias!{
128    ///     trait OddFields<A,B,C>{
129    ///         1:A,
130    ///         3:B,
131    ///         5:C,
132    ///     }
133    /// }
134    ///
135    /// fn with_even(this:&impl OddFields<u32,u32,u32>){
136    ///     assert_eq!( this.fields(fp!(1,3,5)), (&22,&44,&77) );
137    /// }
138    ///
139    /// fn main(){
140    ///     with_even( &(0,22,0,44,0,77) );
141    ///     with_even( &(0,22,0,44,0,77,0) );
142    ///     with_even( &(0,22,0,44,0,77,0,0) );
143    ///     with_even( &(0,22,0,44,0,77,0,0,0) );
144    /// }
145    ///
146    /// ```
147    ///
148    /// # Enum Example
149    ///
150    /// ```
151    /// use structural::{StructuralExt,Structural,fp};
152    ///
153    /// with_car( &Vehicle::Car{ name:"initial-c", km:9001 } );
154    /// with_car( &MoreVehicles::Car{ name:"initial-c", km:9001 } );
155    ///
156    /// fn with_car<T>(car:&T)
157    /// where
158    ///     // `Vehicle_SI` was generated for Vehicle by the `Structural` derive.
159    ///     T: Vehicle_SI
160    /// {
161    ///     assert_eq!(
162    ///         car.fields(fp!(::Car.name, ::Car.km)),
163    ///         ( Some(&"initial-c"), Some(&9001) )
164    ///     );
165    ///
166    ///     // You can use `=>` to access multiple fields inside of a nested field(or a variant)
167    ///     // this allows accessing multiple fields inside an enum variant without having to
168    ///     // create an intermediate variant proxy
169    ///     // (look at the next assert for what that looks like).
170    ///     assert_eq!( car.fields(fp!(::Car=>name,km)), Some((&"initial-c",&9001)) );
171    ///
172    ///     assert_eq!(
173    ///         // This is equivalent to the field access in the previous assert
174    ///         car.field_(fp!(::Car)).map(|vp| vp.fields(fp!(name,km)) ),
175    ///         Some((&"initial-c",&9001))
176    ///     );
177    ///
178    ///     assert_eq!( car.cloned_fields(fp!(::Truck=>weight_kg,driven_km)), None);
179    /// }
180    ///
181    /// #[derive(Structural)]
182    /// enum Vehicle{
183    ///     Car{name: &'static str, km:u32},
184    ///     Truck{ weight_kg:u32, driven_km:u32 },
185    /// }
186    ///
187    /// #[derive(Structural)]
188    /// # #[struc(no_trait)]
189    /// enum MoreVehicles{
190    ///     Car{name: &'static str, km:u32},
191    ///     Truck{ weight_kg:u32, driven_km:u32 },
192    ///     Boat,
193    /// }
194    ///
195    ///
196    /// ```
197    #[inline(always)]
198    fn fields<'a, P>(&'a self, path: P) -> RevGetMultiFieldOut<'a, P, Self>
199    where
200        P: RevGetMultiField<'a, Self>,
201    {
202        path.rev_get_multi_field(self)
203    }
204
205    /// Gets clones of multiple fields,determined by `path`.
206    ///
207    /// # Access many fields
208    ///
209    /// If you pass a `path` that references over 8 fields,this will return a
210    /// tuple of tuples(each nested tuple with 8 elements) instead of
211    /// a singly nested tuple.
212    ///
213    /// For examples accessing over 8 field look at the docs for the [`field_pat`] macro
214    ///
215    /// [`field_pat`]: ./macro.field_pat.html#the-structuralext-example
216    ///
217    /// # Example
218    ///
219    /// This example also uses the reexported `IntoArray` trait,
220    /// which allows converting homogeneous tuples to arrays,
221    /// in this case it's used to iterate over the fields.
222    ///
223    /// ```
224    /// use structural::{StructuralExt,Structural,fp,make_struct};
225    /// use structural::reexports::IntoArray;
226    ///
227    /// // The `Fruits_SI` trait was declared by the `Structural` derive on `Fruits`.
228    /// fn total_fruit_count(fruits:&dyn Fruits_SI)->u32{
229    ///     fruits
230    ///         .cloned_fields(fp!( apples, oranges, tangerines, tomatoes ))
231    ///         .into_array()
232    ///         .iter()
233    ///         .sum()
234    /// }
235    ///
236    /// {
237    ///     let fruits=Fruits{
238    ///         apples:1,
239    ///         oranges:2,
240    ///         tangerines:3,
241    ///         tomatoes:5,
242    ///     };
243    ///     
244    ///     assert_eq!( total_fruit_count(&fruits), 11 );
245    /// }
246    ///
247    /// {
248    ///     let fruits=make_struct!{
249    ///         apples:8,
250    ///         oranges:13,
251    ///         tangerines:21,
252    ///         tomatoes:34,
253    ///     };
254    ///     
255    ///     assert_eq!( total_fruit_count(&fruits), 76 );
256    /// }
257    ///
258    /// #[derive(Structural)]
259    /// // We only get read access to the fields.
260    /// #[struc(public,access="ref")]
261    /// struct Fruits{
262    ///     apples:u32,
263    ///     oranges:u32,
264    ///     tangerines:u32,
265    ///     tomatoes:u32,
266    /// }
267    ///
268    /// ```
269    ///
270    /// # Enum Example
271    ///
272    /// ```
273    /// use structural::{StructuralExt,Structural,fp};
274    ///
275    /// with_pc( &Device::Pc{ manufacturer:"dawn", year:2038 } );
276    /// with_pc( &MoreDevices::Pc{ manufacturer:"dawn", year:2038 } );
277    ///
278    /// fn with_pc<T>(pc:&T)
279    /// where
280    ///     // `Device_SI` was generated for Device by the `Structural` derive.
281    ///     T: Device_SI
282    /// {
283    ///     assert_eq!(
284    ///         pc.cloned_fields(fp!(::Pc.manufacturer, ::Pc.year)),
285    ///         ( Some("dawn"), Some(2038) )
286    ///     );
287    ///
288    ///     // You can use `=>` to access multiple fields inside of a nested field(or a variant)
289    ///     // this allows accessing multiple fields inside an enum variant without having to
290    ///     // create an intermediate variant proxy
291    ///     // (look at the next assert for what that looks like).
292    ///     assert_eq!( pc.cloned_fields(fp!(::Pc=>manufacturer,year)), Some(("dawn",2038)) );
293    ///
294    ///     assert_eq!(
295    ///         // This is equivalent to the field access in the previous assert
296    ///         pc.field_(fp!(::Pc)).map(|vp| vp.cloned_fields(fp!(manufacturer,year)) ),
297    ///         Some(("dawn",2038))
298    ///     );
299    ///
300    ///     assert_eq!( pc.cloned_fields(fp!(::Phone=>number,charge)), None);
301    /// }
302    ///
303    /// #[derive(Structural)]
304    /// enum Device{
305    ///     Pc{manufacturer: &'static str, year:u32},
306    ///     Phone{number:&'static str,charge:u8},
307    /// }
308    ///
309    /// #[derive(Structural)]
310    /// # #[struc(no_trait)]
311    /// enum MoreDevices{
312    ///     Pc{manufacturer: &'static str, year:u32},
313    ///     Phone{number:&'static str,charge:u8},
314    ///     Tablet,
315    /// }
316    ///
317    ///
318    /// ```
319    fn cloned_fields<'a, P>(&'a self, path: P) -> ClonedOut<RevGetMultiFieldOut<'a, P, Self>>
320    where
321        P: RevGetMultiField<'a, Self>,
322        RevGetMultiFieldOut<'a, P, Self>: Cloned,
323    {
324        path.rev_get_multi_field(self).cloned_()
325    }
326
327    /// Gets a mutable reference to a field,determined by `path`.
328    ///
329    /// # Example
330    ///
331    /// ```
332    /// use structural::{StructuralExt,fp,make_struct,Structural};
333    ///
334    /// #[derive(Structural)]
335    /// struct Human{
336    ///     pub x:i32,
337    ///     pub y:i32,
338    ///     pub health:u32,
339    ///     flags:u32,
340    /// }
341    ///
342    /// // The `Human_SI` trait was declared by the `Structural` derive on `Human`.
343    /// fn move_human( this:&mut dyn Human_SI, dx:i32, dy:i32 ){
344    ///     *this.field_mut(fp!(x))+=dx;
345    ///     *this.field_mut(fp!(y))+=dy;
346    /// }
347    ///
348    /// {
349    ///     let mut entity=make_struct!{
350    ///         x: 0,
351    ///         y: 0,
352    ///         health: 100,
353    ///     };
354    ///     move_human(&mut entity,-100,300);
355    ///     assert_eq!( entity.fields(fp!(x,y,health)), (&-100,&300,&100) )
356    /// }
357    /// {
358    ///     let mut entity=Human{
359    ///         x: -1000,
360    ///         y: 1000,
361    ///         health: 1,
362    ///         flags: 0b11111,
363    ///     };
364    ///     
365    ///     move_human(&mut entity,500,-200);
366    ///
367    ///     assert_eq!( entity.x, -500 );
368    ///     assert_eq!( entity.y, 800 );
369    ///     assert_eq!( entity.health, 1 );
370    ///     assert_eq!( entity.flags, 0b11111 );
371    /// }
372    ///
373    /// ```
374    ///
375    /// # Enum Example
376    ///
377    /// ```
378    /// use structural::{StructuralExt,Structural,fp};
379    ///
380    /// with_soda( &mut Beverage::Soda{ ml:600, cents:400 } );
381    /// with_soda( &mut MoreBeverages::Soda{ ml:600, cents:400 } );
382    ///
383    /// fn with_soda<T>(soda:&mut T)
384    /// where
385    ///     // `Beverage_SI` was generated for Beverage by the `Structural` derive.
386    ///     T: Beverage_SI
387    /// {
388    ///     assert_eq!( soda.field_mut(fp!(::Soda.ml)), Some(&mut 600) );
389    ///     assert_eq!( soda.field_mut(fp!(::Soda.cents)), Some(&mut 400) );
390    ///
391    ///     // Constructing the variant proxy is the only Option we have to handle here,
392    ///     // instead of every access to the fields in the Soda variant being optional.
393    ///     let proxy=soda.field_mut(fp!(::Soda)).expect("Expected a soda");
394    ///     assert_eq!( proxy.field_mut(fp!(ml)), &mut 600 );
395    ///     assert_eq!( proxy.field_mut(fp!(cents)), &mut 400 );
396    /// }
397    ///
398    /// #[derive(Structural)]
399    /// enum Beverage{
400    ///     Soda{ ml:u32, cents:u32 },
401    ///     Water,
402    /// }
403    ///
404    /// #[derive(Structural)]
405    /// # #[struc(no_trait)]
406    /// enum MoreBeverages{
407    ///     Soda{ ml:u32, cents:u32 },
408    ///     Water,
409    ///     Beer,
410    /// }
411    ///
412    ///
413    /// ```
414    #[inline(always)]
415    fn field_mut<'a, P>(&'a mut self, path: P) -> NormalizeFieldsOut<Result<&'a mut P::Ty, P::Err>>
416    where
417        P: RevGetFieldMutImpl<'a, Self>,
418        Result<&'a mut P::Ty, P::Err>: NormalizeFields,
419    {
420        path.rev_get_field_mut(self).normalize_fields()
421    }
422
423    /// Gets mutable references to multiple fields,determined by `path`.
424    ///
425    /// # Access many fields
426    ///
427    /// If you pass a `path` that references over 8 fields,this will return a
428    /// tuple of tuples(each nested tuple with 8 elements) instead of
429    /// a singly nested tuple.
430    ///
431    /// For examples accessing over 8 field look at the docs for the [`field_pat`] macro
432    ///
433    /// [`field_pat`]: ./macro.field_pat.html#the-structuralext-example
434    ///
435    /// # Example
436    ///
437    /// ```
438    /// use structural::{
439    ///     StructuralExt,GetFieldMut,GetFieldType,Structural,
440    ///     fp,field_path_aliases,
441    /// };
442    ///
443    /// field_path_aliases!{
444    ///     mod names{x,y}
445    /// }
446    ///
447    /// fn swap_coordinates<T,U>(this:&mut T)
448    /// where
449    ///     T:GetFieldMut<names::x,Ty=U>,
450    ///     T:GetFieldMut<names::y,Ty=U>,
451    /// {
452    ///     let (x,y)=this.fields_mut(fp!(x,y));
453    ///     std::mem::swap(x,y);
454    /// }
455    ///
456    /// {
457    ///     let mut this=Point2D{ x:100, y:300 };
458    ///     swap_coordinates(&mut this);
459    ///     assert_eq!( this.x, 300 );
460    ///     assert_eq!( this.y, 100 );
461    /// }
462    ///
463    /// {
464    ///     let mut this=Point3D{ x:30, y:0, z:500 };
465    ///     swap_coordinates(&mut this);
466    ///     assert_eq!( this.x, 0 );
467    ///     assert_eq!( this.y, 30 );
468    ///     assert_eq!( this.z, 500 );
469    /// }
470    ///
471    /// #[derive(Structural)]
472    /// struct Point2D<T>{
473    ///     pub x:T,
474    ///     pub y:T,
475    /// }
476    ///
477    /// #[derive(Structural)]
478    /// struct Point3D<T>{
479    ///     pub x:T,
480    ///     pub y:T,
481    ///     pub z:T,
482    /// }
483    ///
484    ///
485    /// ```
486    ///
487    /// # Example
488    ///
489    /// An example of how this method does not allow multiple mutable borrows
490    /// of the same field.
491    ///
492    /// ```compile_fail
493    /// use structural::{StructuralExt,fp};
494    ///
495    /// let mut tup=(1,1,2,3,5,8);
496    ///
497    /// let _=tup.fields_mut(fp!(4,4));
498    ///
499    /// ```
500    ///
501    /// # Enum Example
502    ///
503    /// ```
504    /// use structural::{StructuralExt,Structural,fp};
505    ///
506    /// with_book( &mut Medium::Book{ pages:500, title:"Dracular" } );
507    /// with_book( &mut MoreMedia::Book{ pages:500, title:"Dracular" } );
508    ///
509    /// fn with_book<T>(book:&mut T)
510    /// where
511    ///     // `Medium_SI` was generated for Medium by the `Structural` derive.
512    ///     T: Medium_SI
513    /// {
514    ///     assert_eq!(
515    ///         book.fields_mut(fp!(::Book.pages, ::Book.title)),
516    ///         ( Some(&mut 500), Some(&mut "Dracular") )
517    ///     );
518    ///
519    ///     // You can use `=>` to access multiple fields inside of a nested field(or a variant)
520    ///     // this allows accessing multiple fields inside an enum variant without having to
521    ///     // create an intermediate variant proxy
522    ///     // (look at the next assert for what that looks like).
523    ///     assert_eq!(
524    ///         book.fields_mut(fp!(::Book=>pages,title)),
525    ///         Some((&mut 500,&mut "Dracular")),
526    ///     );
527    ///
528    ///     assert_eq!(
529    ///         // This is equivalent to the field access in the previous assert
530    ///         book.field_mut(fp!(::Book)).map(|vp| vp.fields_mut(fp!(pages,title)) ),
531    ///         Some((&mut 500,&mut "Dracular"))
532    ///     );
533    ///
534    ///     assert_eq!( book.fields_mut(fp!(::Comic=>artist,in_color)), None);
535    /// }
536    ///
537    /// #[derive(Structural)]
538    /// enum Medium{
539    ///     Book{ pages:u32, title:&'static str },
540    ///     Comic{artist:&'static str,in_color:bool},
541    /// }
542    ///
543    /// #[derive(Structural)]
544    /// # #[struc(no_trait)]
545    /// enum MoreMedia{
546    ///     Book{ pages:u32, title:&'static str },
547    ///     Comic{artist:&'static str,in_color:bool},
548    ///     Television,
549    /// }
550    ///
551    /// ```
552    #[inline(always)]
553    fn fields_mut<'a, P>(&'a mut self, path: P) -> RevGetMultiFieldMutOut<'a, P, Self>
554    where
555        P: RevGetMultiFieldMut<'a, Self>,
556    {
557        path.rev_get_multi_field_mut(self)
558    }
559
560    /// Converts ´self´ into a field,determined by `path`.
561    ///
562    /// # Example
563    ///
564    /// ```
565    /// use structural::{StructuralExt,Structural,fp};
566    ///
567    ///
568    /// #[derive(Structural,Clone)]
569    /// #[struc(public,access="move")]
570    /// struct Tupled<T>(T,T,T,T);
571    ///
572    /// // The `Tupled_SI` trait was declared by the `Structural` derive on `Tupled`.
573    /// fn pick_index<T>(this:impl Tupled_SI<T>,which_one:u32)->T{
574    ///     match which_one % 4 {
575    ///         0=>this.into_field(fp!(0)),
576    ///         1=>this.into_field(fp!(1)),
577    ///         2=>this.into_field(fp!(2)),
578    ///         _=>this.into_field(fp!(3)),
579    ///     }
580    /// }
581    ///
582    /// {
583    ///     let tup=Tupled(13,21,34,55);
584    ///     
585    ///     assert_eq!( pick_index(tup.clone(),0), 13 );
586    ///     assert_eq!( pick_index(tup.clone(),1), 21 );
587    ///     assert_eq!( pick_index(tup.clone(),2), 34 );
588    ///     assert_eq!( pick_index(tup        ,3), 55 );
589    /// }
590    ///
591    /// {
592    ///     let array=[13,21,34,55];
593    ///     
594    ///     assert_eq!( pick_index(array.clone(),0), 13 );
595    ///     assert_eq!( pick_index(array.clone(),1), 21 );
596    ///     assert_eq!( pick_index(array.clone(),2), 34 );
597    ///     assert_eq!( pick_index(array        ,3), 55 );
598    /// }
599    ///
600    /// ```
601    ///
602    /// # Enum Example
603    ///
604    /// ```
605    /// use structural::{StructuralExt,Structural,fp};
606    ///
607    /// with_table( &Furniture::Table{ height_cm:101, width_cm:333 } );
608    /// with_table( &MoreFurniture::Table{ height_cm:101, width_cm:333 } );
609    ///
610    /// fn with_table<T>(table:&T)
611    /// where
612    ///     // `Furniture_SI` was generated for Furniture by the `Structural` derive.
613    ///     T: Furniture_SI + Clone
614    /// {
615    ///     assert_eq!( table.clone().into_field(fp!(::Table.height_cm)), Some(101) );
616    ///     assert_eq!( table.clone().into_field(fp!(::Table.width_cm)), Some(333) );
617    ///
618    ///     // Constructing the variant proxy is the only Option we have to handle here,
619    ///     // instead of every access to the fields in the Table variant being optional.
620    ///     let proxy=table.clone().into_field(fp!(::Table)).expect("Expected a table");
621    ///     assert_eq!( proxy.clone().into_field(fp!(height_cm)), 101 );
622    ///     assert_eq!( proxy.clone().into_field(fp!(width_cm)), 333 );
623    /// }
624    ///
625    /// #[derive(Structural,Clone)]
626    /// enum Furniture{
627    ///     Table{ height_cm:u32, width_cm:u32 },
628    ///     Chair,
629    /// }
630    ///
631    /// #[derive(Structural,Clone)]
632    /// # #[struc(no_trait)]
633    /// enum MoreFurniture{
634    ///     Table{ height_cm:u32, width_cm:u32 },
635    ///     Chair,
636    ///     Sofa,
637    /// }
638    ///
639    ///
640    /// ```
641    #[inline(always)]
642    fn into_field<P>(self, path: P) -> NormalizeFieldsOut<Result<P::Ty, P::Err>>
643    where
644        P: RevIntoFieldImpl<Self>,
645        P::Ty: Sized,
646        Result<P::Ty, P::Err>: NormalizeFields,
647        Self: Sized,
648    {
649        path.rev_into_field(self).normalize_fields()
650    }
651
652    /// Converts `self` into multiple fields by value.
653    ///
654    /// # Access many fields
655    ///
656    /// If you pass a `path` that references over 8 fields,this will return a
657    /// tuple of tuples(each nested tuple with 8 elements) instead of
658    /// a singly nested tuple.
659    ///
660    /// For examples accessing over 8 field look at the docs for the [`field_pat`] macro
661    ///
662    /// [`field_pat`]: ./macro.field_pat.html#the-structuralext-example
663    ///
664    /// # Valid Paths
665    ///
666    /// As opposed to the other multiple fields accessor methods,
667    /// this method only accepts field paths that refer to
668    /// multiple non-nested fields inside some value (possibly a nested field itself).
669    ///
670    /// <span id="valid_into_field_paths"></span>
671    ///
672    /// Examples of accepted field paths:
673    ///
674    /// - `fp!(a, b, c)`:
675    /// Accesses the `a`,`b`,and `c` fields.
676    ///
677    /// - `fp!(a.b.c=> d, e, f)`:
678    /// Accesses the `d`,`e`,and `f` fields inside the `a.b.c` field.
679    ///
680    /// - `fp!(::Foo=> bar, baz)`:
681    /// Accesses the `bar` and `baz` field in the `Foo` variant.
682    ///
683    /// Examples of rejected field paths(accepted in other methods):
684    ///
685    /// - `fp!(a.b, c)`
686    ///
687    /// - `fp!(a.b, c.d)`
688    ///
689    /// - `fp!(::Bar=> a.b, c.d)`
690    ///
691    /// # Struct Example
692    ///
693    /// ```rust
694    /// use structural::{StructuralExt,fp,make_struct};
695    /// use structural::for_examples::{Struct2, Struct2_SI, Struct3};
696    ///
697    /// assert_eq!(
698    ///     into_struct2(Struct3{ foo:Some("13".to_string()), bar: 21, baz: 34}),
699    ///     Struct2{ foo:Some("13".to_string()), bar: 21 }
700    /// );
701    ///
702    /// {
703    ///     let value=Struct2{ foo:Some(vec![55, 89]), bar: 144 };
704    ///     assert_eq!( into_struct2(value.clone()), value );
705    /// }
706    ///
707    /// assert_eq!(
708    ///     into_struct2(make_struct!{
709    ///         foo: None::<()>,
710    ///         bar: 233,
711    ///         baz: false,
712    ///         qux: "hello".to_string()
713    ///     }),
714    ///     Struct2{ foo:None, bar: 233 }
715    /// );
716    ///
717    /// // `Struct2_SI` was declared by the `Structural` derive on `Struct2`,
718    /// // aliasing the accessor traits that `Struct2` implements.
719    /// fn into_struct2<T,U>(this: impl Struct2_SI<T,U>)->Struct2<T,U>{
720    ///     let (foo, bar)=this.into_fields(fp!(foo, bar));
721    ///     Struct2{foo, bar}
722    /// }
723    ///
724    /// ```
725    ///
726    /// # Enum Example
727    ///
728    /// ```rust
729    /// use structural::{StructuralExt,fp};
730    /// use structural::for_examples::{Enum1, Enum1_SI, Enum2, Enum3};
731    ///
732    /// use std::cmp::Ordering;
733    ///
734    /// assert_eq!( into_enum1(Enum1::Foo(3, 5)), Some(Enum1::Foo(3, 5)) );
735    ///
736    /// assert_eq!( into_enum1(Enum2::Foo(8, 13)), Some(Enum1::Foo(8, 13)) );
737    /// assert_eq!( into_enum1(Enum2::Bar(Ordering::Less, None)), None );
738    ///
739    /// assert_eq!( into_enum1(Enum3::Foo(21, 34)), Some(Enum1::Foo(21, 34)) );
740    /// assert_eq!( into_enum1(Enum3::Bar(Ordering::Less, None)), None );
741    /// assert_eq!( into_enum1(Enum3::Baz { foom: "whoop"}), None );
742    ///
743    /// // `Enum1_SI` was declared by the `Structural` derive on `Enum1`,
744    /// // aliasing the accessor traits that `Enum1` implements.
745    /// fn into_enum1(this: impl Enum1_SI)-> Option<Enum1> {
746    ///     this.into_fields(fp!(::Foo=>0,1))
747    ///         .map(|(a,b)| Enum1::Foo(a,b) )
748    /// }
749    ///
750    /// ```
751    ///
752    #[inline(always)]
753    fn into_fields<P>(self, path: P) -> RevIntoMultiFieldOut<P, Self>
754    where
755        P: RevIntoMultiField<Self>,
756        Self: Sized,
757    {
758        path.rev_into_multi_field(self)
759    }
760
761    /// Checks whether an enum is a particular variant.
762    ///
763    /// # Example
764    ///
765    /// ```
766    /// use structural::{StructuralExt,Structural,fp};
767    ///
768    /// check_colors( &Color::Red, &Color::Blue, &Color::Green );
769    /// check_colors( &ColorPlus::Red, &ColorPlus::Blue, &ColorPlus::Green );
770    ///
771    /// fn check_colors<T>( red:&T, blue:&T, green:&T )
772    /// where
773    ///     // `Color_SI` was declared by the `Structural` derive on `Color`,
774    ///     // aliasing the accessor traits that `Color` implements.
775    ///     T: Color_SI
776    /// {
777    ///     assert!(  red.is_variant(fp!(Red)) );
778    ///     assert!( !red.is_variant(fp!(Blue)) );
779    ///     assert!( !red.is_variant(fp!(Green)) );
780    ///
781    ///     assert!( !blue.is_variant(fp!(Red)) );
782    ///     assert!(  blue.is_variant(fp!(Blue)) );
783    ///     assert!( !blue.is_variant(fp!(Green)) );
784    ///
785    ///     assert!( !green.is_variant(fp!(Red)) );
786    ///     assert!( !green.is_variant(fp!(Blue)) );
787    ///     assert!(  green.is_variant(fp!(Green)) );
788    /// }
789    ///
790    /// #[derive(Structural)]
791    /// enum Color{
792    ///     Red,
793    ///     Blue,
794    ///     Green,
795    /// }
796    ///
797    /// #[derive(Structural)]
798    /// # #[struc(no_trait)]
799    /// enum ColorPlus{
800    ///     Red,
801    ///     Blue,
802    ///     Green,
803    ///     Teal,
804    ///     White,
805    ///     Gray,
806    ///     Black,
807    /// }
808    ///
809    ///
810    /// ```
811    #[inline(always)]
812    fn is_variant<P>(&self, _path: P) -> bool
813    where
814        P: IsTStr,
815        Self: IsVariant<P>,
816    {
817        IsVariant::is_variant_(self, _path)
818    }
819
820    /// Converts this into another structural type using `IntoStructural`.
821    ///
822    /// # Struct Example
823    ///
824    /// ```rust
825    /// use structural::{
826    ///     Structural, StructuralExt, fp, make_struct,
827    /// };
828    ///
829    /// assert_eq!( Foo(55, 89, 144, 233).into_struc::<[_;3]>(), [55, 89, 144] );
830    ///
831    /// assert_eq!(
832    ///     make_struct!{x:"foo", y:"bar", z:"baz", w:"what"}.into_struc::<Point<_>>(),
833    ///     Point{x:"foo", y:"bar", z:"baz"}
834    /// );
835    ///
836    /// #[derive(Debug,Structural,PartialEq)]
837    /// # #[struc(no_trait)]
838    /// struct Foo(pub u8, pub u8, pub u8, pub u8);
839    ///
840    /// #[derive(Debug,Structural,PartialEq)]
841    /// struct Point<T>{
842    ///     pub x: T,
843    ///     pub y: T,
844    ///     pub z: T,
845    /// }
846    ///
847    /// // This macro also implement TryFromStructural for Point
848    /// structural::z_impl_from_structural!{
849    ///     impl[F, T] FromStructural<F> for Point<T>
850    ///     where[
851    ///         // `Point_SI` was generated for `Point` by the Structural derive.
852    ///         F: Point_SI<T>,
853    ///     ]{
854    ///         fn from_structural(this){
855    ///             let (x,y,z) = this.into_fields(fp!(x, y, z));
856    ///             Self{x,y,z}
857    ///         }
858    ///     }
859    /// }
860    ///
861    /// ```
862    ///
863    /// # Enum example
864    ///
865    /// ```rust
866    /// use structural::{
867    ///     for_examples::ResultLike,
868    ///     Structural, StructuralExt, switch,
869    /// };
870    ///
871    /// assert_eq!( ResultLike::<_,()>::Ok (300).into_struc::<ResultV>(), ResultV::Ok );
872    /// assert_eq!( ResultLike::<(),_>::Err(300).into_struc::<ResultV>(), ResultV::Err );
873    ///
874    /// assert_eq!( Ok::<_,()>(300).into_struc::<ResultV>(), ResultV::Ok );
875    /// assert_eq!( Err::<(),_>(300).into_struc::<ResultV>(), ResultV::Err );
876    ///
877    /// #[derive(Debug,Structural,PartialEq)]
878    /// enum ResultV{
879    ///     Ok,
880    ///     Err,
881    /// }
882    ///
883    /// // This macro also implement TryFromStructural for ResultV
884    /// structural::z_impl_from_structural!{
885    ///     impl[F] FromStructural<F> for ResultV
886    ///     where[
887    ///         // `ResultV_ESI` was generated for `Point` by the Structural derive.
888    ///         F: ResultV_ESI
889    ///     ]{
890    ///         fn from_structural(this){
891    ///             switch!{this;
892    ///                 Ok => ResultV::Ok,
893    ///                 Err => ResultV::Err,
894    ///             }
895    ///         }
896    ///     }
897    /// }
898    ///
899    /// ```
900    ///
901    fn into_struc<U>(self) -> U
902    where
903        Self: IntoStructural<U>,
904    {
905        self.into_structural()
906    }
907
908    /// Performs a fallible conversion into another structural type using `TryIntoStructural`.
909    ///
910    /// # Enum example
911    ///
912    /// ```rust
913    /// use structural::{
914    ///     convert::{EmptyTryFromError, TryFromError},
915    ///     for_examples::ResultLike,
916    ///     Structural, StructuralExt, switch,
917    /// };
918    ///
919    /// assert_eq!( Shapes::Rectangle.try_into_struc::<Shapes>(), Ok(Shapes::Rectangle) );
920    /// assert_eq!( Shapes::Circle.try_into_struc::<Shapes>()   , Ok(Shapes::Circle) );
921    ///
922    /// assert_eq!( MoreShapes::Rectangle.try_into_struc::<Shapes>(), Ok(Shapes::Rectangle) );
923    /// assert_eq!( MoreShapes::Circle.try_into_struc::<Shapes>()   , Ok(Shapes::Circle) );
924    /// assert_eq!(
925    ///     MoreShapes::Hexagon.try_into_struc::<Shapes>(),
926    ///     Err(TryFromError::with_empty_error(MoreShapes::Hexagon)),
927    /// );
928    ///
929    /// #[derive(Debug,Structural,PartialEq)]
930    /// enum Shapes{
931    ///     Rectangle,
932    ///     Circle,
933    /// }
934    ///
935    /// #[derive(Debug,Structural,PartialEq)]
936    /// enum MoreShapes{
937    ///     Rectangle,
938    ///     Circle,
939    ///     Hexagon,
940    /// }
941    ///
942    /// // This macro implements FromStructural in terms of TryFromStructural,
943    /// structural::z_impl_try_from_structural_for_enum!{
944    ///     impl[F] TryFromStructural<F> for Shapes
945    ///     where[ F: Shapes_SI, ]
946    ///     {
947    ///         type Error = EmptyTryFromError;
948    ///
949    ///         fn try_from_structural(this){
950    ///             switch! {this;
951    ///                 Rectangle => Ok(Self::Rectangle),
952    ///                 Circle => Ok(Self::Circle),
953    ///                 _ => Err(TryFromError::with_empty_error(this)),
954    ///             }
955    ///         }
956    ///     }
957    ///
958    ///     // `Shapes_ESI` was generated by the `Structural` derive for `Shapes`
959    ///     // aliasing its accessor trait impls,
960    ///     // and requires `F` to only have the `Rectangle` and `Circle` variants.
961    ///     FromStructural
962    ///     where[ F: Shapes_ESI, ]
963    /// }
964    ///
965    /// ```
966    ///
967    fn try_into_struc<U>(self) -> Result<U, TryFromError<Self, Self::Error>>
968    where
969        Self: TryIntoStructural<U>,
970    {
971        self.try_into_structural()
972    }
973}
974
975impl<T: ?Sized> StructuralExt for T {}