• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Fuchsia Authors
2 //
3 // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
4 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
6 // This file may not be copied, modified, or distributed except according to
7 // those terms.
8 
9 // See comment in `include.rs` for why we disable the prelude.
10 #![no_implicit_prelude]
11 #![allow(warnings)]
12 
13 include!("include.rs");
14 
15 #[derive(Eq, PartialEq, Debug, imp::Immutable, imp::KnownLayout, imp::TryFromBytes)]
16 #[repr(u8)]
17 enum Foo {
18     A,
19 }
20 
21 util_assert_impl_all!(Foo: imp::TryFromBytes);
22 
23 #[test]
test_foo()24 fn test_foo() {
25     imp::assert_eq!(<Foo as imp::TryFromBytes>::try_read_from_bytes(&[0]), imp::Ok(Foo::A));
26     imp::assert!(<Foo as imp::TryFromBytes>::try_read_from_bytes(&[]).is_err());
27     imp::assert!(<Foo as imp::TryFromBytes>::try_read_from_bytes(&[1]).is_err());
28     imp::assert!(<Foo as imp::TryFromBytes>::try_read_from_bytes(&[0, 0]).is_err());
29 }
30 
31 #[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)]
32 #[repr(u16)]
33 enum Bar {
34     A = 0,
35 }
36 
37 util_assert_impl_all!(Bar: imp::TryFromBytes);
38 
39 #[test]
test_bar()40 fn test_bar() {
41     imp::assert_eq!(<Bar as imp::TryFromBytes>::try_read_from_bytes(&[0, 0]), imp::Ok(Bar::A));
42     imp::assert!(<Bar as imp::TryFromBytes>::try_read_from_bytes(&[]).is_err());
43     imp::assert!(<Bar as imp::TryFromBytes>::try_read_from_bytes(&[0]).is_err());
44     imp::assert!(<Bar as imp::TryFromBytes>::try_read_from_bytes(&[0, 1]).is_err());
45     imp::assert!(<Bar as imp::TryFromBytes>::try_read_from_bytes(&[0, 0, 0]).is_err());
46 }
47 
48 #[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)]
49 #[repr(u32)]
50 enum Baz {
51     A = 1,
52     B = 0,
53 }
54 
55 util_assert_impl_all!(Baz: imp::TryFromBytes);
56 
57 #[test]
test_baz()58 fn test_baz() {
59     imp::assert_eq!(
60         <Baz as imp::TryFromBytes>::try_read_from_bytes(imp::IntoBytes::as_bytes(&1u32)),
61         imp::Ok(Baz::A)
62     );
63     imp::assert_eq!(
64         <Baz as imp::TryFromBytes>::try_read_from_bytes(imp::IntoBytes::as_bytes(&0u32)),
65         imp::Ok(Baz::B)
66     );
67     imp::assert!(<Baz as imp::TryFromBytes>::try_read_from_bytes(&[]).is_err());
68     imp::assert!(<Baz as imp::TryFromBytes>::try_read_from_bytes(&[0]).is_err());
69     imp::assert!(<Baz as imp::TryFromBytes>::try_read_from_bytes(&[0, 0]).is_err());
70     imp::assert!(<Baz as imp::TryFromBytes>::try_read_from_bytes(&[0, 0, 0]).is_err());
71     imp::assert!(<Baz as imp::TryFromBytes>::try_read_from_bytes(&[0, 0, 0, 0, 0]).is_err());
72 }
73 
74 // Test hygiene - make sure that `i8` being shadowed doesn't cause problems for
75 // the code emitted by the derive.
76 type i8 = bool;
77 
78 const THREE: ::core::primitive::i8 = 3;
79 
80 #[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)]
81 #[repr(i8)]
82 enum Blah {
83     A = 1,
84     B = 0,
85     C = 1 + 2,
86     D = 3 + THREE,
87 }
88 
89 util_assert_impl_all!(Blah: imp::TryFromBytes);
90 
91 #[test]
test_blah()92 fn test_blah() {
93     imp::assert_eq!(
94         <Blah as imp::TryFromBytes>::try_read_from_bytes(imp::IntoBytes::as_bytes(&1i8)),
95         imp::Ok(Blah::A)
96     );
97     imp::assert_eq!(
98         <Blah as imp::TryFromBytes>::try_read_from_bytes(imp::IntoBytes::as_bytes(&0i8)),
99         imp::Ok(Blah::B)
100     );
101     imp::assert_eq!(
102         <Blah as imp::TryFromBytes>::try_read_from_bytes(imp::IntoBytes::as_bytes(&3i8)),
103         imp::Ok(Blah::C)
104     );
105     imp::assert_eq!(
106         <Blah as imp::TryFromBytes>::try_read_from_bytes(imp::IntoBytes::as_bytes(&6i8)),
107         imp::Ok(Blah::D)
108     );
109     imp::assert!(<Blah as imp::TryFromBytes>::try_read_from_bytes(&[]).is_err());
110     imp::assert!(<Blah as imp::TryFromBytes>::try_read_from_bytes(&[4]).is_err());
111     imp::assert!(<Blah as imp::TryFromBytes>::try_read_from_bytes(&[0, 0]).is_err());
112 }
113 
114 #[derive(
115     Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes, imp::IntoBytes,
116 )]
117 #[repr(C)]
118 enum FieldlessButNotUnitOnly {
119     A,
120     B(),
121     C {},
122 }
123 
124 #[test]
test_fieldless_but_not_unit_only()125 fn test_fieldless_but_not_unit_only() {
126     const SIZE: usize = ::core::mem::size_of::<FieldlessButNotUnitOnly>();
127     let disc: [u8; SIZE] = ::zerocopy::transmute!(FieldlessButNotUnitOnly::A);
128     imp::assert_eq!(
129         <FieldlessButNotUnitOnly as imp::TryFromBytes>::try_read_from_bytes(&disc[..]),
130         imp::Ok(FieldlessButNotUnitOnly::A)
131     );
132     let disc: [u8; SIZE] = ::zerocopy::transmute!(FieldlessButNotUnitOnly::B());
133     imp::assert_eq!(
134         <FieldlessButNotUnitOnly as imp::TryFromBytes>::try_read_from_bytes(&disc[..]),
135         imp::Ok(FieldlessButNotUnitOnly::B())
136     );
137     let disc: [u8; SIZE] = ::zerocopy::transmute!(FieldlessButNotUnitOnly::C {});
138     imp::assert_eq!(
139         <FieldlessButNotUnitOnly as imp::TryFromBytes>::try_read_from_bytes(&disc[..]),
140         imp::Ok(FieldlessButNotUnitOnly::C {})
141     );
142     imp::assert!(<FieldlessButNotUnitOnly as imp::TryFromBytes>::try_read_from_bytes(
143         &[0xFF; SIZE][..]
144     )
145     .is_err());
146 }
147 
148 #[derive(
149     Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes, imp::IntoBytes,
150 )]
151 #[repr(C)]
152 enum WeirdDiscriminants {
153     A = -7,
154     B,
155     C = 33,
156 }
157 
158 #[test]
test_weird_discriminants()159 fn test_weird_discriminants() {
160     const SIZE: usize = ::core::mem::size_of::<WeirdDiscriminants>();
161     let disc: [u8; SIZE] = ::zerocopy::transmute!(WeirdDiscriminants::A);
162     imp::assert_eq!(
163         <WeirdDiscriminants as imp::TryFromBytes>::try_read_from_bytes(&disc[..]),
164         imp::Ok(WeirdDiscriminants::A)
165     );
166     let disc: [u8; SIZE] = ::zerocopy::transmute!(WeirdDiscriminants::B);
167     imp::assert_eq!(
168         <WeirdDiscriminants as imp::TryFromBytes>::try_read_from_bytes(&disc[..]),
169         imp::Ok(WeirdDiscriminants::B)
170     );
171     let disc: [u8; SIZE] = ::zerocopy::transmute!(WeirdDiscriminants::C);
172     imp::assert_eq!(
173         <WeirdDiscriminants as imp::TryFromBytes>::try_read_from_bytes(&disc[..]),
174         imp::Ok(WeirdDiscriminants::C)
175     );
176     imp::assert!(
177         <WeirdDiscriminants as imp::TryFromBytes>::try_read_from_bytes(&[0xFF; SIZE][..]).is_err()
178     );
179 }
180 
181 // Technically non-portable since this is only `IntoBytes` if the discriminant
182 // is an `i32` or `u32`, but we'll cross that bridge when we get to it...
183 #[derive(
184     Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes, imp::IntoBytes,
185 )]
186 #[repr(C)]
187 enum HasFields {
188     A(u32),
189     B { foo: ::core::num::NonZeroU32 },
190 }
191 
192 #[test]
test_has_fields()193 fn test_has_fields() {
194     const SIZE: usize = ::core::mem::size_of::<HasFields>();
195 
196     let bytes: [u8; SIZE] = ::zerocopy::transmute!(HasFields::A(10));
197     imp::assert_eq!(
198         <HasFields as imp::TryFromBytes>::try_read_from_bytes(&bytes[..]),
199         imp::Ok(HasFields::A(10)),
200     );
201 
202     let bytes: [u8; SIZE] =
203         ::zerocopy::transmute!(HasFields::B { foo: ::core::num::NonZeroU32::new(123456).unwrap() });
204     imp::assert_eq!(
205         <HasFields as imp::TryFromBytes>::try_read_from_bytes(&bytes[..]),
206         imp::Ok(HasFields::B { foo: ::core::num::NonZeroU32::new(123456).unwrap() }),
207     );
208 }
209 
210 #[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)]
211 #[repr(C, align(16))]
212 enum HasFieldsAligned {
213     A(u32),
214     B { foo: ::core::num::NonZeroU32 },
215 }
216 
217 util_assert_impl_all!(HasFieldsAligned: imp::TryFromBytes);
218 
219 #[test]
test_has_fields_aligned()220 fn test_has_fields_aligned() {
221     const SIZE: usize = ::core::mem::size_of::<HasFieldsAligned>();
222 
223     #[derive(imp::IntoBytes)]
224     #[repr(C)]
225     struct BytesOfHasFieldsAligned {
226         has_fields: HasFields,
227         padding: [u8; 8],
228     }
229 
230     let wrap = |has_fields| BytesOfHasFieldsAligned { has_fields, padding: [0; 8] };
231 
232     let bytes: [u8; SIZE] = ::zerocopy::transmute!(wrap(HasFields::A(10)));
233     imp::assert_eq!(
234         <HasFieldsAligned as imp::TryFromBytes>::try_read_from_bytes(&bytes[..]),
235         imp::Ok(HasFieldsAligned::A(10)),
236     );
237 
238     let bytes: [u8; SIZE] = ::zerocopy::transmute!(wrap(HasFields::B {
239         foo: ::core::num::NonZeroU32::new(123456).unwrap()
240     }));
241     imp::assert_eq!(
242         <HasFieldsAligned as imp::TryFromBytes>::try_read_from_bytes(&bytes[..]),
243         imp::Ok(HasFieldsAligned::B { foo: ::core::num::NonZeroU32::new(123456).unwrap() }),
244     );
245 }
246 
247 #[derive(
248     Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes, imp::IntoBytes,
249 )]
250 #[repr(u32)]
251 enum HasFieldsPrimitive {
252     A(u32),
253     B { foo: ::core::num::NonZeroU32 },
254 }
255 
256 #[test]
test_has_fields_primitive()257 fn test_has_fields_primitive() {
258     const SIZE: usize = ::core::mem::size_of::<HasFieldsPrimitive>();
259 
260     let bytes: [u8; SIZE] = ::zerocopy::transmute!(HasFieldsPrimitive::A(10));
261     imp::assert_eq!(
262         <HasFieldsPrimitive as imp::TryFromBytes>::try_read_from_bytes(&bytes[..]),
263         imp::Ok(HasFieldsPrimitive::A(10)),
264     );
265 
266     let bytes: [u8; SIZE] = ::zerocopy::transmute!(HasFieldsPrimitive::B {
267         foo: ::core::num::NonZeroU32::new(123456).unwrap(),
268     });
269     imp::assert_eq!(
270         <HasFieldsPrimitive as imp::TryFromBytes>::try_read_from_bytes(&bytes[..]),
271         imp::Ok(HasFieldsPrimitive::B { foo: ::core::num::NonZeroU32::new(123456).unwrap() }),
272     );
273 }
274 
275 #[derive(Eq, PartialEq, Debug, imp::KnownLayout, imp::Immutable, imp::TryFromBytes)]
276 #[repr(u32, align(16))]
277 enum HasFieldsPrimitiveAligned {
278     A(u32),
279     B { foo: ::core::num::NonZeroU32 },
280 }
281 
282 util_assert_impl_all!(HasFieldsPrimitiveAligned: imp::TryFromBytes);
283 
284 #[test]
test_has_fields_primitive_aligned()285 fn test_has_fields_primitive_aligned() {
286     const SIZE: usize = ::core::mem::size_of::<HasFieldsPrimitiveAligned>();
287 
288     #[derive(imp::IntoBytes)]
289     #[repr(C)]
290     struct BytesOfHasFieldsPrimitiveAligned {
291         has_fields: HasFieldsPrimitive,
292         padding: [u8; 8],
293     }
294 
295     let wrap = |has_fields| BytesOfHasFieldsPrimitiveAligned { has_fields, padding: [0; 8] };
296 
297     let bytes: [u8; SIZE] = ::zerocopy::transmute!(wrap(HasFieldsPrimitive::A(10)));
298     imp::assert_eq!(
299         <HasFieldsPrimitiveAligned as imp::TryFromBytes>::try_read_from_bytes(&bytes[..]),
300         imp::Ok(HasFieldsPrimitiveAligned::A(10)),
301     );
302 
303     let bytes: [u8; SIZE] = ::zerocopy::transmute!(wrap(HasFieldsPrimitive::B {
304         foo: ::core::num::NonZeroU32::new(123456).unwrap()
305     }));
306     imp::assert_eq!(
307         <HasFieldsPrimitiveAligned as imp::TryFromBytes>::try_read_from_bytes(&bytes[..]),
308         imp::Ok(HasFieldsPrimitiveAligned::B {
309             foo: ::core::num::NonZeroU32::new(123456).unwrap()
310         }),
311     );
312 }
313 
314 #[derive(imp::TryFromBytes)]
315 #[repr(align(4), u32)]
316 enum HasReprAlignFirst {
317     A,
318     B,
319 }
320 
321 util_assert_impl_all!(HasReprAlignFirst: imp::TryFromBytes);
322 
323 #[derive(imp::KnownLayout, imp::TryFromBytes, imp::Immutable)]
324 #[repr(u8)]
325 enum Complex {
326     UnitLike,
327     StructLike { a: u8, b: u16 },
328     TupleLike(bool, char),
329 }
330 
331 util_assert_impl_all!(Complex: imp::TryFromBytes);
332 
333 #[derive(imp::KnownLayout, imp::TryFromBytes, imp::Immutable)]
334 #[repr(u8)]
335 enum ComplexWithGenerics<X, Y> {
336     UnitLike,
337     StructLike { a: u8, b: X },
338     TupleLike(bool, Y),
339 }
340 
341 util_assert_impl_all!(ComplexWithGenerics<u16, char>: imp::TryFromBytes);
342 
343 #[derive(imp::KnownLayout, imp::TryFromBytes, imp::Immutable)]
344 #[repr(C)]
345 enum GenericWithLifetimes<'a, 'b, X: 'a, Y: 'b> {
346     Foo(::core::marker::PhantomData<&'a X>),
347     Bar(::core::marker::PhantomData<&'b Y>),
348 }
349 
350 #[derive(Clone, Copy, imp::TryFromBytes)]
351 struct A;
352 
353 #[derive(imp::TryFromBytes)]
354 #[repr(C)]
355 enum B {
356     A(A),
357     A2 { a: A },
358 }
359 
360 #[derive(imp::TryFromBytes)]
361 #[repr(u8)]
362 enum FooU8 {
363     Variant0,
364     Variant1,
365     Variant2,
366     Variant3,
367     Variant4,
368     Variant5,
369     Variant6,
370     Variant7,
371     Variant8,
372     Variant9,
373     Variant10,
374     Variant11,
375     Variant12,
376     Variant13,
377     Variant14,
378     Variant15,
379     Variant16,
380     Variant17,
381     Variant18,
382     Variant19,
383     Variant20,
384     Variant21,
385     Variant22,
386     Variant23,
387     Variant24,
388     Variant25,
389     Variant26,
390     Variant27,
391     Variant28,
392     Variant29,
393     Variant30,
394     Variant31,
395     Variant32,
396     Variant33,
397     Variant34,
398     Variant35,
399     Variant36,
400     Variant37,
401     Variant38,
402     Variant39,
403     Variant40,
404     Variant41,
405     Variant42,
406     Variant43,
407     Variant44,
408     Variant45,
409     Variant46,
410     Variant47,
411     Variant48,
412     Variant49,
413     Variant50,
414     Variant51,
415     Variant52,
416     Variant53,
417     Variant54,
418     Variant55,
419     Variant56,
420     Variant57,
421     Variant58,
422     Variant59,
423     Variant60,
424     Variant61,
425     Variant62,
426     Variant63,
427     Variant64,
428     Variant65,
429     Variant66,
430     Variant67,
431     Variant68,
432     Variant69,
433     Variant70,
434     Variant71,
435     Variant72,
436     Variant73,
437     Variant74,
438     Variant75,
439     Variant76,
440     Variant77,
441     Variant78,
442     Variant79,
443     Variant80,
444     Variant81,
445     Variant82,
446     Variant83,
447     Variant84,
448     Variant85,
449     Variant86,
450     Variant87,
451     Variant88,
452     Variant89,
453     Variant90,
454     Variant91,
455     Variant92,
456     Variant93,
457     Variant94,
458     Variant95,
459     Variant96,
460     Variant97,
461     Variant98,
462     Variant99,
463     Variant100,
464     Variant101,
465     Variant102,
466     Variant103,
467     Variant104,
468     Variant105,
469     Variant106,
470     Variant107,
471     Variant108,
472     Variant109,
473     Variant110,
474     Variant111,
475     Variant112,
476     Variant113,
477     Variant114,
478     Variant115,
479     Variant116,
480     Variant117,
481     Variant118,
482     Variant119,
483     Variant120,
484     Variant121,
485     Variant122,
486     Variant123,
487     Variant124,
488     Variant125,
489     Variant126,
490     Variant127,
491     Variant128,
492     Variant129,
493     Variant130,
494     Variant131,
495     Variant132,
496     Variant133,
497     Variant134,
498     Variant135,
499     Variant136,
500     Variant137,
501     Variant138,
502     Variant139,
503     Variant140,
504     Variant141,
505     Variant142,
506     Variant143,
507     Variant144,
508     Variant145,
509     Variant146,
510     Variant147,
511     Variant148,
512     Variant149,
513     Variant150,
514     Variant151,
515     Variant152,
516     Variant153,
517     Variant154,
518     Variant155,
519     Variant156,
520     Variant157,
521     Variant158,
522     Variant159,
523     Variant160,
524     Variant161,
525     Variant162,
526     Variant163,
527     Variant164,
528     Variant165,
529     Variant166,
530     Variant167,
531     Variant168,
532     Variant169,
533     Variant170,
534     Variant171,
535     Variant172,
536     Variant173,
537     Variant174,
538     Variant175,
539     Variant176,
540     Variant177,
541     Variant178,
542     Variant179,
543     Variant180,
544     Variant181,
545     Variant182,
546     Variant183,
547     Variant184,
548     Variant185,
549     Variant186,
550     Variant187,
551     Variant188,
552     Variant189,
553     Variant190,
554     Variant191,
555     Variant192,
556     Variant193,
557     Variant194,
558     Variant195,
559     Variant196,
560     Variant197,
561     Variant198,
562     Variant199,
563     Variant200,
564     Variant201,
565     Variant202,
566     Variant203,
567     Variant204,
568     Variant205,
569     Variant206,
570     Variant207,
571     Variant208,
572     Variant209,
573     Variant210,
574     Variant211,
575     Variant212,
576     Variant213,
577     Variant214,
578     Variant215,
579     Variant216,
580     Variant217,
581     Variant218,
582     Variant219,
583     Variant220,
584     Variant221,
585     Variant222,
586     Variant223,
587     Variant224,
588     Variant225,
589     Variant226,
590     Variant227,
591     Variant228,
592     Variant229,
593     Variant230,
594     Variant231,
595     Variant232,
596     Variant233,
597     Variant234,
598     Variant235,
599     Variant236,
600     Variant237,
601     Variant238,
602     Variant239,
603     Variant240,
604     Variant241,
605     Variant242,
606     Variant243,
607     Variant244,
608     Variant245,
609     Variant246,
610     Variant247,
611     Variant248,
612     Variant249,
613     Variant250,
614     Variant251,
615     Variant252,
616     Variant253,
617     Variant254,
618     Variant255,
619 }
620 
621 #[test]
test_trivial_is_bit_valid()622 fn test_trivial_is_bit_valid() {
623     // Though we don't derive `FromBytes`, `FooU8` *could* soundly implement
624     // `FromBytes`. Therefore, `TryFromBytes` derive's `is_bit_valid` impl is
625     // trivial - it unconditionally returns `true`.
626     util_assert_not_impl_any!(FooU8: imp::FromBytes);
627     util::test_trivial_is_bit_valid::<FooU8>();
628 }
629 
630 #[deny(non_camel_case_types)]
631 mod issue_2051 {
632     use super::*;
633 
634     // Test that the `non_camel_case_types` lint isn't triggered by generated code.
635     // Prevents regressions of #2051.
636     #[repr(u32)]
637     #[derive(imp::TryFromBytes)]
638     #[allow(non_camel_case_types)]
639     pub enum Code {
640         I32_ADD,
641         I32_SUB,
642         I32_MUL,
643     }
644 }
645