]>
git.proxmox.com Git - rustc.git/blob - src/test/run-pass/structs-enums/enum-non-c-like-repr-c.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.
12 // This test deserializes an enum in-place by transmuting to a union that
13 // should have the same layout, and manipulating the tag and payloads
14 // independently. This verifies that `repr(some_int)` has a stable representation,
15 // and that we don't miscompile these kinds of manipulations.
17 use std
::time
::Duration
;
21 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
23 A(u32), // Single primitive value
24 B { x: u8, y: i16 }
, // Composite, and the offset of `y` depends on tag being internal
26 D(Option
<u32>), // Contains an enum
27 E(Duration
), // Contains a struct
33 payload
: MyEnumPayload
,
37 #[allow(non_snake_case)]
45 #[repr(C)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E }
46 #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32);
47 #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 }
48 #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option<u32>);
49 #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration);
52 let result
: Vec
<Result
<MyEnum
, ()>> = vec
![
54 Ok(MyEnum
::B { x: 206, y: 1145 }
),
57 Ok(MyEnum
::D(Some(407))),
59 Ok(MyEnum
::E(Duration
::from_secs(100))),
63 // Binary serialized version of the above (little-endian)
64 let input
: Vec
<u8> = vec
![
68 8, /* invalid tag value */
71 4, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, /* incomplete value */
75 let mut output
= vec
![];
76 let mut buf
= &input
[..];
79 // This should be safe, because we don't match on it unless it's fully formed,
80 // and it doesn't have a destructor.
81 let mut dest
: MyEnum
= mem
::uninitialized();
83 match parse_my_enum(&mut dest
, &mut buf
) {
84 Ok(()) => output
.push(Ok(dest
)),
85 Err(()) => output
.push(Err(())),
90 assert_eq
!(output
, result
);
93 fn parse_my_enum
<'a
>(dest
: &'a
mut MyEnum
, buf
: &mut &[u8]) -> Result
<(), ()> {
95 // Should be correct to do this transmute.
96 let dest
: &'a
mut MyEnumRepr
= mem
::transmute(dest
);
97 let tag
= read_u8(buf
)?
;
99 dest
.tag
= match tag
{
110 dest
.payload
.A
.0 = read_u32_le(buf
)?
;
113 dest
.payload
.B
.x
= read_u8(buf
)?
;
114 dest
.payload
.B
.y
= read_u16_le(buf
)?
as i16;
120 let is_some
= read_u8(buf
)?
== 0;
122 dest
.payload
.D
.0 = Some(read_u32_le(buf
)?
);
124 dest
.payload
.D
.0 = None
;
128 let secs
= read_u64_le(buf
)?
;
129 let nanos
= read_u32_le(buf
)?
;
130 dest
.payload
.E
.0 = Duration
::new(secs
, nanos
);
141 fn read_u64_le(buf
: &mut &[u8]) -> Result
<u64, ()> {
142 if buf
.len() < 8 { return Err(()) }
143 let val
= (buf
[0] as u64) << 0
144 | (buf
[1] as u64) << 8
145 | (buf
[2] as u64) << 16
146 | (buf
[3] as u64) << 24
147 | (buf
[4] as u64) << 32
148 | (buf
[5] as u64) << 40
149 | (buf
[6] as u64) << 48
150 | (buf
[7] as u64) << 56;
155 fn read_u32_le(buf
: &mut &[u8]) -> Result
<u32, ()> {
156 if buf
.len() < 4 { return Err(()) }
157 let val
= (buf
[0] as u32) << 0
158 | (buf
[1] as u32) << 8
159 | (buf
[2] as u32) << 16
160 | (buf
[3] as u32) << 24;
165 fn read_u16_le(buf
: &mut &[u8]) -> Result
<u16, ()> {
166 if buf
.len() < 2 { return Err(()) }
167 let val
= (buf
[0] as u16) << 0
168 | (buf
[1] as u16) << 8;
173 fn read_u8(buf
: &mut &[u8]) -> Result
<u8, ()> {
174 if buf
.len() < 1 { return Err(()) }