(info: &EnumSetInfo, paths: &Paths)
| 471 | } |
| 472 | |
| 473 | fn create_enum_conversions(info: &EnumSetInfo, paths: &Paths) -> SynTokenStream { |
| 474 | let name = &info.name; |
| 475 | let core = &paths.core; |
| 476 | let enum_repr = info.enum_repr(); |
| 477 | |
| 478 | let hint_is_transmute = quote! { |
| 479 | #[cfg(target_endian = "little")] |
| 480 | let r = *(&r as *const #enum_repr as *const #name); |
| 481 | |
| 482 | #[cfg(target_endian = "big")] |
| 483 | let r = { |
| 484 | let offset = |
| 485 | #core::mem::size_of::<#enum_repr>() - #core::mem::size_of::<#name>(); |
| 486 | let r = r << ((offset as #enum_repr) * 8); |
| 487 | *(&r as *const #enum_repr as *const u8 as *const #name) |
| 488 | }; |
| 489 | }; |
| 490 | |
| 491 | if info.variants.is_empty() { |
| 492 | // Uninhabited types have no values. |
| 493 | quote! { |
| 494 | fn enum_into_u32(self) -> u32 { |
| 495 | #core::panic!(concat!(stringify!(#name), " is uninhabited.")) |
| 496 | } |
| 497 | unsafe fn enum_from_u32(val: u32) -> Self { |
| 498 | #core::panic!(concat!(stringify!(#name), " is uninhabited.")) |
| 499 | } |
| 500 | } |
| 501 | } else if info.variants.len() == 1 { |
| 502 | // Single-variant enums are generally ZSTs in #[repr(Rust)], and can use simpler code. |
| 503 | let variant = &info.variants[0].name; |
| 504 | quote! { |
| 505 | fn enum_into_u32(self) -> u32 { |
| 506 | self as u32 |
| 507 | } |
| 508 | unsafe fn enum_from_u32(val: u32) -> Self { |
| 509 | #name::#variant |
| 510 | } |
| 511 | } |
| 512 | } else if info.uses_lsb_encoding() || info.uses_msb_encoding().is_some() { |
| 513 | // Prepares output for MSB mode. |
| 514 | let process_output = if let Some(msb_repr) = info.uses_msb_encoding() { |
| 515 | quote! { |
| 516 | let r = (#msb_repr as #enum_repr) - 1 - r; |
| 517 | } |
| 518 | } else { |
| 519 | quote!() |
| 520 | }; |
| 521 | |
| 522 | let (names, values) = if info.bit_width() >= 1000 { |
| 523 | // This worsens codegen quality, but avoids creating big tables for no good reason. |
| 524 | let variant_bits: Vec<_> = info.variants.iter().map(|x| x.variant_bit).collect(); |
| 525 | let variant_names: Vec<_> = info |
| 526 | .variants |
| 527 | .iter() |
| 528 | .map(|x| { |
| 529 | let variant_name = &x.name; |
| 530 | quote! { #name::#variant_name } |
no test coverage detected