1use crate::hlist::*;
151use crate::indices::*;
152use crate::traits::ToRef;
153#[cfg(feature = "serde")]
154use serde::{Deserialize, Serialize};
155
156use core::fmt;
157use core::marker::PhantomData;
158
159pub trait LabelledGeneric {
199 type Repr;
201
202 fn into(self) -> Self::Repr;
204
205 fn from(repr: Self::Repr) -> Self;
208
209 #[inline(always)]
212 fn convert_from<Src>(src: Src) -> Self
213 where
214 Src: LabelledGeneric<Repr = Self::Repr>,
215 Self: Sized,
216 {
217 let repr = <Src as LabelledGeneric>::into(src);
218 <Self as LabelledGeneric>::from(repr)
219 }
220
221 #[deprecated(note = "obsolete, transform_from instead")]
227 fn sculpted_convert_from<A, Indices>(a: A) -> Self
228 where
229 A: LabelledGeneric,
230 Self: Sized,
231 <A as LabelledGeneric>::Repr: Sculptor<<Self as LabelledGeneric>::Repr, Indices>,
233 {
234 <Self as LabelledGeneric>::transform_from(a)
235 }
236
237 #[inline(always)]
245 fn transform_from<Src, Indices>(src: Src) -> Self
246 where
247 Src: LabelledGeneric,
248 Self: Sized,
249 <Src as LabelledGeneric>::Repr: Sculptor<<Self as LabelledGeneric>::Repr, Indices>,
251 {
252 let src_gen = <Src as LabelledGeneric>::into(src);
253 let (self_gen, _): (<Self as LabelledGeneric>::Repr, _) = src_gen.sculpt();
255 <Self as LabelledGeneric>::from(self_gen)
256 }
257}
258
259pub trait IntoLabelledGeneric {
260 type Repr;
262
263 fn into(self) -> Self::Repr;
265}
266
267impl<A> IntoLabelledGeneric for A
268where
269 A: LabelledGeneric,
270{
271 type Repr = <A as LabelledGeneric>::Repr;
272
273 #[inline(always)]
274 fn into(self) -> <Self as IntoLabelledGeneric>::Repr {
275 self.into()
276 }
277}
278
279pub fn from_labelled_generic<Dst, Repr>(repr: Repr) -> Dst
281where
282 Dst: LabelledGeneric<Repr = Repr>,
283{
284 <Dst as LabelledGeneric>::from(repr)
285}
286
287pub fn into_labelled_generic<Src, Repr>(src: Src) -> Repr
289where
290 Src: LabelledGeneric<Repr = Repr>,
291{
292 <Src as LabelledGeneric>::into(src)
293}
294
295pub fn labelled_convert_from<Src, Dst, Repr>(src: Src) -> Dst
298where
299 Src: LabelledGeneric<Repr = Repr>,
300 Dst: LabelledGeneric<Repr = Repr>,
301{
302 <Dst as LabelledGeneric>::convert_from(src)
303}
304
305#[deprecated(note = "obsolete, transform_from instead")]
311pub fn sculpted_convert_from<A, B, Indices>(a: A) -> B
312where
313 A: LabelledGeneric,
314 B: LabelledGeneric,
315 <A as LabelledGeneric>::Repr: Sculptor<<B as LabelledGeneric>::Repr, Indices>,
317{
318 <B as LabelledGeneric>::transform_from(a)
319}
320pub fn transform_from<Src, Dst, Indices>(src: Src) -> Dst
326where
327 Src: LabelledGeneric,
328 Dst: LabelledGeneric,
329 <Src as LabelledGeneric>::Repr: Sculptor<<Dst as LabelledGeneric>::Repr, Indices>,
331{
332 <Dst as LabelledGeneric>::transform_from(src)
333}
334
335pub mod chars {
336 macro_rules! create_enums_for {
349 ($($i: ident)*) => {
350 $(
351 #[allow(non_snake_case, non_camel_case_types)]
352 #[derive(PartialEq, Debug, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
353 pub enum $i {}
354 )*
355 }
356 }
357
358 create_enums_for! {
360 a b c d e f g h i j k l m n o p q r s t u v w x y z
362 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
363 _1 _2 _3 _4 _5 _6 _7 _8 _9 _0 __ _uc uc_
364 }
365
366 #[test]
367 fn simple_var_names_are_allowed() {
368 let a = 3;
373 #[allow(clippy::match_single_binding)]
374 match a {
375 a => assert_eq!(a, 3),
376 }
377 }
378}
379
380#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
397#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
398pub struct Field<Name, Type> {
399 name_type_holder: PhantomData<Name>,
400 pub name: &'static str,
401 pub value: Type,
402}
403
404#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
407#[derive(PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
408pub struct ValueField<Type> {
409 pub name: &'static str,
410 pub value: Type,
411}
412
413impl<Name, Type> fmt::Debug for Field<Name, Type>
414where
415 Type: fmt::Debug,
416{
417 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
418 f.debug_struct("Field")
419 .field("name", &DebugAsDisplay(&self.name))
421 .field("value", &self.value)
422 .finish()
423 }
424}
425
426impl<Type> fmt::Debug for ValueField<Type>
427where
428 Type: fmt::Debug,
429{
430 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
431 f.debug_struct("ValueField")
432 .field("name", &DebugAsDisplay(&self.name))
434 .field("value", &self.value)
435 .finish()
436 }
437}
438
439struct DebugAsDisplay<T>(T);
441
442impl<T: fmt::Display> fmt::Debug for DebugAsDisplay<T> {
443 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
444 fmt::Display::fmt(&self.0, f)
445 }
446}
447
448pub fn field_with_name<Label, Value>(name: &'static str, value: Value) -> Field<Label, Value> {
464 Field {
465 name_type_holder: PhantomData,
466 name,
467 value,
468 }
469}
470
471pub trait IntoUnlabelled {
473 type Output;
474
475 fn into_unlabelled(self) -> Self::Output;
498}
499
500impl IntoUnlabelled for HNil {
502 type Output = HNil;
503 fn into_unlabelled(self) -> Self::Output {
504 self
505 }
506}
507
508impl<Label, Value, Tail> IntoUnlabelled for HCons<Field<Label, Value>, Tail>
510where
511 Tail: IntoUnlabelled,
512{
513 type Output = HCons<Value, <Tail as IntoUnlabelled>::Output>;
514
515 fn into_unlabelled(self) -> Self::Output {
516 HCons {
517 head: self.head.value,
518 tail: self.tail.into_unlabelled(),
519 }
520 }
521}
522
523pub trait IntoValueLabelled {
525 type Output;
526
527 fn into_value_labelled(self) -> Self::Output;
562}
563
564impl IntoValueLabelled for HNil {
565 type Output = HNil;
566 fn into_value_labelled(self) -> Self::Output {
567 self
568 }
569}
570
571impl<Label, Value, Tail> IntoValueLabelled for HCons<Field<Label, Value>, Tail>
572where
573 Tail: IntoValueLabelled,
574{
575 type Output = HCons<ValueField<Value>, <Tail as IntoValueLabelled>::Output>;
576
577 fn into_value_labelled(self) -> Self::Output {
578 HCons {
579 head: ValueField {
580 name: self.head.name,
581 value: self.head.value,
582 },
583 tail: self.tail.into_value_labelled(),
584 }
585 }
586}
587
588pub trait ByNameFieldPlucker<TargetKey, Index> {
590 type TargetValue;
591 type Remainder;
592
593 fn pluck_by_name(self) -> (Field<TargetKey, Self::TargetValue>, Self::Remainder);
595}
596
597impl<K, V, Tail> ByNameFieldPlucker<K, Here> for HCons<Field<K, V>, Tail> {
599 type TargetValue = V;
600 type Remainder = Tail;
601
602 #[inline(always)]
603 fn pluck_by_name(self) -> (Field<K, Self::TargetValue>, Self::Remainder) {
604 let field = field_with_name(self.head.name, self.head.value);
605 (field, self.tail)
606 }
607}
608
609impl<Head, Tail, K, TailIndex> ByNameFieldPlucker<K, There<TailIndex>> for HCons<Head, Tail>
611where
612 Tail: ByNameFieldPlucker<K, TailIndex>,
613{
614 type TargetValue = <Tail as ByNameFieldPlucker<K, TailIndex>>::TargetValue;
615 type Remainder = HCons<Head, <Tail as ByNameFieldPlucker<K, TailIndex>>::Remainder>;
616
617 #[inline(always)]
618 fn pluck_by_name(self) -> (Field<K, Self::TargetValue>, Self::Remainder) {
619 let (target, tail_remainder) =
620 <Tail as ByNameFieldPlucker<K, TailIndex>>::pluck_by_name(self.tail);
621 (
622 target,
623 HCons {
624 head: self.head,
625 tail: tail_remainder,
626 },
627 )
628 }
629}
630
631impl<'a, K, V, Tail: ToRef<'a>> ByNameFieldPlucker<K, Here> for &'a HCons<Field<K, V>, Tail> {
633 type TargetValue = &'a V;
634 type Remainder = <Tail as ToRef<'a>>::Output;
635
636 #[inline(always)]
637 fn pluck_by_name(self) -> (Field<K, Self::TargetValue>, Self::Remainder) {
638 let field = field_with_name(self.head.name, &self.head.value);
639 (field, self.tail.to_ref())
640 }
641}
642
643impl<'a, Head, Tail, K, TailIndex> ByNameFieldPlucker<K, There<TailIndex>> for &'a HCons<Head, Tail>
645where
646 &'a Tail: ByNameFieldPlucker<K, TailIndex>,
647{
648 type TargetValue = <&'a Tail as ByNameFieldPlucker<K, TailIndex>>::TargetValue;
649 type Remainder = HCons<&'a Head, <&'a Tail as ByNameFieldPlucker<K, TailIndex>>::Remainder>;
650
651 #[inline(always)]
652 fn pluck_by_name(self) -> (Field<K, Self::TargetValue>, Self::Remainder) {
653 let (target, tail_remainder) =
654 <&'a Tail as ByNameFieldPlucker<K, TailIndex>>::pluck_by_name(&self.tail);
655 (
656 target,
657 HCons {
658 head: &self.head,
659 tail: tail_remainder,
660 },
661 )
662 }
663}
664
665pub trait Transmogrifier<Target, TransmogrifyIndexIndices> {
756 fn transmogrify(self) -> Target;
760}
761
762impl<Key, SourceValue> Transmogrifier<SourceValue, IdentityTransMog> for Field<Key, SourceValue> {
764 #[inline(always)]
765 fn transmogrify(self) -> SourceValue {
766 self.value
767 }
768}
769
770#[cfg(feature = "alloc")]
772mod _alloc {
773 use super::MappingIndicesWrapper;
774 use super::{Field, Transmogrifier};
775 use alloc::boxed::Box;
776 use alloc::collections::{LinkedList, VecDeque};
777 use alloc::vec::Vec;
778
779 macro_rules! transmogrify_seq {
780 ($container:ident) => {
781 impl<Key, Source, Target, InnerIndices>
784 Transmogrifier<$container<Target>, MappingIndicesWrapper<InnerIndices>>
785 for Field<Key, $container<Source>>
786 where
787 Source: Transmogrifier<Target, InnerIndices>,
788 {
789 fn transmogrify(self) -> $container<Target> {
790 self.value.into_iter().map(|e| e.transmogrify()).collect()
791 }
792 }
793 };
794 }
795
796 transmogrify_seq!(Vec);
797 transmogrify_seq!(LinkedList);
798 transmogrify_seq!(VecDeque);
799
800 impl<Key, Source, Target, InnerIndices>
803 Transmogrifier<Box<Target>, MappingIndicesWrapper<InnerIndices>> for Field<Key, Box<Source>>
804 where
805 Source: Transmogrifier<Target, InnerIndices>,
806 {
807 fn transmogrify(self) -> Box<Target> {
808 Box::new(self.value.transmogrify())
809 }
810 }
811}
812
813impl<Key, Source, Target, InnerIndices>
816 Transmogrifier<Option<Target>, MappingIndicesWrapper<InnerIndices>>
817 for Field<Key, Option<Source>>
818where
819 Source: Transmogrifier<Target, InnerIndices>,
820{
821 fn transmogrify(self) -> Option<Target> {
822 self.value.map(|e| e.transmogrify())
823 }
824}
825
826impl Transmogrifier<HNil, HNil> for HNil {
828 #[inline(always)]
829 fn transmogrify(self) -> HNil {
830 HNil
831 }
832}
833
834impl<SourceHead, SourceTail> Transmogrifier<HNil, HNil> for HCons<SourceHead, SourceTail> {
836 #[inline(always)]
837 fn transmogrify(self) -> HNil {
838 HNil
839 }
840}
841
842impl<
845 SourceHead,
846 SourceTail,
847 TargetName,
848 TargetHead,
849 TargetTail,
850 TransmogHeadIndex,
851 TransmogTailIndices,
852 > Transmogrifier<HCons<TargetHead, TargetTail>, HCons<TransmogHeadIndex, TransmogTailIndices>>
853 for Field<TargetName, HCons<SourceHead, SourceTail>>
854where
855 HCons<SourceHead, SourceTail>: Transmogrifier<
856 HCons<TargetHead, TargetTail>,
857 HCons<TransmogHeadIndex, TransmogTailIndices>,
858 >,
859{
860 #[inline(always)]
861 fn transmogrify(self) -> HCons<TargetHead, TargetTail> {
862 self.value.transmogrify()
863 }
864}
865
866impl<
870 SourceHead,
871 SourceTail,
872 TargetHeadName,
873 TargetHeadValue,
874 TargetTail,
875 PluckSourceHeadNameIndex,
876 TransMogSourceHeadValueIndices,
877 TransMogTailIndices,
878 >
879 Transmogrifier<
880 HCons<Field<TargetHeadName, TargetHeadValue>, TargetTail>,
881 HCons<
882 DoTransmog<PluckSourceHeadNameIndex, TransMogSourceHeadValueIndices>,
883 TransMogTailIndices,
884 >,
885 > for HCons<SourceHead, SourceTail>
886where
887 HCons<SourceHead, SourceTail>: ByNameFieldPlucker<TargetHeadName, PluckSourceHeadNameIndex>,
889 Field<
891 TargetHeadName,
892 <HCons<SourceHead, SourceTail> as ByNameFieldPlucker<
893 TargetHeadName,
894 PluckSourceHeadNameIndex,
895 >>::TargetValue,
896 >: Transmogrifier<TargetHeadValue, TransMogSourceHeadValueIndices>,
897 <HCons<SourceHead, SourceTail> as ByNameFieldPlucker<
900 TargetHeadName,
901 PluckSourceHeadNameIndex,
902 >>::Remainder: Transmogrifier<TargetTail, TransMogTailIndices>,
903{
904 #[inline(always)]
905 fn transmogrify(self) -> HCons<Field<TargetHeadName, TargetHeadValue>, TargetTail> {
906 let (source_field_for_head_target_name, remainder) = self.pluck_by_name();
907 let name = source_field_for_head_target_name.name;
908 let transmogrified_value: TargetHeadValue =
909 source_field_for_head_target_name.transmogrify();
910 let as_field: Field<TargetHeadName, TargetHeadValue> =
911 field_with_name(name, transmogrified_value);
912 HCons {
913 head: as_field,
914 tail: remainder.transmogrify(),
915 }
916 }
917}
918
919impl<Source, Target, TransmogIndices>
920 Transmogrifier<Target, LabelledGenericTransmogIndicesWrapper<TransmogIndices>> for Source
921where
922 Source: LabelledGeneric,
923 Target: LabelledGeneric,
924 <Source as LabelledGeneric>::Repr:
925 Transmogrifier<<Target as LabelledGeneric>::Repr, TransmogIndices>,
926{
927 #[inline(always)]
928 fn transmogrify(self) -> Target {
929 let source_as_repr = self.into();
930 let source_transmogged = source_as_repr.transmogrify();
931 <Target as LabelledGeneric>::from(source_transmogged)
932 }
933}
934
935impl<Source, TargetName, TargetValue, TransmogIndices>
937 Transmogrifier<TargetValue, PluckedLabelledGenericIndicesWrapper<TransmogIndices>>
938 for Field<TargetName, Source>
939where
940 Source: LabelledGeneric,
941 TargetValue: LabelledGeneric,
942 Source: Transmogrifier<TargetValue, TransmogIndices>,
943{
944 #[inline(always)]
945 fn transmogrify(self) -> TargetValue {
946 self.value.transmogrify()
947 }
948}
949
950#[cfg(test)]
951mod tests {
952 use super::chars::*;
953 use super::*;
954 use alloc::collections::{LinkedList, VecDeque};
955 use alloc::{boxed::Box, format, string::ToString, vec, vec::Vec};
956
957 #[allow(non_camel_case_types)]
959 type abc = (a, b, c);
960 #[allow(non_camel_case_types)]
961 type name = (n, a, m, e);
962 #[allow(non_camel_case_types)]
963 type age = (a, g, e);
964 #[allow(non_camel_case_types)]
965 type is_admin = (i, s, __, a, d, m, i, n);
966 #[allow(non_camel_case_types)]
967 type inner = (i, n, n, e, r);
968
969 #[test]
970 fn test_label_new_building() {
971 let l1 = field!(abc, 3);
972 assert_eq!(l1.value, 3);
973 assert_eq!(l1.name, "abc");
974 let l2 = field!((a, b, c), 3);
975 assert_eq!(l2.value, 3);
976 assert_eq!(l2.name, "abc");
977
978 let l3 = field!(abc, 3, "nope");
980 assert_eq!(l3.value, 3);
981 assert_eq!(l3.name, "nope");
982 let l4 = field!((a, b, c), 3, "nope");
983 assert_eq!(l4.value, 3);
984 assert_eq!(l4.name, "nope");
985 }
986
987 #[test]
988 fn test_field_construction() {
989 let f1 = field!(age, 3);
990 let f2 = field!((a, g, e), 3);
991 assert_eq!(f1, f2)
992 }
993
994 #[test]
995 fn test_field_debug() {
996 let field = field!(age, 3);
997 let hlist_pat![value_field] = hlist![field].into_value_labelled();
998
999 assert!(format!("{:?}", field).contains("name: age"));
1001 assert!(format!("{:?}", value_field).contains("name: age"));
1002 assert!(format!("{:#?}", field).contains('\n'));
1004 assert!(format!("{:#?}", value_field).contains('\n'));
1005 }
1006
1007 #[test]
1008 fn test_anonymous_record_usage() {
1009 let record = hlist![field!(name, "Joe"), field!((a, g, e), 30)];
1010 let (name, _): (Field<name, _>, _) = record.pluck();
1011 assert_eq!(name.value, "Joe")
1012 }
1013
1014 #[test]
1015 fn test_pluck_by_name() {
1016 let record = hlist![
1017 field!(is_admin, true),
1018 field!(name, "Joe".to_string()),
1019 field!((a, g, e), 30),
1020 ];
1021
1022 let (name, r): (Field<name, _>, _) = record.clone().pluck_by_name();
1023 assert_eq!(name.value, "Joe");
1024 assert_eq!(r, hlist![field!(is_admin, true), field!((a, g, e), 30),]);
1025 }
1026
1027 #[test]
1028 fn test_ref_pluck_by_name() {
1029 let record = &hlist![
1030 field!(is_admin, true),
1031 field!(name, "Joe".to_string()),
1032 field!((a, g, e), 30),
1033 ];
1034
1035 let (name, r): (Field<name, _>, _) = record.pluck_by_name();
1036 assert_eq!(name.value, "Joe");
1037 assert_eq!(r, hlist![&field!(is_admin, true), &field!((a, g, e), 30),]);
1038 }
1039
1040 #[test]
1041 fn test_unlabelling() {
1042 let labelled_hlist = hlist![field!(name, "joe"), field!((a, g, e), 3)];
1043 let unlabelled = labelled_hlist.into_unlabelled();
1044 assert_eq!(unlabelled, hlist!["joe", 3])
1045 }
1046
1047 #[test]
1048 fn test_value_labelling() {
1049 let labelled_hlist = hlist![field!(name, "joe"), field!((a, g, e), 3)];
1050 let value_labelled: HList![ValueField<&str>, ValueField<isize>] =
1051 labelled_hlist.into_value_labelled();
1052 let hlist_pat!(f1, f2) = value_labelled;
1053 assert_eq!(f1.name, "name");
1054 assert_eq!(f2.name, "age");
1055 }
1056
1057 #[test]
1058 fn test_name() {
1059 let labelled = field!(name, "joe");
1060 assert_eq!(labelled.name, "name")
1061 }
1062
1063 #[test]
1064 fn test_transmogrify_hnil_identity() {
1065 let hnil_again: HNil = HNil.transmogrify();
1066 assert_eq!(HNil, hnil_again);
1067 }
1068
1069 #[test]
1070 fn test_transmogrify_hcons_sculpting_super_simple() {
1071 type Source = HList![Field<name, &'static str>, Field<age, i32>, Field<is_admin, bool>];
1072 type Target = HList![Field<age, i32>];
1073 let hcons: Source = hlist!(field!(name, "joe"), field!(age, 3), field!(is_admin, true));
1074 let t_hcons: Target = hcons.transmogrify();
1075 assert_eq!(t_hcons, hlist!(field!(age, 3)));
1076 }
1077
1078 #[test]
1079 fn test_transmogrify_hcons_sculpting_somewhat_simple() {
1080 type Source = HList![Field<name, &'static str>, Field<age, i32>, Field<is_admin, bool>];
1081 type Target = HList![Field<is_admin, bool>, Field<name, &'static str>];
1082 let hcons: Source = hlist!(field!(name, "joe"), field!(age, 3), field!(is_admin, true));
1083 let t_hcons: Target = hcons.transmogrify();
1084 assert_eq!(t_hcons, hlist!(field!(is_admin, true), field!(name, "joe")));
1085 }
1086
1087 #[test]
1088 fn test_transmogrify_hcons_recursive_simple() {
1089 type Source = HList![
1090 Field<name, HList![
1091 Field<inner, f32>,
1092 Field<is_admin, bool>,
1093 ]>,
1094 Field<age, i32>,
1095 Field<is_admin, bool>];
1096 type Target = HList![
1097 Field<is_admin, bool>,
1098 Field<name, HList![
1099 Field<is_admin, bool>,
1100 ]>,
1101 ];
1102 let source: Source = hlist![
1103 field!(name, hlist![field!(inner, 42f32), field!(is_admin, true)]),
1104 field!(age, 32),
1105 field!(is_admin, true)
1106 ];
1107 let target: Target = source.transmogrify();
1108 assert_eq!(
1109 target,
1110 hlist![
1111 field!(is_admin, true),
1112 field!(name, hlist![field!(is_admin, true)]),
1113 ]
1114 )
1115 }
1116
1117 #[test]
1118 fn test_transmogrify_hcons_sculpting_required_simple() {
1119 type Source = HList![Field<name, &'static str>, Field<age, i32>, Field<is_admin, bool>];
1120 type Target = HList![Field<is_admin, bool>, Field<name, &'static str>, Field<age, i32>];
1121 let hcons: Source = hlist!(field!(name, "joe"), field!(age, 3), field!(is_admin, true));
1122 let t_hcons: Target = hcons.transmogrify();
1123 assert_eq!(
1124 t_hcons,
1125 hlist!(field!(is_admin, true), field!(name, "joe"), field!(age, 3))
1126 );
1127 }
1128
1129 #[test]
1130 fn test_transmogrify_identical_transform_labelled_fields() {
1131 type Source = HList![
1132 Field<name, &'static str>,
1133 Field<age, i32>,
1134 Field<is_admin, bool>
1135 ];
1136 type Target = Source;
1137 let source: Source = hlist![field!(name, "joe"), field!(age, 32), field!(is_admin, true)];
1138 let target: Target = source.transmogrify();
1139 assert_eq!(
1140 target,
1141 hlist![field!(name, "joe"), field!(age, 32), field!(is_admin, true)]
1142 )
1143 }
1144
1145 #[test]
1146 fn test_transmogrify_through_containers() {
1147 type SourceOuter<T> = HList![
1148 Field<name, &'static str>,
1149 Field<inner, T>,
1150 ];
1151 type SourceInner = HList![
1152 Field<is_admin, bool>,
1153 Field<age, i32>,
1154 ];
1155 type TargetOuter<T> = HList![
1156 Field<name, &'static str>,
1157 Field<inner, T>,
1158 ];
1159 type TargetInner = HList![
1160 Field<age, i32>,
1161 Field<is_admin, bool>,
1162 ];
1163
1164 fn create_inner() -> (SourceInner, TargetInner) {
1165 let source_inner: SourceInner = hlist![field!(is_admin, true), field!(age, 14)];
1166 let target_inner: TargetInner = hlist![field!(age, 14), field!(is_admin, true)];
1167 (source_inner, target_inner)
1168 }
1169
1170 let (source_inner, target_inner) = create_inner();
1172 let source: SourceOuter<Vec<SourceInner>> =
1173 hlist![field!(name, "Joe"), field!(inner, vec![source_inner])];
1174 let target: TargetOuter<Vec<TargetInner>> = source.transmogrify();
1175 assert_eq!(
1176 target,
1177 hlist![field!(name, "Joe"), field!(inner, vec![target_inner])]
1178 );
1179
1180 let (source_inner, target_inner) = create_inner();
1182 let source_inner = {
1183 let mut list = LinkedList::new();
1184 list.push_front(source_inner);
1185 list
1186 };
1187 let target_inner = {
1188 let mut list = LinkedList::new();
1189 list.push_front(target_inner);
1190 list
1191 };
1192 let source: SourceOuter<LinkedList<SourceInner>> =
1193 hlist![field!(name, "Joe"), field!(inner, source_inner)];
1194 let target: TargetOuter<LinkedList<TargetInner>> = source.transmogrify();
1195 assert_eq!(
1196 target,
1197 hlist![field!(name, "Joe"), field!(inner, target_inner)]
1198 );
1199
1200 let (source_inner, target_inner) = create_inner();
1202 let source_inner = {
1203 let mut list = VecDeque::new();
1204 list.push_front(source_inner);
1205 list
1206 };
1207 let target_inner = {
1208 let mut list = VecDeque::new();
1209 list.push_front(target_inner);
1210 list
1211 };
1212 let source: SourceOuter<VecDeque<SourceInner>> =
1213 hlist![field!(name, "Joe"), field!(inner, source_inner)];
1214 let target: TargetOuter<VecDeque<TargetInner>> = source.transmogrify();
1215 assert_eq!(
1216 target,
1217 hlist![field!(name, "Joe"), field!(inner, target_inner)]
1218 );
1219
1220 let (source_inner, target_inner) = create_inner();
1222 let source_inner = Some(source_inner);
1223 let target_inner = Some(target_inner);
1224 let source: SourceOuter<Option<SourceInner>> =
1225 hlist![field!(name, "Joe"), field!(inner, source_inner)];
1226 let target: TargetOuter<Option<TargetInner>> = source.transmogrify();
1227 assert_eq!(
1228 target,
1229 hlist![field!(name, "Joe"), field!(inner, target_inner)]
1230 );
1231 let source: SourceOuter<Option<SourceInner>> =
1232 hlist![field!(name, "Joe"), field!(inner, None)];
1233 let target: TargetOuter<Option<TargetInner>> = source.transmogrify();
1234 assert_eq!(target, hlist![field!(name, "Joe"), field!(inner, None)]);
1235
1236 let (source_inner, target_inner) = create_inner();
1238 let source_inner = Box::new(source_inner);
1239 let target_inner = Box::new(target_inner);
1240 let source: SourceOuter<Box<SourceInner>> =
1241 hlist![field!(name, "Joe"), field!(inner, source_inner)];
1242 let target: TargetOuter<Box<TargetInner>> = source.transmogrify();
1243 assert_eq!(
1244 target,
1245 hlist![field!(name, "Joe"), field!(inner, target_inner)]
1246 );
1247 }
1248
1249 }