1
- use std:: ops:: ControlFlow ;
1
+ use std:: ops:: { ControlFlow , RangeInclusive } ;
2
2
3
3
use super :: { Byte , Def , Ref } ;
4
4
32
32
Byte ( Byte ) ,
33
33
}
34
34
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
+
35
51
impl < D , R > Tree < D , R >
36
52
where
37
53
D : Def ,
@@ -59,22 +75,60 @@ where
59
75
60
76
/// A `Tree` representing the layout of `bool`.
61
77
pub ( crate ) fn bool ( ) -> Self {
62
- Self :: Byte ( Byte :: new ( 0x00 ..=0x01 ) )
78
+ Self :: byte ( 0x00 ..=0x01 )
63
79
}
64
80
65
81
/// A `Tree` whose layout matches that of a `u8`.
66
82
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] )
68
104
}
69
105
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 ( ) )
73
127
}
74
128
75
129
/// 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 ( ) ] )
78
132
}
79
133
80
134
/// A `Tree` whose layout is entirely padding of the given width.
@@ -125,13 +179,35 @@ where
125
179
Self :: Byte ( ..) | Self :: Ref ( ..) | Self :: Def ( ..) => true ,
126
180
}
127
181
}
128
- }
129
182
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
+
135
211
/// Produces a new `Tree` where `other` is sequenced after `self`.
136
212
pub ( crate ) fn then ( self , other : Self ) -> Self {
137
213
match ( self , other) {
@@ -222,17 +298,17 @@ pub(crate) mod rustc {
222
298
223
299
ty:: Float ( nty) => {
224
300
let width = nty. bit_width ( ) / 8 ;
225
- Ok ( Self :: number ( width as _ ) )
301
+ Ok ( Self :: number ( width. try_into ( ) . unwrap ( ) ) )
226
302
}
227
303
228
304
ty:: Int ( nty) => {
229
305
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 ( ) ) )
231
307
}
232
308
233
309
ty:: Uint ( nty) => {
234
310
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 ( ) ) )
236
312
}
237
313
238
314
ty:: Tuple ( members) => Self :: from_tuple ( ( ty, layout) , members, cx) ,
@@ -249,11 +325,33 @@ pub(crate) mod rustc {
249
325
. fold ( Tree :: unit ( ) , |tree, elt| tree. then ( elt) ) )
250
326
}
251
327
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
+ }
257
355
258
356
ty:: Ref ( lifetime, ty, mutability) => {
259
357
let layout = layout_of ( cx, * ty) ?;
@@ -268,6 +366,8 @@ pub(crate) mod rustc {
268
366
} ) )
269
367
}
270
368
369
+ ty:: Char => Ok ( Self :: char ( cx. tcx ( ) . data_layout . endian . into ( ) ) ) ,
370
+
271
371
_ => Err ( Err :: NotYetSupported ) ,
272
372
}
273
373
}
@@ -450,7 +550,7 @@ pub(crate) mod rustc {
450
550
& bytes[ bytes. len ( ) - size. bytes_usize ( ) ..]
451
551
}
452
552
} ;
453
- Self :: Seq ( bytes. iter ( ) . map ( |& b| Self :: from_bits ( b) ) . collect ( ) )
553
+ Self :: Seq ( bytes. iter ( ) . map ( |& b| Self :: byte ( b) ) . collect ( ) )
454
554
}
455
555
456
556
/// Constructs a `Tree` from a union.
0 commit comments