]>
git.proxmox.com Git - rustc.git/blob - src/test/run-pass/enum-non-c-like-repr-int.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // This test deserializes an enum in-place by transmuting to a union that
12 // should have the same layout, and manipulating the tag and payloads
13 // independently. This verifies that `repr(some_int)` has a stable representation,
14 // and that we don't miscompile these kinds of manipulations.
16 use std
::time
::Duration
;
20 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
22 A(u32), // Single primitive value
23 B { x: u8, y: i16 }
, // Composite, and the offset of `y` depends on tag being internal
25 D(Option
<u32>), // Contains an enum
26 E(Duration
), // Contains a struct
29 #[allow(non_snake_case)]
39 #[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E }
40 #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(MyEnumTag, u32);
41 #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16 }
42 #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantC(MyEnumTag);
43 #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(MyEnumTag, Option<u32>);
44 #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(MyEnumTag, Duration);
47 let result
: Vec
<Result
<MyEnum
, ()>> = vec
![
49 Ok(MyEnum
::B { x: 206, y: 1145 }
),
52 Ok(MyEnum
::D(Some(407))),
54 Ok(MyEnum
::E(Duration
::from_secs(100))),
58 // Binary serialized version of the above (little-endian)
59 let input
: Vec
<u8> = vec
![
63 8, /* invalid tag value */
66 4, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, /* incomplete value */
70 let mut output
= vec
![];
71 let mut buf
= &input
[..];
74 // This should be safe, because we don't match on it unless it's fully formed,
75 // and it doesn't have a destructor.
76 let mut dest
: MyEnum
= mem
::uninitialized();
78 match parse_my_enum(&mut dest
, &mut buf
) {
79 Ok(()) => output
.push(Ok(dest
)),
80 Err(()) => output
.push(Err(())),
85 assert_eq
!(output
, result
);
88 fn parse_my_enum
<'a
>(dest
: &'a
mut MyEnum
, buf
: &mut &[u8]) -> Result
<(), ()> {
90 // Should be correct to do this transmute.
91 let dest
: &'a
mut MyEnumRepr
= mem
::transmute(dest
);
92 let tag
= read_u8(buf
)?
;
94 dest
.A
.0 = match tag
{
105 dest
.A
.1 = read_u32_le(buf
)?
;
108 dest
.B
.x
= read_u8(buf
)?
;
109 dest
.B
.y
= read_u16_le(buf
)?
as i16;
115 let is_some
= read_u8(buf
)?
== 0;
117 dest
.D
.1 = Some(read_u32_le(buf
)?
);
123 let secs
= read_u64_le(buf
)?
;
124 let nanos
= read_u32_le(buf
)?
;
125 dest
.E
.1 = Duration
::new(secs
, nanos
);
136 fn read_u64_le(buf
: &mut &[u8]) -> Result
<u64, ()> {
137 if buf
.len() < 8 { return Err(()) }
138 let val
= (buf
[0] as u64) << 0
139 | (buf
[1] as u64) << 8
140 | (buf
[2] as u64) << 16
141 | (buf
[3] as u64) << 24
142 | (buf
[4] as u64) << 32
143 | (buf
[5] as u64) << 40
144 | (buf
[6] as u64) << 48
145 | (buf
[7] as u64) << 56;
150 fn read_u32_le(buf
: &mut &[u8]) -> Result
<u32, ()> {
151 if buf
.len() < 4 { return Err(()) }
152 let val
= (buf
[0] as u32) << 0
153 | (buf
[1] as u32) << 8
154 | (buf
[2] as u32) << 16
155 | (buf
[3] as u32) << 24;
160 fn read_u16_le(buf
: &mut &[u8]) -> Result
<u16, ()> {
161 if buf
.len() < 2 { return Err(()) }
162 let val
= (buf
[0] as u16) << 0
163 | (buf
[1] as u16) << 8;
168 fn read_u8(buf
: &mut &[u8]) -> Result
<u8, ()> {
169 if buf
.len() < 1 { return Err(()) }