1 use std::fmt; 2 use std::marker::PhantomData; 3 use std::mem; 4 5 use crate::reflect::runtime_types::RuntimeTypeEnumOrUnknown; 6 use crate::reflect::EnumDescriptor; 7 use crate::reflect::ProtobufValue; 8 use crate::Enum; 9 use crate::EnumFull; 10 11 /// Protobuf enums with possibly unknown values are preserved in this struct. 12 #[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)] 13 #[repr(transparent)] 14 // This should be <E: ProtobufEnum> when it no longer prevents using const fns. 15 pub struct EnumOrUnknown<E> { 16 value: i32, 17 _marker: PhantomData<E>, 18 } 19 20 // Move into <E: ProtobufEnum> when no longer: 21 // > trait bounds other than `Sized` on const fn parameters are unstable. 22 impl<E> EnumOrUnknown<E> { 23 /// Construct from any `i32` value. 24 /// 25 /// Note passed value is not required to be a valid enum value. from_i32(value: i32) -> EnumOrUnknown<E>26 pub const fn from_i32(value: i32) -> EnumOrUnknown<E> { 27 EnumOrUnknown { 28 value, 29 _marker: PhantomData, 30 } 31 } 32 } 33 34 impl<E: Enum> EnumOrUnknown<E> { 35 /// Construct from typed enum new(e: E) -> EnumOrUnknown<E>36 pub fn new(e: E) -> EnumOrUnknown<E> { 37 EnumOrUnknown::from_i32(e.value()) 38 } 39 40 /// Get contained `i32` value of enum value(&self) -> i3241 pub fn value(&self) -> i32 { 42 self.value 43 } 44 45 /// Get `i32` value as typed enum. Return `None` is value is unknown. enum_value(&self) -> Result<E, i32>46 pub fn enum_value(&self) -> Result<E, i32> { 47 E::from_i32(self.value).ok_or(self.value) 48 } 49 50 /// Get contained enum, panic if value is unknown. unwrap(&self) -> E51 pub fn unwrap(&self) -> E { 52 self.enum_value().unwrap() 53 } 54 55 /// Get `i32` value as typed enum. 56 /// Return default enum value (first value) if value is unknown. enum_value_or_default(&self) -> E57 pub fn enum_value_or_default(&self) -> E { 58 self.enum_value().unwrap_or_default() 59 } 60 61 /// Get `i32` value as typed enum. 62 /// Return given enum value if value is unknown. enum_value_or(&self, map_unknown: E) -> E63 pub fn enum_value_or(&self, map_unknown: E) -> E { 64 self.enum_value().unwrap_or(map_unknown) 65 } 66 cast_to_values(enums: &[EnumOrUnknown<E>]) -> &[i32]67 pub(crate) fn cast_to_values(enums: &[EnumOrUnknown<E>]) -> &[i32] { 68 assert_eq!(mem::size_of::<EnumOrUnknown<E>>(), mem::size_of::<i32>()); 69 // SAFETY: `EnumOrUnknown` is `repr(C)`. 70 unsafe { std::slice::from_raw_parts(enums.as_ptr() as *const i32, enums.len()) } 71 } 72 } 73 74 impl<E: EnumFull> EnumOrUnknown<E> { 75 /// Get enum descriptor by type. enum_descriptor() -> EnumDescriptor76 pub fn enum_descriptor() -> EnumDescriptor { 77 E::enum_descriptor() 78 } 79 } 80 81 impl<E: Enum> From<E> for EnumOrUnknown<E> { from(e: E) -> Self82 fn from(e: E) -> Self { 83 EnumOrUnknown::new(e) 84 } 85 } 86 87 impl<E: Enum> Default for EnumOrUnknown<E> { default() -> EnumOrUnknown<E>88 fn default() -> EnumOrUnknown<E> { 89 EnumOrUnknown::new(E::default()) 90 } 91 } 92 93 impl<E: Enum + fmt::Debug> fmt::Debug for EnumOrUnknown<E> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result94 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 95 match self.enum_value() { 96 Ok(e) => fmt::Debug::fmt(&e, f), 97 Err(e) => fmt::Debug::fmt(&e, f), 98 } 99 } 100 } 101 102 impl<E: EnumFull> ProtobufValue for EnumOrUnknown<E> { 103 type RuntimeType = RuntimeTypeEnumOrUnknown<E>; 104 } 105