@@ -1676,12 +1676,55 @@ impl<'a> TraitDef<'a> {
1676
1676
1677
1677
// helpful premade recipes
1678
1678
1679
+ pub fn cs_fold_fields < ' a , F > ( use_foldl : bool ,
1680
+ mut f : F ,
1681
+ base : P < Expr > ,
1682
+ cx : & mut ExtCtxt ,
1683
+ all_fields : & [ FieldInfo < ' a > ] )
1684
+ -> P < Expr >
1685
+ where F : FnMut ( & mut ExtCtxt , Span , P < Expr > , P < Expr > , & [ P < Expr > ] ) -> P < Expr >
1686
+ {
1687
+ if use_foldl {
1688
+ all_fields. iter ( ) . fold ( base, |old, field| {
1689
+ f ( cx, field. span , old, field. self_ . clone ( ) , & field. other )
1690
+ } )
1691
+ } else {
1692
+ all_fields. iter ( ) . rev ( ) . fold ( base, |old, field| {
1693
+ f ( cx, field. span , old, field. self_ . clone ( ) , & field. other )
1694
+ } )
1695
+ }
1696
+ }
1697
+
1698
+ pub fn cs_fold_enumnonmatch ( mut enum_nonmatch_f : EnumNonMatchCollapsedFunc ,
1699
+ cx : & mut ExtCtxt ,
1700
+ trait_span : Span ,
1701
+ substructure : & Substructure )
1702
+ -> P < Expr >
1703
+ {
1704
+ match * substructure. fields {
1705
+ EnumNonMatchingCollapsed ( ref all_args, _, tuple) => {
1706
+ enum_nonmatch_f ( cx,
1707
+ trait_span,
1708
+ ( & all_args[ ..] , tuple) ,
1709
+ substructure. nonself_args )
1710
+ }
1711
+ _ => cx. span_bug ( trait_span, "cs_fold_enumnonmatch expected an EnumNonMatchingCollapsed" )
1712
+ }
1713
+ }
1714
+
1715
+ pub fn cs_fold_static ( cx : & mut ExtCtxt ,
1716
+ trait_span : Span )
1717
+ -> P < Expr >
1718
+ {
1719
+ cx. span_bug ( trait_span, "static function in `derive`" )
1720
+ }
1721
+
1679
1722
/// Fold the fields. `use_foldl` controls whether this is done
1680
1723
/// left-to-right (`true`) or right-to-left (`false`).
1681
1724
pub fn cs_fold < F > ( use_foldl : bool ,
1682
- mut f : F ,
1725
+ f : F ,
1683
1726
base : P < Expr > ,
1684
- mut enum_nonmatch_f : EnumNonMatchCollapsedFunc ,
1727
+ enum_nonmatch_f : EnumNonMatchCollapsedFunc ,
1685
1728
cx : & mut ExtCtxt ,
1686
1729
trait_span : Span ,
1687
1730
substructure : & Substructure )
@@ -1691,26 +1734,58 @@ pub fn cs_fold<F>(use_foldl: bool,
1691
1734
match * substructure. fields {
1692
1735
EnumMatching ( .., ref all_fields) |
1693
1736
Struct ( _, ref all_fields) => {
1694
- if use_foldl {
1695
- all_fields. iter ( ) . fold ( base, |old, field| {
1696
- f ( cx, field. span , old, field. self_ . clone ( ) , & field. other )
1697
- } )
1698
- } else {
1699
- all_fields. iter ( ) . rev ( ) . fold ( base, |old, field| {
1700
- f ( cx, field. span , old, field. self_ . clone ( ) , & field. other )
1701
- } )
1702
- }
1737
+ cs_fold_fields ( use_foldl, f, base, cx, all_fields)
1703
1738
}
1704
- EnumNonMatchingCollapsed ( ref all_args , _ , tuple ) => {
1705
- enum_nonmatch_f ( cx,
1706
- trait_span ,
1707
- ( & all_args [ .. ] , tuple ) ,
1708
- substructure . nonself_args )
1739
+ EnumNonMatchingCollapsed ( .. ) => {
1740
+ cs_fold_enumnonmatch ( enum_nonmatch_f , cx, trait_span , substructure )
1741
+ }
1742
+ StaticEnum ( .. ) | StaticStruct ( .. ) => {
1743
+ cs_fold_static ( cx , trait_span )
1709
1744
}
1710
- StaticEnum ( ..) | StaticStruct ( ..) => cx. span_bug ( trait_span, "static function in `derive`" ) ,
1711
1745
}
1712
1746
}
1713
1747
1748
+ /// Special version of `cs_fold` that uses the result of a function call on the first field
1749
+ /// as the base case when is at least 1 field, and the usual base case when there are zero fields.
1750
+ pub fn cs_fold1 < F , B > ( use_foldl : bool ,
1751
+ f : F ,
1752
+ mut b : B ,
1753
+ enum_nonmatch_f : EnumNonMatchCollapsedFunc ,
1754
+ cx : & mut ExtCtxt ,
1755
+ trait_span : Span ,
1756
+ substructure : & Substructure )
1757
+ -> P < Expr >
1758
+ where F : FnMut ( & mut ExtCtxt , Span , P < Expr > , P < Expr > , & [ P < Expr > ] ) -> P < Expr > ,
1759
+ B : FnMut ( & mut ExtCtxt , Option < ( Span , P < Expr > , & [ P < Expr > ] ) > ) -> P < Expr >
1760
+ {
1761
+ match * substructure. fields {
1762
+ EnumMatching ( .., ref all_fields) |
1763
+ Struct ( _, ref all_fields) => {
1764
+ let ( base, all_fields) = match ( all_fields. is_empty ( ) , use_foldl) {
1765
+ ( false , true ) => {
1766
+ let field = & all_fields[ 0 ] ;
1767
+ let args = ( field. span , field. self_ . clone ( ) , & field. other [ ..] ) ;
1768
+ ( b ( cx, Some ( args) ) , & all_fields[ 1 ..] )
1769
+ }
1770
+ ( false , false ) => {
1771
+ let idx = all_fields. len ( ) - 1 ;
1772
+ let field = & all_fields[ idx] ;
1773
+ let args = ( field. span , field. self_ . clone ( ) , & field. other [ ..] ) ;
1774
+ ( b ( cx, Some ( args) ) , & all_fields[ ..idx] )
1775
+ }
1776
+ ( true , _) => ( b ( cx, None ) , & all_fields[ ..] )
1777
+ } ;
1778
+
1779
+ cs_fold_fields ( use_foldl, f, base, cx, all_fields)
1780
+ }
1781
+ EnumNonMatchingCollapsed ( ..) => {
1782
+ cs_fold_enumnonmatch ( enum_nonmatch_f, cx, trait_span, substructure)
1783
+ }
1784
+ StaticEnum ( ..) | StaticStruct ( ..) => {
1785
+ cs_fold_static ( cx, trait_span)
1786
+ }
1787
+ }
1788
+ }
1714
1789
1715
1790
/// Call the method that is being derived on all the fields, and then
1716
1791
/// process the collected results. i.e.
0 commit comments