1- use std:: ops:: ControlFlow ;
1+ use std:: ops:: { ControlFlow , RangeInclusive } ;
22
33use super :: { Byte , Def , Ref } ;
44
3232 Byte ( 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`.
6177 pub ( 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`.
6682 pub ( 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`.
136212 pub ( 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