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,62 @@ 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 ) 
6884    } 
6985
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) ) 
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+         // OverB(B) = 0xD800, 
101+         // UnderC(C) = 0xDFFF, 
102+         let  x = Self :: from_big_endian ( order,  [ _0,  _0,  0x00 ..=0xD7 ,  BYTE ] ) ; 
103+         let  y = Self :: from_big_endian ( order,  [ _0,  _0,  0xE0 ..=0xFF ,  BYTE ] ) ; 
104+         let  z = Self :: from_big_endian ( order,  [ _0,  0x01 ..=0x10 ,  BYTE ,  BYTE ] ) ; 
105+         Self :: alt ( [ x,  y,  z] ) 
106+     } 
107+ 
108+     /// A `Tree` whose layout matches `std::num::NonZeroXxx`. 
109+ #[ allow( dead_code) ]  
110+     pub ( crate )  fn  nonzero ( width_in_bytes :  u64 )  -> Self  { 
111+         const  BYTE :  RangeInclusive < u8 >  = 0x00 ..=0xFF ; 
112+         const  NONZERO :  RangeInclusive < u8 >  = 0x01 ..=0xFF ; 
113+ 
114+         ( 0 ..width_in_bytes) 
115+             . map ( |nz_idx| { 
116+                 ( 0 ..width_in_bytes) 
117+                     . map ( |pos| Self :: byte ( if  pos == nz_idx {  NONZERO  }  else  {  BYTE  } ) ) 
118+                     . fold ( Self :: unit ( ) ,  Self :: then) 
119+             } ) 
120+             . fold ( Self :: uninhabited ( ) ,  Self :: or) 
121+     } 
122+ 
123+     pub ( crate )  fn  bytes < const  N :  usize ,  B :  Into < Byte > > ( bytes :  [ B ;  N ] )  -> Self  { 
124+         Self :: seq ( bytes. map ( B :: into) . map ( Self :: Byte ) ) 
125+     } 
126+ 
127+     pub ( crate )  fn  byte ( byte :  impl  Into < Byte > )  -> Self  { 
128+         Self :: Byte ( byte. into ( ) ) 
73129    } 
74130
75131    /// 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] ) 
132+ pub ( crate )  fn  number ( width_in_bytes :  u64 )  -> Self  { 
133+         Self :: Seq ( vec ! [ Self :: u8 ( ) ;  width_in_bytes. try_into ( ) . unwrap ( ) ] ) 
78134    } 
79135
80136    /// A `Tree` whose layout is entirely padding of the given width. 
@@ -125,13 +181,35 @@ where
125181            Self :: Byte ( ..)  | Self :: Ref ( ..)  | Self :: Def ( ..)  => true , 
126182        } 
127183    } 
128- } 
129184
130- impl < D ,  R >  Tree < D ,  R > 
131- where 
132-     D :  Def , 
133-     R :  Ref , 
134- { 
185+     /// Produces a `Tree` which represents a sequence of bytes stored in 
186+ /// `order`. 
187+ /// 
188+ /// `bytes` is taken to be in big-endian byte order, and its order will be 
189+ /// swapped if `order == Endian::Little`. 
190+ pub ( crate )  fn  from_big_endian < const  N :  usize ,  B :  Into < Byte > > ( 
191+         order :  Endian , 
192+         mut  bytes :  [ B ;  N ] , 
193+     )  -> Self  { 
194+         if  order == Endian :: Little  { 
195+             ( & mut  bytes[ ..] ) . reverse ( ) ; 
196+         } 
197+ 
198+         Self :: bytes ( bytes) 
199+     } 
200+ 
201+     /// Produces a `Tree` where each of the trees in `trees` are sequenced one 
202+ /// after another. 
203+ pub ( crate )  fn  seq < const  N :  usize > ( trees :  [ Tree < D ,  R > ;  N ] )  -> Self  { 
204+         trees. into_iter ( ) . fold ( Tree :: unit ( ) ,  Self :: then) 
205+     } 
206+ 
207+     /// Produces a `Tree` where each of the trees in `trees` are accepted as 
208+ /// alternative layouts. 
209+ pub ( crate )  fn  alt < const  N :  usize > ( trees :  [ Tree < D ,  R > ;  N ] )  -> Self  { 
210+         trees. into_iter ( ) . fold ( Tree :: uninhabited ( ) ,  Self :: or) 
211+     } 
212+ 
135213    /// Produces a new `Tree` where `other` is sequenced after `self`. 
136214pub ( crate )  fn  then ( self ,  other :  Self )  -> Self  { 
137215        match  ( self ,  other)  { 
@@ -222,17 +300,17 @@ pub(crate) mod rustc {
222300
223301                ty:: Float ( nty)  => { 
224302                    let  width = nty. bit_width ( )  / 8 ; 
225-                     Ok ( Self :: number ( width  as   _ ) ) 
303+                     Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) ) 
226304                } 
227305
228306                ty:: Int ( nty)  => { 
229307                    let  width = nty. normalize ( pointer_size. bits ( )  as  _ ) . bit_width ( ) . unwrap ( )  / 8 ; 
230-                     Ok ( Self :: number ( width  as   _ ) ) 
308+                     Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) ) 
231309                } 
232310
233311                ty:: Uint ( nty)  => { 
234312                    let  width = nty. normalize ( pointer_size. bits ( )  as  _ ) . bit_width ( ) . unwrap ( )  / 8 ; 
235-                     Ok ( Self :: number ( width  as   _ ) ) 
313+                     Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) ) 
236314                } 
237315
238316                ty:: Tuple ( members)  => Self :: from_tuple ( ( ty,  layout) ,  members,  cx) , 
@@ -249,11 +327,41 @@ pub(crate) mod rustc {
249327                        . fold ( Tree :: unit ( ) ,  |tree,  elt| tree. then ( elt) ) ) 
250328                } 
251329
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-                 } , 
330+                 ty:: Adt ( adt_def,  _args_ref)  if  !ty. is_box ( )  => { 
331+                     let  ( lo,  hi)  = cx. tcx ( ) . layout_scalar_valid_range ( adt_def. did ( ) ) ; 
332+ 
333+                     use  core:: ops:: Bound :: * ; 
334+                     let  is_transparent = adt_def. repr ( ) . transparent ( ) ; 
335+                     match  ( adt_def. adt_kind ( ) ,  lo,  hi)  { 
336+                         ( AdtKind :: Struct ,  Unbounded ,  Unbounded )  => { 
337+                             Self :: from_struct ( ( ty,  layout) ,  * adt_def,  cx) 
338+                         } 
339+                         ( AdtKind :: Struct ,  Included ( 1 ) ,  Included ( hi) )  if  is_transparent => { 
340+                             let  field_ty = ty_field ( cx,  ( ty,  layout) ,  FieldIdx :: from_usize ( 0 ) ) ; 
341+                             let  width_bits = match  field_ty. kind ( )  { 
342+                                 ty:: Float ( nty)  => nty. bit_width ( ) , 
343+                                 ty:: Int ( nty)  => { 
344+                                     nty. normalize ( pointer_size. bits ( )  as  _ ) . bit_width ( ) . unwrap ( ) 
345+                                 } 
346+                                 ty:: Uint ( nty)  => { 
347+                                     nty. normalize ( pointer_size. bits ( )  as  _ ) . bit_width ( ) . unwrap ( ) 
348+                                 } 
349+                                 _ => return  Err ( Err :: NotYetSupported ) , 
350+                             } ; 
351+                             if  hi != ( 1u128  << ( width_bits) )  - 1  { 
352+                                 return  Err ( Err :: NotYetSupported ) ; 
353+                             } 
354+                             Ok ( Self :: nonzero ( width_bits / 8 ) ) 
355+                         } 
356+                         ( AdtKind :: Enum ,  Unbounded ,  Unbounded )  => { 
357+                             Self :: from_enum ( ( ty,  layout) ,  * adt_def,  cx) 
358+                         } 
359+                         ( AdtKind :: Union ,  Unbounded ,  Unbounded )  => { 
360+                             Self :: from_union ( ( ty,  layout) ,  * adt_def,  cx) 
361+                         } 
362+                         _ => Err ( Err :: NotYetSupported ) , 
363+                     } 
364+                 } 
257365
258366                ty:: Ref ( lifetime,  ty,  mutability)  => { 
259367                    let  layout = layout_of ( cx,  * ty) ?; 
@@ -268,6 +376,10 @@ pub(crate) mod rustc {
268376                    } ) ) 
269377                } 
270378
379+                 ty:: Char  => Ok ( Self :: char ( cx. tcx ( ) . data_layout . endian . into ( ) ) ) , 
380+ 
381+                 ty:: Alias ( _kind,  ty)  => Self :: from_ty ( ty. to_ty ( cx. tcx ( ) ) ,  cx) , 
382+ 
271383                _ => Err ( Err :: NotYetSupported ) , 
272384            } 
273385        } 
@@ -450,7 +562,7 @@ pub(crate) mod rustc {
450562                    & bytes[ bytes. len ( )  - size. bytes_usize ( ) ..] 
451563                } 
452564            } ; 
453-             Self :: Seq ( bytes. iter ( ) . map ( |& b| Self :: from_bits ( b) ) . collect ( ) ) 
565+             Self :: Seq ( bytes. iter ( ) . map ( |& b| Self :: byte ( b) ) . collect ( ) ) 
454566        } 
455567
456568        /// Constructs a `Tree` from a union. 
0 commit comments