diff options
Diffstat (limited to 'src/test/ui/structs-enums/enum-non-c-like-repr-int.rs')
-rw-r--r-- | src/test/ui/structs-enums/enum-non-c-like-repr-int.rs | 169 |
1 files changed, 0 insertions, 169 deletions
diff --git a/src/test/ui/structs-enums/enum-non-c-like-repr-int.rs b/src/test/ui/structs-enums/enum-non-c-like-repr-int.rs deleted file mode 100644 index f9e96c1a0..000000000 --- a/src/test/ui/structs-enums/enum-non-c-like-repr-int.rs +++ /dev/null @@ -1,169 +0,0 @@ -// run-pass -// This test deserializes an enum in-place by transmuting to a union that -// should have the same layout, and manipulating the tag and payloads -// independently. This verifies that `repr(some_int)` has a stable representation, -// and that we don't miscompile these kinds of manipulations. - -use std::time::Duration; -use std::mem; - -#[repr(u8)] -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z` - // depend on tag being internal - C, // Empty - D(Option<u32>), // Contains an enum - E(Duration), // Contains a struct -} - -#[allow(non_snake_case)] -#[repr(C)] -union MyEnumRepr { - A: MyEnumVariantA, - B: MyEnumVariantB, - C: MyEnumVariantC, - D: MyEnumVariantD, - E: MyEnumVariantE, -} - -#[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(MyEnumTag, u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16, z: u8 } -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantC(MyEnumTag); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(MyEnumTag, Option<u32>); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(MyEnumTag, Duration); - -fn main() { - let result: Vec<Result<MyEnum, ()>> = vec![ - Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), - Ok(MyEnum::C), - Err(()), - Ok(MyEnum::D(Some(407))), - Ok(MyEnum::D(None)), - Ok(MyEnum::E(Duration::from_secs(100))), - Err(()), - ]; - - // Binary serialized version of the above (little-endian) - let input: Vec<u8> = vec![ - 0, 17, 0, 0, 0, - 1, 206, 121, 4, 78, - 2, - 8, /* invalid tag value */ - 3, 0, 151, 1, 0, 0, - 3, 1, - 4, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, /* incomplete value */ - ]; - - let mut output = vec![]; - let mut buf = &input[..]; - - unsafe { - // This should be safe, because we don't match on it unless it's fully formed, - // and it doesn't have a destructor. - // - // MyEnum is repr(u8) so it is guaranteed to have a separate discriminant and each variant - // can be zero initialized. - let mut dest: MyEnum = mem::zeroed(); - while buf.len() > 0 { - match parse_my_enum(&mut dest, &mut buf) { - Ok(()) => output.push(Ok(dest)), - Err(()) => output.push(Err(())), - } - } - } - - assert_eq!(output, result); -} - -fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { - unsafe { - // Should be correct to do this transmute. - let dest: &'a mut MyEnumRepr = mem::transmute(dest); - let tag = read_u8(buf)?; - - dest.A.0 = match tag { - 0 => MyEnumTag::A, - 1 => MyEnumTag::B, - 2 => MyEnumTag::C, - 3 => MyEnumTag::D, - 4 => MyEnumTag::E, - _ => return Err(()), - }; - - match dest.B.tag { - MyEnumTag::A => { - dest.A.1 = read_u32_le(buf)?; - } - MyEnumTag::B => { - dest.B.x = read_u8(buf)?; - dest.B.y = read_u16_le(buf)? as i16; - dest.B.z = read_u8(buf)?; - } - MyEnumTag::C => { - /* do nothing */ - } - MyEnumTag::D => { - let is_some = read_u8(buf)? == 0; - if is_some { - dest.D.1 = Some(read_u32_le(buf)?); - } else { - dest.D.1 = None; - } - } - MyEnumTag::E => { - let secs = read_u64_le(buf)?; - let nanos = read_u32_le(buf)?; - dest.E.1 = Duration::new(secs, nanos); - } - } - Ok(()) - } -} - - - -// reader helpers - -fn read_u64_le(buf: &mut &[u8]) -> Result<u64, ()> { - if buf.len() < 8 { return Err(()) } - let val = (buf[0] as u64) << 0 - | (buf[1] as u64) << 8 - | (buf[2] as u64) << 16 - | (buf[3] as u64) << 24 - | (buf[4] as u64) << 32 - | (buf[5] as u64) << 40 - | (buf[6] as u64) << 48 - | (buf[7] as u64) << 56; - *buf = &buf[8..]; - Ok(val) -} - -fn read_u32_le(buf: &mut &[u8]) -> Result<u32, ()> { - if buf.len() < 4 { return Err(()) } - let val = (buf[0] as u32) << 0 - | (buf[1] as u32) << 8 - | (buf[2] as u32) << 16 - | (buf[3] as u32) << 24; - *buf = &buf[4..]; - Ok(val) -} - -fn read_u16_le(buf: &mut &[u8]) -> Result<u16, ()> { - if buf.len() < 2 { return Err(()) } - let val = (buf[0] as u16) << 0 - | (buf[1] as u16) << 8; - *buf = &buf[2..]; - Ok(val) -} - -fn read_u8(buf: &mut &[u8]) -> Result<u8, ()> { - if buf.len() < 1 { return Err(()) } - let val = buf[0]; - *buf = &buf[1..]; - Ok(val) -} |