Skip to main content

structural/
wrapper.rs

1use crate::{
2    convert::{IntoStructural, TryFromError, TryIntoStructural},
3    enums::IsVariant,
4    field::{
5        GetField, GetFieldMut, NormalizeFields, NormalizeFieldsOut, RevGetFieldImpl,
6        RevGetFieldMutImpl, RevGetMultiField, RevGetMultiFieldMut, RevGetMultiFieldMutOut,
7        RevGetMultiFieldOut, RevIntoFieldImpl, RevIntoMultiField, RevIntoMultiFieldOut,
8    },
9    path::IsTStr,
10};
11
12use core_extensions::{
13    collection_traits::{Cloned, ClonedOut},
14    ConstDefault,
15};
16
17use std_::{
18    fmt::Debug,
19    ops::{Index, IndexMut},
20};
21
22/// A wrapper type alternative to [`StructuralExt`],
23/// with methods for accessing fields in structural types.
24///
25/// # Example: Struct
26///
27/// ```rust
28/// use structural::{StrucWrapper, Structural, fp};
29/// use structural::structural_aliases::Array3;
30///
31/// let mut this=Point{x:3, y:5, z:8};
32/// let mut tuple=(13,21,34);
33///
34/// rotate_tuple(&mut this);
35/// rotate_tuple(&mut tuple);
36///
37/// assert_eq!( this, Point{x:8, y:3, z:5} );
38/// assert_eq!( tuple, (34,13,21) );
39///
40/// fn rotate_tuple(tuple: &mut dyn Array3<u32>){
41///     use std::mem::swap;
42///
43///     let mut tuple=StrucWrapper(tuple);
44///     let (a,b,c)=tuple.muts(fp!(0,1,2));
45///     swap(b,c);
46///     swap(a,b);
47/// }
48///
49/// #[derive(Debug,Structural,PartialEq)]
50/// struct Point{
51///     #[struc(rename="0")]
52///     pub x: u32,
53///     #[struc(rename="1")]
54///     pub y: u32,
55///     #[struc(rename="2")]
56///     pub z: u32,
57/// }
58///
59/// ```
60///
61/// # Example: Enum
62///
63/// ```rust
64/// use structural::{StrucWrapper, Structural, fp};
65///
66/// assert_eq!( get_value(States::Initial), 1 );
67/// assert_eq!( get_value(States::Open{how_much: 10}), 160+2 );
68/// assert_eq!( get_value(States::Closed), 3 );
69///
70/// assert_eq!( get_value(UberStates::Initial), 1 );
71/// assert_eq!( get_value(UberStates::Open{how_much: 10, throughput: 14}), 160+2 );
72/// assert_eq!( get_value(UberStates::Open{how_much: 20, throughput: 55}), 320+2 );
73/// assert_eq!( get_value(UberStates::Closed), 3 );
74///
75/// // `States_SI` was declared by the `Structural` derive macro on
76/// // the `States` enum,aliasing its accessor trait impls.
77/// fn get_value(this: impl States_SI)-> u64 {
78///     let this=StrucWrapper(this);
79///
80///     if this.is_variant(fp!(Initial)) {
81///         1
82///     }else if let Some(how_much)= this.r(fp!(::Open.how_much)) {
83///         2 + ((*how_much as u64) << 4)
84///     }else if this.is_variant(fp!(Closed)) {
85///         3
86///     }else{
87///         0
88///     }
89/// }
90///
91/// // This function is equivalent to `get_value`
92/// //
93/// // `States_SI` was declared by the `Structural` derive macro on
94/// // the `States` enum,aliasing its accessor trait impls.
95/// fn get_value_switch(this: impl States_SI)-> u64 {
96///     structural::switch!{ref this;
97///         Initial=>1,
98///         Open{&how_much}=>2 + ((how_much as u64) << 4),
99///         Closed=>3,
100///         _=>0,
101///     }
102/// }
103///
104/// #[derive(Structural)]
105/// enum States{
106///     Initial,
107///     Open{how_much: u32},
108///     Closed,
109/// }
110///
111/// #[derive(Structural)]
112/// enum UberStates{
113///     Initial,
114///     Open{
115///         how_much: u32,
116///         throughput: u64,
117///     },
118///     Closed,
119/// }
120///
121/// ```
122///
123/// [`StructuralExt`]: ./trait.StructuralExt.html
124#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
125#[repr(transparent)]
126pub struct StrucWrapper<T>(pub T);
127
128impl<T> StrucWrapper<T> {
129    /// Gets a reference to a single field,determined by `path`.
130    ///
131    /// This function is equivalent to [`StructuralExt::field_`],
132    /// which has more complete examples.
133    ///
134    /// # Example: Struct
135    ///
136    /// ```
137    /// use structural::{StrucWrapper, fp};
138    /// use structural::structural_aliases::Array5;
139    ///
140    /// assertions((0,0,13,0,34));
141    /// assertions((0,0,13,0,34,""));
142    /// assertions((0,0,13,0,34,"",false));
143    ///
144    /// assertions([0,0,13,0,34]);
145    /// assertions([0,0,13,0,34,0]);
146    /// assertions([0,0,13,0,34,0,0]);
147    ///
148    /// fn assertions(this: impl Array5<u64>){
149    ///     let mut this=StrucWrapper(this);
150    ///
151    ///     assert_eq!( this.r(fp!(2)), &13  );
152    ///     assert_eq!( this.r(fp!(4)), &34 );
153    /// }
154    ///
155    ///
156    /// ```
157    ///
158    /// # Example: Enum
159    ///
160    /// ```rust
161    /// use structural::{StrucWrapper, fp};
162    /// use structural::for_examples::{
163    ///     EnumWithNewtype, EnumWithoutNewtype, EnumWithNewtype_SI, RefWrapper,
164    /// };
165    ///
166    /// assertions(EnumWithNewtype::U32(RefWrapper(0x100, &43370)));
167    ///
168    /// assertions(EnumWithoutNewtype::U32(0x100, &43370));
169    ///
170    /// // `EnumWithNewtype_SI` was declared by the `Structural` derive macro on
171    /// // the `EnumWithNewtype` enum,aliasing its accessor trait impls.
172    /// fn assertions<'a>(this: impl EnumWithNewtype_SI<'a>){
173    ///     let mut this=StrucWrapper(this);
174    ///
175    ///     assert_eq!( this.r(fp!(::U32.0)), Some(&0x100) );
176    ///     assert_eq!( this.r(fp!(::U32.1)), Some(&&43370) );
177    ///     assert_eq!( this.r(fp!(::U64.0)), None );
178    /// }
179    ///
180    /// ```
181    ///
182    /// [`StructuralExt::field_`]: ./trait.StructuralExt.html#method.field_
183    #[inline(always)]
184    pub fn r<'a, P>(&'a self, path: P) -> NormalizeFieldsOut<Result<&'a P::Ty, P::Err>>
185    where
186        P: RevGetFieldImpl<'a, T>,
187        Result<&'a P::Ty, P::Err>: NormalizeFields,
188    {
189        path.rev_get_field(&self.0).normalize_fields()
190    }
191
192    /// Gets a mutable reference to a single field,determined by `path`.
193    ///
194    /// This function is equivalent to [`StructuralExt::field_mut`],
195    /// which has more complete examples.
196    ///
197    /// # Example: Struct
198    ///
199    /// ```rust
200    /// use structural::{StrucWrapper, Structural, fp, make_struct};
201    ///
202    /// assertions(Puck{name:"John", surname:"Chickenbert"});
203    ///
204    /// assertions(make_struct!{
205    ///     #![derive(Debug,Copy,Clone)]
206    ///     name:"John",
207    ///     surname:"Chickenbert"
208    /// });
209    ///
210    /// // `Puck_SI` was declared by the `Structural` derive macro on the Puck struct,
211    /// // aliasing its accessor trait impls.
212    /// fn assertions(this: impl Puck_SI + Copy){
213    ///     let mut this=StrucWrapper(this);
214    ///
215    ///     assert_eq!( this.m(fp!(name)), &mut "John" );
216    ///     assert_eq!( this.m(fp!(surname)), &mut "Chickenbert" );
217    /// }
218    ///
219    /// #[derive(Structural,Copy,Clone)]
220    /// pub struct Puck{
221    ///     pub name: &'static str,
222    ///     pub surname: &'static str,
223    /// }
224    ///
225    /// ```
226    ///
227    /// # Example: Enum
228    ///
229    /// ```rust
230    /// use structural::{StrucWrapper, fp};
231    /// use structural::for_examples::{
232    ///     EnumWithNewtype, EnumWithoutNewtype, EnumWithNewtype_SI, RefWrapper,
233    /// };
234    ///
235    /// assertions(EnumWithNewtype::U32(RefWrapper(0x100, &43370)));
236    ///
237    /// assertions(EnumWithoutNewtype::U32(0x100, &43370));
238    ///
239    /// // `EnumWithNewtype_SI` was declared by the `Structural` derive macro on
240    /// // the `EnumWithNewtype` enum,aliasing its accessor trait impls.
241    /// fn assertions<'a>(this: impl EnumWithNewtype_SI<'a>){
242    ///     let mut this=StrucWrapper(this);
243    ///
244    ///     assert_eq!( this.m(fp!(::U32.0)), Some(&mut 0x100) );
245    ///     assert_eq!( this.m(fp!(::U32.1)), Some(&mut &43370) );
246    ///     assert_eq!( this.m(fp!(::U64.0)), None );
247    /// }
248    ///
249    /// ```
250    ///
251    /// [`StructuralExt::field_mut`]: ./trait.StructuralExt.html#method.field_mut
252    #[inline(always)]
253    pub fn m<'a, P>(&'a mut self, path: P) -> NormalizeFieldsOut<Result<&'a mut P::Ty, P::Err>>
254    where
255        P: RevGetFieldMutImpl<'a, T>,
256        Result<&'a mut P::Ty, P::Err>: NormalizeFields,
257    {
258        path.rev_get_field_mut(&mut self.0).normalize_fields()
259    }
260
261    /// Converts this into a single field by value,determined by `path`.
262    ///
263    /// This function is equivalent to [`StructuralExt::into_field`],
264    /// which has more complete examples.
265    ///
266    /// # Example: Struct
267    ///
268    /// ```rust
269    /// use structural::{StrucWrapper, Structural, fp, make_struct};
270    ///
271    /// assertions(Puck{name:"John", surname:"Chickenbert"});
272    ///
273    /// assertions(make_struct!{
274    ///     #![derive(Debug,Copy,Clone)]
275    ///     name:"John",
276    ///     surname:"Chickenbert"
277    /// });
278    ///
279    /// // `Puck_SI` was declared by the `Structural` derive macro on the Puck struct,
280    /// // aliasing its accessor trait impls.
281    /// fn assertions(this: impl Puck_SI + Copy){
282    ///     let this=StrucWrapper(this);
283    ///
284    ///     assert_eq!( this.v(fp!(name)), "John" );
285    ///     assert_eq!( this.v(fp!(surname)), "Chickenbert" );
286    /// }
287    ///
288    /// #[derive(Structural,Copy,Clone)]
289    /// pub struct Puck{
290    ///     pub name: &'static str,
291    ///     pub surname: &'static str,
292    /// }
293    ///
294    /// ```
295    ///
296    /// # Example: Enum
297    ///
298    /// ```rust
299    /// use structural::{StrucWrapper, fp};
300    /// use structural::for_examples::{WithBoom, WithBoom_SI, Bomb};
301    ///
302    /// assertions(WithBoom::Boom{a:"#eh#", b:&[5,8,13]});
303    /// assertions(    Bomb::Boom{a:"#eh#", b:&[5,8,13]});
304    ///
305    /// // `WithBoom_SI` was declared by the `Structural` derive macro on the `WithBoom` enum,
306    /// // aliasing its accessor trait impls.
307    /// fn assertions(this: impl WithBoom_SI + Copy){
308    ///     let this=StrucWrapper(this);
309    ///
310    ///     assert_eq!( this.v(fp!(::Boom.a)), Some("#eh#") );
311    ///     assert_eq!( this.v(fp!(::Boom.b)), Some(&[5,8,13][..]) );
312    ///     assert!( this.v(fp!(::Nope)).is_none() );
313    /// }
314    ///
315    /// ```
316    ///
317    /// [`StructuralExt::into_field`]: ./trait.StructuralExt.html#method.into_field
318    #[inline(always)]
319    pub fn v<P>(self, path: P) -> NormalizeFieldsOut<Result<P::Ty, P::Err>>
320    where
321        P: RevIntoFieldImpl<T>,
322        P::Ty: Sized,
323        Result<P::Ty, P::Err>: NormalizeFields,
324    {
325        path.rev_into_field(self.0).normalize_fields()
326    }
327
328    /// Gets references to multiple fields,determined by `path`.
329    ///
330    /// This function is equivalent to [`StructuralExt::fields`],
331    /// which has more complete examples.
332    ///
333    /// # Example: Struct
334    ///
335    /// ```
336    /// use structural::{StrucWrapper, fp, make_struct};
337    /// use structural::for_examples::{Struct2, Struct2_SI, Struct3};
338    ///
339    /// assertions(Struct2{foo:Some("&"), bar:(true,false)});
340    /// assertions(Struct3{foo:Some("&"), bar:(true,false), baz:&[()]});
341    /// assertions(make_struct!{foo:Some("&"), bar:(true,false), boom:()});
342    ///
343    /// // `Struct2_SI` was declared by the `Structural` derive macro on the Struct2 struct,
344    /// // aliasing its accessor trait impls.
345    /// fn assertions(this: impl Struct2_SI<&'static str, (bool,bool)>){
346    ///     let this=StrucWrapper(this);
347    ///
348    ///     assert_eq!( this.refs(fp!(foo,bar)), (&Some("&"), &(true,false)) );
349    /// }
350    ///
351    /// ```
352    ///
353    /// # Example: Enum
354    ///
355    /// ```
356    /// use structural::{StrucWrapper, fp};
357    /// use structural::for_examples::{WithBoom, WithBoom_SI, Bomb};
358    ///
359    /// assertions(WithBoom::Boom{a:"#eh#", b:&[5,8,13]});
360    /// assertions(    Bomb::Boom{a:"#eh#", b:&[5,8,13]});
361    ///
362    /// // `WithBoom_SI` was declared by the `Structural` derive macro on the `WithBoom` enum,
363    /// // aliasing its accessor trait impls.
364    /// fn assertions(this: impl WithBoom_SI){
365    ///     let this=StrucWrapper(this);
366    ///
367    ///     assert_eq!( this.refs(fp!(::Boom=>a,b)), Some((&"#eh#", &&[5,8,13][..])) );
368    ///     assert!( this.refs(fp!(::Nope=>)).is_none() );
369    /// }
370    ///
371    /// ```
372    ///
373    /// [`StructuralExt::fields`]: ./trait.StructuralExt.html#method.fields
374    #[inline(always)]
375    pub fn refs<'a, P>(&'a self, path: P) -> RevGetMultiFieldOut<'a, P, T>
376    where
377        P: RevGetMultiField<'a, T>,
378    {
379        path.rev_get_multi_field(&self.0)
380    }
381
382    /// Gets clones of multiple fields,determined by `path`.
383    ///
384    /// This function is equivalent to [`StructuralExt::cloned_fields`],
385    /// which has more complete examples.
386    ///
387    /// # Example: Struct
388    ///
389    /// ```
390    /// use structural::{StrucWrapper, fp, make_struct};
391    /// use structural::for_examples::{Struct2, Struct2_SI, Struct3};
392    ///
393    /// assertions(Struct2{foo:Some("&"), bar:(true,false)});
394    /// assertions(Struct3{foo:Some("&"), bar:(true,false), baz:&[()]});
395    /// assertions(make_struct!{foo:Some("&"), bar:(true,false), boom:()});
396    ///
397    /// fn assertions(this: impl Struct2_SI<&'static str, (bool,bool)>){
398    ///     let this=StrucWrapper(this);
399    ///
400    ///     assert_eq!( this.clones(fp!(foo,bar)), (Some("&"), (true,false)) );
401    /// }
402    ///
403    /// ```
404    ///
405    /// # Example: Enum
406    ///
407    /// ```
408    /// use structural::{StrucWrapper, fp};
409    /// use structural::for_examples::{Enum2, Enum2_SI, Enum3, Enum4};
410    ///
411    /// use std::cmp::Ordering;
412    ///
413    /// assertions(Enum2::Bar(Ordering::Less, Some(1337)));
414    /// assertions(Enum3::Bar(Ordering::Less, Some(1337)));
415    /// assertions(Enum4::Bar(Ordering::Less, Some(1337)));
416    ///
417    /// fn assertions(this: impl Enum2_SI){
418    ///     let this=StrucWrapper(this);
419    ///
420    ///     assert_eq!( this.clones(fp!(::Bar=>0,1)), Some((Ordering::Less, Some(1337))) );
421    ///     assert_eq!( this.clones(fp!(::Foo=>0,1)), None );
422    /// }
423    ///
424    ///
425    /// ```
426    ///
427    /// [`StructuralExt::cloned_fields`]: ./trait.StructuralExt.html#method.cloned_fields
428    #[inline(always)]
429    pub fn clones<'a, P>(&'a self, path: P) -> ClonedOut<RevGetMultiFieldOut<'a, P, T>>
430    where
431        P: RevGetMultiField<'a, T>,
432        RevGetMultiFieldOut<'a, P, T>: Cloned,
433    {
434        path.rev_get_multi_field(&self.0).cloned_()
435    }
436
437    /// Gets mutable references to multiple fields,determined by `path`.
438    ///
439    /// This function is equivalent to [`StructuralExt::fields_mut`],
440    /// which has more complete examples.
441    ///
442    /// # Example: Struct
443    ///
444    /// ```
445    /// use structural::{StrucWrapper, fp};
446    /// use structural::structural_aliases::Array5;
447    ///
448    /// assertions((0,0,8,0,21));
449    /// assertions((0,0,8,0,21,""));
450    /// assertions((0,0,8,0,21,"",false));
451    ///
452    /// assertions([0,0,8,0,21]);
453    /// assertions([0,0,8,0,21,0]);
454    /// assertions([0,0,8,0,21,0,0]);
455    ///
456    /// fn assertions(this: impl Array5<u64>){
457    ///     let mut this=StrucWrapper(this);
458    ///
459    ///     assert_eq!( this.muts(fp!(2,4)), (&mut 8, &mut 21) );
460    /// }
461    ///
462    ///
463    /// ```
464    ///
465    /// # Example: Enum
466    ///
467    /// ```
468    /// use structural::{StrucWrapper, fp};
469    /// use structural::for_examples::{Enum2, Enum2_SI, Enum3, Enum4};
470    ///
471    /// assertions(Enum2::Foo(27, 81));
472    /// assertions(Enum3::Foo(27, 81));
473    /// assertions(Enum4::Foo(27, 81));
474    ///
475    /// fn assertions(this: impl Enum2_SI){
476    ///     let mut this=StrucWrapper(this);
477    ///
478    ///     assert_eq!( this.muts(fp!(::Foo=>0,1)), Some((&mut 27, &mut 81)) );
479    ///     assert_eq!( this.muts(fp!(::Bar=>0)), None );
480    /// }
481    ///
482    ///
483    /// ```
484    ///
485    /// [`StructuralExt::fields_mut`]: ./trait.StructuralExt.html#method.fields_mut
486    #[inline(always)]
487    pub fn muts<'a, P>(&'a mut self, path: P) -> RevGetMultiFieldMutOut<'a, P, T>
488    where
489        P: RevGetMultiFieldMut<'a, T>,
490    {
491        path.rev_get_multi_field_mut(&mut self.0)
492    }
493
494    /// Converts this into multiple fields by value, determined by path.
495    ///
496    /// This function is equivalent to [`StructuralExt::into_fields`],
497    /// which has more complete documentation.
498    ///
499    /// # Valid Paths
500    ///
501    /// As opposed to the other multiple fields accessor methods,
502    /// this method only accepts field paths that refer to
503    /// multiple non-nested fields inside some value (possibly a nested field itself).
504    ///
505    /// For examples of valid and invalid paths to pass as parameter
506    /// [look here](./trait.StructuralExt.html#valid_into_field_paths).
507    ///
508    /// # Example: Struct
509    ///
510    /// ```rust
511    /// use structural::{StrucWrapper, Structural, fp, make_struct};
512    ///
513    /// assert_eq!(
514    ///     into_parts(Bicycle{
515    ///         frame: Frame("wheeee"),
516    ///         wheels: [Wheel("first"), Wheel("second")],
517    ///         handle_bar: HandleBar("hands on me"),
518    ///     }),
519    ///     (Frame("wheeee"), [Wheel("first"), Wheel("second")], HandleBar("hands on me"))
520    /// );
521    ///
522    /// assert_eq!(
523    ///     into_parts(make_struct!{
524    ///         frame: Frame("frame"),
525    ///         wheels: [Wheel("1"), Wheel("4")],
526    ///         handle_bar: HandleBar("9"),
527    ///     }),
528    ///     (Frame("frame"), [Wheel("1"), Wheel("4")], HandleBar("9"))
529    /// );
530    ///
531    /// // The `Bicycle_SI` was generated for the `Bicycle` struct by the `Structural` derive,
532    /// // aliasing it's accessor traits
533    /// fn into_parts(this: impl Bicycle_SI)-> (Frame, [Wheel;2], HandleBar) {
534    ///     let this = StrucWrapper(this);
535    ///
536    ///     this.vals(fp!(frame, wheels, handle_bar))
537    /// }
538    ///
539    /// #[derive(Structural,Debug,Copy,Clone,PartialEq)]
540    /// struct Bicycle{
541    ///     pub frame: Frame,
542    ///     pub wheels: [Wheel;2],
543    ///     pub handle_bar: HandleBar,
544    /// }
545    ///
546    /// # #[derive(Debug,Copy,Clone,PartialEq)]
547    /// # struct Frame(&'static str);
548    /// #
549    /// # #[derive(Debug,Copy,Clone,PartialEq)]
550    /// # struct Wheel(&'static str);
551    /// #
552    /// # #[derive(Debug,Copy,Clone,PartialEq)]
553    /// # struct HandleBar(&'static str);
554    ///
555    /// ```
556    ///
557    /// # Example: Enum
558    ///
559    /// ```rust
560    /// use structural::{StrucWrapper, Structural, TS, fp, make_struct};
561    ///
562    /// let human=Human{name: "bob".into(), gold: 600};
563    /// assert_eq!( enum_into_human(Entities::Human(human.clone())), Some(human.clone()) );
564    ///
565    /// assert_eq!(
566    ///     enum_into_human(MoreEntities::Human{name: "John".into(), gold: 1234}),
567    ///     Some(Human{name: "John".into(), gold: 1234})
568    /// );
569    ///
570    /// // The `Human_VSI` trait was generated for `Human` by the `Structural` derive macro,
571    /// // to access variants with the same fields as Human.
572    /// // The `TS!(Human)` argument makes it require the variant to be `Human`.
573    /// fn enum_into_human(this: impl Human_VSI<TS!(Human)>)-> Option<Human> {
574    ///     let this= StrucWrapper(this);
575    ///     let (name, gold)= this.vals(fp!(::Human=>name,gold))?;
576    ///     Some(Human{name, gold})
577    /// }
578    ///
579    /// #[derive(Structural, Clone, Debug, PartialEq)]
580    /// pub struct Human{
581    ///     pub name: String,
582    ///     pub gold: u64,
583    /// }
584    ///
585    /// #[derive(Structural, Clone, Debug, PartialEq)]
586    /// pub enum Entities {
587    ///     #[struc(newtype(bounds = "Human_VSI<@variant>"))]
588    ///     Human(Human),
589    ///     Wolf,
590    /// }
591    ///
592    /// #[derive(Structural, Clone, Debug, PartialEq)]
593    /// # #[struc(no_trait)]
594    /// pub enum MoreEntities {
595    ///     Human{
596    ///         name: String,
597    ///         gold: u64,
598    ///     },
599    ///     Wolf,
600    ///     Cat,
601    ///     Dog,
602    /// }
603    ///
604    ///
605    /// ```
606    ///
607    /// [`StructuralExt::into_fields`]: ./trait.StructuralExt.html#method.into_fields
608    #[inline(always)]
609    pub fn vals<P>(self, path: P) -> RevIntoMultiFieldOut<P, T>
610    where
611        P: RevIntoMultiField<T>,
612    {
613        path.rev_into_multi_field(self.0)
614    }
615
616    /// Queries whether an enum is a particular variant.
617    ///
618    /// This function is equivalent to [`StructuralExt::is_variant`].
619    ///
620    /// # Example
621    ///
622    /// ```
623    /// use structural::{StrucWrapper, Structural, fp};
624    ///
625    /// assertions(
626    ///     EnumOne::Bar,
627    ///     EnumOne::Baz{x:0, y:100},
628    ///     EnumOne::Qux("hello", "world"),
629    /// );
630    ///
631    /// assertions(EnumTwo::Bar, EnumTwo::Baz, EnumTwo::Qux);
632    ///
633    /// fn assertions<T>(bar: T, baz: T, qux: T)
634    /// where
635    ///     T: EnumTwo_SI
636    /// {
637    ///     let bar=StrucWrapper(bar);
638    ///     let baz=StrucWrapper(baz);
639    ///     let qux=StrucWrapper(qux);
640    ///
641    ///     assert!( bar.is_variant(fp!(Bar)) );
642    ///     assert!( baz.is_variant(fp!(Baz)) );
643    ///     assert!( qux.is_variant(fp!(Qux)) );
644    /// }
645    ///
646    /// #[derive(Structural)]
647    /// # #[struc(no_trait)]
648    /// enum EnumOne{
649    ///     Bar,
650    ///     Baz{
651    ///         x:u32,
652    ///         y:u32,
653    ///     },
654    ///     Qux(&'static str, &'static str),
655    /// }
656    ///
657    /// #[derive(Structural)]
658    /// enum EnumTwo{
659    ///     Bar,
660    ///     Baz,
661    ///     Qux,
662    /// }
663    ///
664    /// ```
665    ///
666    /// [`StructuralExt::is_variant`]: ./trait.StructuralExt.html#method.is_variant
667    #[inline(always)]
668    pub fn is_variant<P>(&self, _path: P) -> bool
669    where
670        P: IsTStr,
671        T: IsVariant<P>,
672    {
673        IsVariant::is_variant_(&self.0, _path)
674    }
675
676    /// Converts this into another structural type,using `IntoStructural`.
677    ///
678    /// # Struct Example
679    ///
680    /// ```rust
681    /// use structural::{
682    ///     for_examples::{StructFoo, StructBar},
683    ///     FP, IntoField, StrucWrapper, make_struct,
684    /// };
685    ///
686    /// assert_eq!( into_foo(make_struct!{foo: 100}), StructFoo{foo: 100} );
687    /// assert_eq!( into_foo(make_struct!{foo: 200}), StructFoo{foo: 200} );
688    ///
689    /// assert_eq!( into_bar(make_struct!{bar: 3}), StructBar{bar: 3} );
690    /// assert_eq!( into_bar(make_struct!{bar: 5}), StructBar{bar: 5} );
691    ///
692    /// fn into_foo<T>(this: T)->StructFoo<T::Ty>
693    /// where
694    ///     T: IntoField<FP!(foo)>
695    /// {
696    ///     let this=StrucWrapper(this);
697    ///     this.into_struc()
698    /// }
699    ///
700    /// fn into_bar<T>(this: T)->StructBar<T::Ty>
701    /// where
702    ///     T: IntoField<FP!(bar)>
703    /// {
704    ///     let this=StrucWrapper(this);
705    ///     this.into_struc()
706    /// }
707    ///
708    /// ```
709    ///
710    /// # Enum Example
711    ///
712    /// ```rust
713    /// use structural::{
714    ///     convert::{EmptyTryFromError, FromStructural, TryFromError, TryFromStructural},
715    ///     for_examples::Enum3,
716    ///     Structural, StrucWrapper, make_struct, switch,
717    /// };
718    ///
719    /// use std::cmp::Ordering;
720    ///
721    /// assert_eq!( into_v(Enum3::Foo(3, 8)), NoPayload::Foo );
722    /// assert_eq!( into_v(Enum3::Bar(Ordering::Less, None)), NoPayload::Bar );
723    /// assert_eq!( into_v(Enum3::Baz{foom: "what"}), NoPayload::Baz );
724    ///
725    /// assert_eq!( into_v(WithPayload::Foo(13)), NoPayload::Foo );
726    /// assert_eq!( into_v(WithPayload::Bar(21)), NoPayload::Bar );
727    /// assert_eq!( into_v(WithPayload::Baz(34)), NoPayload::Baz );
728    ///
729    /// assert_eq!( into_v(NoPayload::Foo), NoPayload::Foo );
730    /// assert_eq!( into_v(NoPayload::Bar), NoPayload::Bar );
731    /// assert_eq!( into_v(NoPayload::Baz), NoPayload::Baz );
732    ///
733    /// // `NoPayload_ESI` was generated by the `Structural` derive macro for `NoPayload`,
734    /// // aliasing its accessor trait impls.
735    /// fn into_v(this: impl NoPayload_ESI)->NoPayload {
736    ///     let this = StrucWrapper(this);
737    ///     this.into_struc()
738    /// }
739    ///
740    /// #[derive(Debug,Structural,PartialEq)]
741    /// enum WithPayload<T>{
742    ///     Foo(T),
743    ///     Bar(T),
744    ///     Baz(T),
745    /// }
746    ///
747    /// #[derive(Debug,Structural,PartialEq)]
748    /// enum NoPayload{
749    ///     Foo,
750    ///     Bar,
751    ///     Baz,
752    /// }
753    ///
754    /// // This macro allows enums to only implement the `TryFromStructural` trait,
755    /// // delegating the `FromStructural` trait to it.
756    /// structural::z_impl_try_from_structural_for_enum!{
757    ///     impl[F] TryFromStructural<F> for NoPayload
758    ///     where[ F: NoPayload_SI, ]
759    ///     {
760    ///         type Error = EmptyTryFromError;
761    ///
762    ///          fn try_from_structural(this){
763    ///              switch!{this;
764    ///                  Foo => Ok(NoPayload::Foo),
765    ///                  Bar => Ok(NoPayload::Bar),
766    ///                  Baz => Ok(NoPayload::Baz),
767    ///                  _ => Err(TryFromError::with_empty_error(this)),
768    ///              }
769    ///          }
770    ///     }
771    ///     FromStructural
772    ///     where[ F: NoPayload_ESI, ]
773    /// }
774    ///
775    ///
776    /// ```
777    #[inline(always)]
778    pub fn into_struc<U>(self) -> U
779    where
780        T: IntoStructural<U>,
781    {
782        self.0.into_structural()
783    }
784
785    /// Performs a fallible conversion into another structural type using `TryIntoStructural`.
786    ///
787    /// # Enum example
788    ///
789    /// ```rust
790    /// use structural::{
791    ///     convert::{EmptyTryFromError, TryFromError},
792    ///     for_examples::ResultLike,
793    ///     Structural, StructuralExt, switch,
794    /// };
795    ///
796    /// assert_eq!(
797    ///     MoreCommand::Open(Door::Green).try_into_struc::<Command>(),
798    ///     Ok(Command::Open(Door::Green)),
799    /// );
800    /// assert_eq!(
801    ///     MoreCommand::Close(Door::Green).try_into_struc::<Command>(),
802    ///     Ok(Command::Close(Door::Green)),
803    /// );
804    ///
805    /// let lock_cmd = MoreCommand::Lock(Door::Green, Key(12345678));
806    /// assert_eq!(
807    ///     lock_cmd.clone().try_into_struc::<Command>(),
808    ///     Err(TryFromError::with_empty_error(lock_cmd)),
809    /// );
810    ///
811    ///
812    /// #[derive(Debug,Clone,Structural,PartialEq)]
813    /// enum Command{
814    ///     Open(Door),
815    ///     Close(Door),
816    /// }
817    ///
818    /// #[derive(Debug,Clone,Structural,PartialEq)]
819    /// enum MoreCommand{
820    ///     Open(Door),
821    ///     Close(Door),
822    ///     Lock(Door, Key),
823    /// }
824    ///
825    /// # #[derive(Debug,Copy,Clone,PartialEq)]
826    /// # enum Door{
827    /// #     Red,
828    /// #     Blue,
829    /// #     Green,
830    /// # }
831    /// #
832    /// # #[derive(Debug,Copy,Clone,PartialEq)]
833    /// # struct Key(u128);
834    ///
835    /// // This macro implements FromStructural in terms of TryFromStructural,
836    /// structural::z_impl_try_from_structural_for_enum!{
837    ///     impl[F] TryFromStructural<F> for Command
838    ///     where[ F: Command_SI, ]
839    ///     {
840    ///         type Error = EmptyTryFromError;
841    ///
842    ///         fn try_from_structural(this){
843    ///             switch! {this;
844    ///                 Open(door) => Ok(Self::Open(door)),
845    ///                 Close(door) => Ok(Self::Close(door)),
846    ///                 _ => Err(TryFromError::with_empty_error(this)),
847    ///             }
848    ///         }
849    ///     }
850    ///
851    ///     // `Command_ESI` was generated by the `Structural` derive for `Command`
852    ///     // aliasing its accessor trait impls,
853    ///     // and requires `F` to only have the `Open`,and `Close` variants.
854    ///     FromStructural
855    ///     where[ F: Command_ESI, ]
856    /// }
857    ///
858    /// ```
859    ///
860    #[inline(always)]
861    pub fn try_into_struc<U>(self) -> Result<U, TryFromError<T, T::Error>>
862    where
863        T: TryIntoStructural<U>,
864    {
865        self.0.try_into_structural()
866    }
867}
868
869impl<T> StrucWrapper<T> {
870    /// Turns a `&StrucWrapper<T>` into a `StrucWrapper<&T>`.
871    ///
872    /// # Example
873    ///
874    /// ```rust
875    /// use structural::{Structural, StrucWrapper, fp, make_struct};
876    ///
877    /// {
878    ///     let this= StrucWrapper(Struct3{foo:Some(13), bar:21, baz:"34"});
879    ///     with_struct3(this.as_ref());
880    ///     // Because of the `.as_ref()`,`this` wasn't consumed
881    ///     with_struct3(this.as_ref());
882    /// }
883    /// {
884    ///     let this= StrucWrapper(make_struct!{foo:Some(13), bar:21, baz:"34", quax:false});
885    ///     with_struct3(this.as_ref());
886    ///     // Because of the `.as_ref()`,`this` wasn't consumed
887    ///     with_struct3(this.as_ref());
888    /// }
889    ///
890    /// // The `Struct3_SI` trait was declared for Struct3 by the Structural derive macro,
891    /// // aliasing its accessor trait impls
892    /// //
893    /// // Also, notice how this also requires `Copy`,even though Struct3 doesn't implement it?
894    /// // The call with Struct3 works because of the `.as_ref()`,
895    /// // since `&` always implements `Copy`.
896    /// fn with_struct3(this: StrucWrapper<impl Struct3_SI<u8, u16, &'static str> + Copy>){
897    ///     assert_eq!( this.r(fp!(foo?)), Some(&13) );
898    ///     assert_eq!( this.r(fp!(bar)), &21 );
899    ///     assert_eq!( this.r(fp!(baz)), &"34" );
900    /// }
901    ///     
902    /// #[derive(Structural, Debug)]
903    /// // With this attribute, you can only access fields by shared reference.
904    /// #[struc(access="ref")]
905    /// pub struct Struct3<A, B, C> {
906    ///     pub foo: Option<A>,
907    ///     pub bar: B,
908    ///     pub baz: C,
909    /// }
910    ///
911    /// ```
912    #[inline(always)]
913    pub fn as_ref(&self) -> StrucWrapper<&T> {
914        StrucWrapper(&self.0)
915    }
916
917    /// Turns a `&mut StrucWrapper<T>` into a `StrucWrapper<&mut T>`.
918    /// Turns a `&StrucWrapper<T>` into a `StrucWrapper<&T>`.
919    ///
920    /// # Example
921    ///
922    /// ```rust
923    /// use structural::{Structural, StrucWrapper, fp, make_struct};
924    ///
925    /// {
926    ///     let mut this= StrucWrapper(Struct3{foo:Some(13), bar:21, baz:"34"});
927    ///     with_struct3(this.as_mut());
928    ///     // Because of the `.as_mut()`,`this` wasn't consumed
929    ///     with_struct3(this.as_mut());
930    /// }
931    /// {
932    ///     let mut this= StrucWrapper(make_struct!{foo:Some(13), bar:21, baz:"34", quax:false});
933    ///     with_struct3(this.as_mut());
934    ///     // Because of the `.as_mut()`,`this` wasn't consumed
935    ///     with_struct3(this.as_mut());
936    /// }
937    ///
938    /// // The `Struct3_SI` trait was declared for Struct3 by the Structural derive macro,
939    /// // aliasing its accessor trait impls
940    /// fn with_struct3(mut this: StrucWrapper<impl Struct3_SI<u8, u16, &'static str>>){
941    ///     assert_eq!( this.r(fp!(foo?)), Some(&13) );
942    ///     assert_eq!( this.r(fp!(bar)), &21 );
943    ///     assert_eq!( this.r(fp!(baz)), &"34" );
944    ///
945    ///     assert_eq!( this.m(fp!(foo?)), Some(&mut 13) );
946    ///     assert_eq!( this.m(fp!(bar)), &mut 21 );
947    ///     assert_eq!( this.m(fp!(baz)), &mut "34" );
948    /// }
949    ///     
950    /// #[derive(Structural, Debug)]
951    /// // With this attribute, you can only access fields by shared or mutable reference.
952    /// #[struc(access="mut")]
953    /// pub struct Struct3<A, B, C> {
954    ///     pub foo: Option<A>,
955    ///     pub bar: B,
956    ///     pub baz: C,
957    /// }
958    ///
959    /// ```
960    #[inline(always)]
961    pub fn as_mut(&mut self) -> StrucWrapper<&mut T> {
962        StrucWrapper(&mut self.0)
963    }
964
965    /// Transforms the wrapped value with the `func` function.
966    ///
967    #[inline(always)]
968    pub fn map<F, U>(self, f: F) -> StrucWrapper<U>
969    where
970        F: FnOnce(T) -> U,
971    {
972        StrucWrapper(f(self.0))
973    }
974
975    /// Calls `func` with `self`,rewrapping its return value in a `StrucWrapper<U>`
976    ///
977    #[inline(always)]
978    pub fn then<F, U>(self, f: F) -> StrucWrapper<U>
979    where
980        F: FnOnce(Self) -> U,
981    {
982        StrucWrapper(f(self))
983    }
984}
985
986impl<T: Clone> StrucWrapper<&T> {
987    /// Maps the wrapped reference into a clone.
988    #[inline(always)]
989    pub fn cloned(self) -> StrucWrapper<T> {
990        StrucWrapper((*self.0).clone())
991    }
992}
993
994impl<T: Clone> StrucWrapper<&mut T> {
995    /// Maps the wrapped mutable reference into a clone.
996    #[inline(always)]
997    pub fn cloned(self) -> StrucWrapper<T> {
998        StrucWrapper((*self.0).clone())
999    }
1000}
1001
1002impl<'a, T> StrucWrapper<&'a T> {
1003    /// Turns a `StrucWrapper<&T>` into a `&StrucWrapper<T>`.
1004    ///
1005    /// Note that this only works if `T: Sized`,
1006    /// which means that you can't call this method on a `StrucWrapper<&dyn Trait>`.
1007    #[inline(always)]
1008    pub fn reref(self) -> &'a StrucWrapper<T> {
1009        // `Self` is a `#[repr(transparent)]` wrapper around `T`
1010        unsafe { &*(self.0 as *const T as *const StrucWrapper<T>) }
1011    }
1012}
1013
1014impl<'a, T> StrucWrapper<&'a mut T> {
1015    /// Turns a `StrucWrapper<&mut T>` into a `&mut StrucWrapper<T>`.
1016    ///
1017    /// Note that this only works if `T: Sized`,
1018    /// which means that you can't call this method on a `StrucWrapper<&mut dyn Trait>`.
1019    #[inline(always)]
1020    pub fn remut(self) -> &'a mut StrucWrapper<T> {
1021        // `Self` is a `#[repr(transparent)]` wrapper around `T`
1022        unsafe { &mut *(self.0 as *mut T as *mut StrucWrapper<T>) }
1023    }
1024}
1025
1026/// Gets a reference to a non-nested struct field
1027///
1028/// # Example
1029///
1030/// ```
1031/// use structural::{StrucWrapper, fp};
1032/// use structural::structural_aliases::Array4;
1033///
1034/// assertions(["hello","world","foo","bar"]);
1035/// assertions(["hello","world","foo","bar","baz"]);
1036///
1037/// assertions(("hello","world","foo","bar"));
1038/// assertions(("hello","world","foo","bar","baz"));
1039/// assertions(("hello","world","foo","bar","baz","qux"));
1040///
1041/// fn assertions(this: impl Array4<&'static str> ){
1042///     let this=StrucWrapper(this);
1043///
1044///     assert_eq!( this[fp!(1)], "world" );
1045///     assert_eq!( this[fp!(2)], "foo" );
1046///     assert_eq!( this[fp!(3)], "bar" );
1047/// }
1048///
1049/// ```
1050impl<F, T> Index<F> for StrucWrapper<T>
1051where
1052    T: GetField<F>,
1053{
1054    type Output = T::Ty;
1055
1056    #[inline(always)]
1057    fn index(&self, path: F) -> &T::Ty {
1058        self.0.get_field_(path)
1059    }
1060}
1061
1062/// Gets a mutable reference to a non-nested struct field
1063///
1064/// # Example
1065///
1066/// ```
1067/// use structural::{StructuralExt, StrucWrapper, fp, make_struct};
1068/// use structural::for_examples::{Struct3, Struct3_SI};
1069///
1070/// let mut this=Struct3{ foo:Some(33), bar:55, baz:77 };
1071/// let mut anon=make_struct!{ foo:Some(0), bar:0, baz:0, extra:"extra" };
1072///
1073/// fn mutator(this:&mut impl Struct3_SI<u32,u32,u32>){
1074///     let mut this=StrucWrapper(this);
1075///     
1076///     this[fp!(bar)]+=20;
1077///     this[fp!(baz)]+=30;
1078/// }
1079///
1080/// mutator(&mut this);
1081/// mutator(&mut anon);
1082///
1083/// assert_eq!( this.cloned_fields(fp!(foo, bar, baz)), (Some(33), 75, 107) );
1084/// assert_eq!( anon.cloned_fields(fp!(foo, bar, baz, extra)), (Some(0), 20, 30, "extra") );
1085///
1086/// ```
1087impl<F, T> IndexMut<F> for StrucWrapper<T>
1088where
1089    T: GetFieldMut<F>,
1090{
1091    #[inline(always)]
1092    fn index_mut(&mut self, path: F) -> &mut T::Ty {
1093        self.0.get_field_mut_(path)
1094    }
1095}
1096
1097impl<T> ConstDefault for StrucWrapper<T>
1098where
1099    T: ConstDefault,
1100{
1101    const DEFAULT: Self = StrucWrapper(T::DEFAULT);
1102}
1103
1104unsafe_delegate_structural_with! {
1105    impl[T,] StrucWrapper<T>
1106    where[]
1107
1108    self_ident=this;
1109    specialization_params(Sized);
1110    delegating_to_type=T;
1111
1112    GetField { &this.0 }
1113
1114    GetFieldMut{
1115        &mut this.0
1116    }
1117    as_delegating_raw{
1118        this as *mut T
1119    }
1120
1121    IntoField{
1122        this.0
1123    }
1124    move_out_field{
1125        &mut this.0
1126    }
1127
1128    DropFields = { dropped_fields[] }
1129
1130    FromStructural {
1131        constructor = StrucWrapper;
1132    }
1133}