| 1 | // Wrap this in two cfg_attrs so that it continues to parse pre-1.54.0. |
| 2 | // See https://github.com/rust-lang/rust/issues/82768 |
| 3 | #![cfg_attr (feature = "external_doc" , cfg_attr(all(), doc = include_str!("../README.md" )))] |
| 4 | #![cfg_attr ( |
| 5 | not(feature = "external_doc" ), |
| 6 | doc = "See <https://docs.rs/num_enum> for more info about this crate." |
| 7 | )] |
| 8 | #![cfg_attr (not(feature = "std" ), no_std)] |
| 9 | |
| 10 | pub use ::num_enum_derive::{ |
| 11 | Default, FromPrimitive, IntoPrimitive, TryFromPrimitive, UnsafeFromPrimitive, |
| 12 | }; |
| 13 | |
| 14 | use ::core::fmt; |
| 15 | |
| 16 | pub trait FromPrimitive: Sized { |
| 17 | type Primitive: Copy + Eq; |
| 18 | |
| 19 | fn from_primitive(number: Self::Primitive) -> Self; |
| 20 | } |
| 21 | |
| 22 | pub trait TryFromPrimitive: Sized { |
| 23 | type Primitive: Copy + Eq + fmt::Debug; |
| 24 | type Error; |
| 25 | |
| 26 | const NAME: &'static str; |
| 27 | |
| 28 | fn try_from_primitive(number: Self::Primitive) -> Result<Self, Self::Error>; |
| 29 | } |
| 30 | |
| 31 | pub trait UnsafeFromPrimitive: Sized { |
| 32 | type Primitive: Copy + Eq; |
| 33 | |
| 34 | /// Transmutes into an enum from its primitive. |
| 35 | /// |
| 36 | /// # Safety |
| 37 | /// |
| 38 | /// - `number` must represent a valid discriminant of `Self`. |
| 39 | #[deprecated ( |
| 40 | since = "0.6.0" , |
| 41 | note = "Prefer to use `unchecked_transmute_from`, `from_unchecked` will be removed in a future release." |
| 42 | )] |
| 43 | unsafe fn from_unchecked(number: Self::Primitive) -> Self { |
| 44 | Self::unchecked_transmute_from(number) |
| 45 | } |
| 46 | |
| 47 | /// Transmutes into an enum from its primitive. |
| 48 | /// |
| 49 | /// # Safety |
| 50 | /// |
| 51 | /// - `number` must represent a valid discriminant of `Self`. |
| 52 | unsafe fn unchecked_transmute_from(number: Self::Primitive) -> Self; |
| 53 | } |
| 54 | |
| 55 | #[derive (Copy, Clone, PartialEq, Eq)] |
| 56 | pub struct TryFromPrimitiveError<Enum: TryFromPrimitive> { |
| 57 | pub number: Enum::Primitive, |
| 58 | } |
| 59 | |
| 60 | impl<Enum: TryFromPrimitive> TryFromPrimitiveError<Enum> { |
| 61 | pub fn new(number: Enum::Primitive) -> Self { |
| 62 | Self { number } |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | impl<Enum: TryFromPrimitive> fmt::Debug for TryFromPrimitiveError<Enum> { |
| 67 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
| 68 | fmt&mut DebugStruct<'_, '_>.debug_struct("TryFromPrimitiveError" ) |
| 69 | .field(name:"number" , &self.number) |
| 70 | .finish() |
| 71 | } |
| 72 | } |
| 73 | impl<Enum: TryFromPrimitive> fmt::Display for TryFromPrimitiveError<Enum> { |
| 74 | fn fmt(&self, stream: &'_ mut fmt::Formatter<'_>) -> fmt::Result { |
| 75 | write!( |
| 76 | stream, |
| 77 | "No discriminant in enum ` {name}` matches the value ` {input:?}`" , |
| 78 | name = Enum::NAME, |
| 79 | input = self.number, |
| 80 | ) |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | #[cfg (feature = "std" )] |
| 85 | impl<Enum: TryFromPrimitive> ::std::error::Error for TryFromPrimitiveError<Enum> {} |
| 86 | |
| 87 | // This trait exists to try to give a more clear error message when someone attempts to derive both FromPrimitive and TryFromPrimitive. |
| 88 | // This isn't allowed because both end up creating a `TryFrom<primitive>` implementation. |
| 89 | // TryFromPrimitive explicitly implements TryFrom<primitive> with Error=TryFromPrimitiveError, which conflicts with: |
| 90 | // FromPrimitive explicitly implements From<primitive> which has a blanket implementation of TryFrom<primitive> with Error=Infallible. |
| 91 | // |
| 92 | // This is a private implementation detail of the num_enum crate which should not be depended on externally. |
| 93 | // It is subject to change in any release regardless of semver. |
| 94 | #[doc (hidden)] |
| 95 | pub trait CannotDeriveBothFromPrimitiveAndTryFromPrimitive {} |
| 96 | |