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,62 @@ 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 )
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`.
136214 pub ( 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