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}