1- use  std:: ops:: ControlFlow ; 
1+ use  std:: ops:: { ControlFlow ,   RangeInclusive } ; 
22
33use  super :: { Byte ,  Def ,  Ref } ; 
44
3232Byte ( Byte ) , 
3333} 
3434
35+ #[ derive( Debug ,  Copy ,  Clone ,  Eq ,  PartialEq ) ]  
36+ pub ( crate )  enum  Endian  { 
37+     Little , 
38+     Big , 
39+ } 
40+ 
41+ #[ cfg( feature = "rustc" ) ]  
42+ impl  From < rustc_abi:: Endian >  for  Endian  { 
43+     fn  from ( order :  rustc_abi:: Endian )  -> Endian  { 
44+         match  order { 
45+             rustc_abi:: Endian :: Little  => Endian :: Little , 
46+             rustc_abi:: Endian :: Big  => Endian :: Big , 
47+         } 
48+     } 
49+ } 
50+ 
3551impl < D ,  R >  Tree < D ,  R > 
3652where 
3753    D :  Def , 
@@ -59,22 +75,60 @@ where
5975
6076    /// A `Tree` representing the layout of `bool`. 
6177pub ( crate )  fn  bool ( )  -> Self  { 
62-         Self :: Byte ( Byte :: new ( 0x00 ..=0x01 ) ) 
78+         Self :: byte ( 0x00 ..=0x01 ) 
6379    } 
6480
6581    /// A `Tree` whose layout matches that of a `u8`. 
6682pub ( crate )  fn  u8 ( )  -> Self  { 
67-         Self :: Byte ( Byte :: new ( 0x00 ..=0xFF ) ) 
83+         Self :: byte ( 0x00 ..=0xFF ) 
84+     } 
85+ 
86+     /// A `Tree` whose layout matches that of a `char`. 
87+ pub ( crate )  fn  char ( order :  Endian )  -> Self  { 
88+         // `char`s can be in the following ranges: 
89+         // - [0, 0xD7FF] 
90+         // - [0xE000, 10FFFF] 
91+         // 
92+         // All other `char` values are illegal. We can thus represent a `char` 
93+         // as a union of three possible layouts: 
94+         // - 00 00 [00, D7] XX 
95+         // - 00 00 [E0, FF] XX 
96+         // - 00 [01, 10] XX XX 
97+ 
98+         const  _0:  RangeInclusive < u8 >  = 0 ..=0 ; 
99+         const  BYTE :  RangeInclusive < u8 >  = 0x00 ..=0xFF ; 
100+         let  x = Self :: from_big_endian ( order,  [ _0,  _0,  0x00 ..=0xD7 ,  BYTE ] ) ; 
101+         let  y = Self :: from_big_endian ( order,  [ _0,  _0,  0xE0 ..=0xFF ,  BYTE ] ) ; 
102+         let  z = Self :: from_big_endian ( order,  [ _0,  0x01 ..=0x10 ,  BYTE ,  BYTE ] ) ; 
103+         Self :: alt ( [ x,  y,  z] ) 
68104    } 
69105
70-     /// A `Tree` whose layout accepts exactly the given bit pattern. 
71- pub ( crate )  fn  from_bits ( bits :  u8 )  -> Self  { 
72-         Self :: Byte ( Byte :: from_val ( bits) ) 
106+     /// A `Tree` whose layout matches `std::num::NonZeroXxx`. 
107+ #[ allow( dead_code) ]  
108+     pub ( crate )  fn  nonzero ( width_in_bytes :  u64 )  -> Self  { 
109+         const  BYTE :  RangeInclusive < u8 >  = 0x00 ..=0xFF ; 
110+         const  NONZERO :  RangeInclusive < u8 >  = 0x01 ..=0xFF ; 
111+ 
112+         ( 0 ..width_in_bytes) 
113+             . map ( |nz_idx| { 
114+                 ( 0 ..width_in_bytes) 
115+                     . map ( |pos| Self :: byte ( if  pos == nz_idx {  NONZERO  }  else  {  BYTE  } ) ) 
116+                     . fold ( Self :: unit ( ) ,  Self :: then) 
117+             } ) 
118+             . fold ( Self :: uninhabited ( ) ,  Self :: or) 
119+     } 
120+ 
121+     pub ( crate )  fn  bytes < const  N :  usize ,  B :  Into < Byte > > ( bytes :  [ B ;  N ] )  -> Self  { 
122+         Self :: seq ( bytes. map ( B :: into) . map ( Self :: Byte ) ) 
123+     } 
124+ 
125+     pub ( crate )  fn  byte ( byte :  impl  Into < Byte > )  -> Self  { 
126+         Self :: Byte ( byte. into ( ) ) 
73127    } 
74128
75129    /// A `Tree` whose layout is a number of the given width. 
76- pub ( crate )  fn  number ( width_in_bytes :  usize )  -> Self  { 
77-         Self :: Seq ( vec ! [ Self :: u8 ( ) ;  width_in_bytes] ) 
130+ pub ( crate )  fn  number ( width_in_bytes :  u64 )  -> Self  { 
131+         Self :: Seq ( vec ! [ Self :: u8 ( ) ;  width_in_bytes. try_into ( ) . unwrap ( ) ] ) 
78132    } 
79133
80134    /// A `Tree` whose layout is entirely padding of the given width. 
@@ -125,13 +179,35 @@ where
125179            Self :: Byte ( ..)  | Self :: Ref ( ..)  | Self :: Def ( ..)  => true , 
126180        } 
127181    } 
128- } 
129182
130- impl < D ,  R >  Tree < D ,  R > 
131- where 
132-     D :  Def , 
133-     R :  Ref , 
134- { 
183+     /// Produces a `Tree` which represents a sequence of bytes stored in 
184+ /// `order`. 
185+ /// 
186+ /// `bytes` is taken to be in big-endian byte order, and its order will be 
187+ /// swapped if `order == Endian::Little`. 
188+ pub ( crate )  fn  from_big_endian < const  N :  usize ,  B :  Into < Byte > > ( 
189+         order :  Endian , 
190+         mut  bytes :  [ B ;  N ] , 
191+     )  -> Self  { 
192+         if  order == Endian :: Little  { 
193+             ( & mut  bytes[ ..] ) . reverse ( ) ; 
194+         } 
195+ 
196+         Self :: bytes ( bytes) 
197+     } 
198+ 
199+     /// Produces a `Tree` where each of the trees in `trees` are sequenced one 
200+ /// after another. 
201+ pub ( crate )  fn  seq < const  N :  usize > ( trees :  [ Tree < D ,  R > ;  N ] )  -> Self  { 
202+         trees. into_iter ( ) . fold ( Tree :: unit ( ) ,  Self :: then) 
203+     } 
204+ 
205+     /// Produces a `Tree` where each of the trees in `trees` are accepted as 
206+ /// alternative layouts. 
207+ pub ( crate )  fn  alt < const  N :  usize > ( trees :  [ Tree < D ,  R > ;  N ] )  -> Self  { 
208+         trees. into_iter ( ) . fold ( Tree :: uninhabited ( ) ,  Self :: or) 
209+     } 
210+ 
135211    /// Produces a new `Tree` where `other` is sequenced after `self`. 
136212pub ( crate )  fn  then ( self ,  other :  Self )  -> Self  { 
137213        match  ( self ,  other)  { 
@@ -222,17 +298,17 @@ pub(crate) mod rustc {
222298
223299                ty:: Float ( nty)  => { 
224300                    let  width = nty. bit_width ( )  / 8 ; 
225-                     Ok ( Self :: number ( width  as   _ ) ) 
301+                     Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) ) 
226302                } 
227303
228304                ty:: Int ( nty)  => { 
229305                    let  width = nty. normalize ( pointer_size. bits ( )  as  _ ) . bit_width ( ) . unwrap ( )  / 8 ; 
230-                     Ok ( Self :: number ( width  as   _ ) ) 
306+                     Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) ) 
231307                } 
232308
233309                ty:: Uint ( nty)  => { 
234310                    let  width = nty. normalize ( pointer_size. bits ( )  as  _ ) . bit_width ( ) . unwrap ( )  / 8 ; 
235-                     Ok ( Self :: number ( width  as   _ ) ) 
311+                     Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) ) 
236312                } 
237313
238314                ty:: Tuple ( members)  => Self :: from_tuple ( ( ty,  layout) ,  members,  cx) , 
@@ -249,11 +325,33 @@ pub(crate) mod rustc {
249325                        . fold ( Tree :: unit ( ) ,  |tree,  elt| tree. then ( elt) ) ) 
250326                } 
251327
252-                 ty:: Adt ( adt_def,  _args_ref)  if  !ty. is_box ( )  => match  adt_def. adt_kind ( )  { 
253-                     AdtKind :: Struct  => Self :: from_struct ( ( ty,  layout) ,  * adt_def,  cx) , 
254-                     AdtKind :: Enum  => Self :: from_enum ( ( ty,  layout) ,  * adt_def,  cx) , 
255-                     AdtKind :: Union  => Self :: from_union ( ( ty,  layout) ,  * adt_def,  cx) , 
256-                 } , 
328+                 ty:: Adt ( adt_def,  _args_ref)  if  !ty. is_box ( )  => { 
329+                     let  ( lo,  hi)  = cx. tcx ( ) . layout_scalar_valid_range ( adt_def. did ( ) ) ; 
330+ 
331+                     use  core:: ops:: Bound :: * ; 
332+                     let  is_transparent = adt_def. repr ( ) . transparent ( ) ; 
333+                     match  ( adt_def. adt_kind ( ) ,  lo,  hi)  { 
334+                         ( AdtKind :: Struct ,  Unbounded ,  Unbounded )  => { 
335+                             Self :: from_struct ( ( ty,  layout) ,  * adt_def,  cx) 
336+                         } 
337+                         ( AdtKind :: Struct ,  Included ( 1 ) ,  Included ( _hi) )  if  is_transparent => { 
338+                             // FIXME(@joshlf): Support `NonZero` types: 
339+                             // - Check to make sure that the first field is 
340+                             //   numerical 
341+                             // - Check to make sure that the upper bound is the 
342+                             //   maximum value for the field's type 
343+                             // - Construct `Self::nonzero` 
344+                             Err ( Err :: NotYetSupported ) 
345+                         } 
346+                         ( AdtKind :: Enum ,  Unbounded ,  Unbounded )  => { 
347+                             Self :: from_enum ( ( ty,  layout) ,  * adt_def,  cx) 
348+                         } 
349+                         ( AdtKind :: Union ,  Unbounded ,  Unbounded )  => { 
350+                             Self :: from_union ( ( ty,  layout) ,  * adt_def,  cx) 
351+                         } 
352+                         _ => Err ( Err :: NotYetSupported ) , 
353+                     } 
354+                 } 
257355
258356                ty:: Ref ( lifetime,  ty,  mutability)  => { 
259357                    let  layout = layout_of ( cx,  * ty) ?; 
@@ -268,6 +366,8 @@ pub(crate) mod rustc {
268366                    } ) ) 
269367                } 
270368
369+                 ty:: Char  => Ok ( Self :: char ( cx. tcx ( ) . data_layout . endian . into ( ) ) ) , 
370+ 
271371                _ => Err ( Err :: NotYetSupported ) , 
272372            } 
273373        } 
@@ -450,7 +550,7 @@ pub(crate) mod rustc {
450550                    & bytes[ bytes. len ( )  - size. bytes_usize ( ) ..] 
451551                } 
452552            } ; 
453-             Self :: Seq ( bytes. iter ( ) . map ( |& b| Self :: from_bits ( b) ) . collect ( ) ) 
553+             Self :: Seq ( bytes. iter ( ) . map ( |& b| Self :: byte ( b) ) . collect ( ) ) 
454554        } 
455555
456556        /// Constructs a `Tree` from a union. 
0 commit comments