object_rainbow/
enumkind.rs1use crate::*;
2
3pub trait UsizeTag: Sized {
5 fn from_usize(n: usize) -> Self;
11 fn to_usize(&self) -> usize;
13 fn try_to_usize(&self) -> Option<usize>;
15}
16
17#[derive(
19 ToOutput,
20 InlineOutput,
21 ListHashes,
22 Topological,
23 Tagged,
24 ParseAsInline,
25 Size,
26 MaybeHasNiche,
27 PartialEq,
28 Eq,
29 PartialOrd,
30 Ord,
31 ByteOrd,
32)]
33pub struct EnumTag<T, const MAX: usize>(T);
34
35impl<T: UsizeTag, const MAX: usize> UsizeTag for EnumTag<T, MAX> {
36 fn from_usize(n: usize) -> Self {
37 assert!(n < MAX);
38 Self(UsizeTag::from_usize(n))
39 }
40
41 fn to_usize(&self) -> usize {
42 self.0.to_usize()
43 }
44
45 fn try_to_usize(&self) -> Option<usize> {
46 self.0.try_to_usize()
47 }
48}
49
50impl<T: UsizeTag, const MAX: usize> EnumTag<T, MAX> {
51 pub fn to_usize(&self) -> usize {
53 self.0.to_usize()
54 }
55
56 pub fn from_const<const N: usize>() -> Self {
58 assert!(N < MAX);
59 Self(UsizeTag::from_usize(N))
60 }
61}
62
63impl<T: ParseInline<I> + UsizeTag, I: ParseInput, const MAX: usize> ParseInline<I>
64 for EnumTag<T, MAX>
65{
66 fn parse_inline(input: &mut I) -> crate::Result<Self> {
67 let n_raw = T::parse_inline(input)?;
68 let n: Option<usize> = n_raw.try_to_usize();
69 if let Some(n) = n
70 && n < MAX
71 {
72 return Ok(Self(n_raw));
73 }
74 Err(Error::DiscriminantOverflow)
75 }
76}
77
78pub trait EnumKind: Copy {
80 type Tag;
82 fn to_tag(self) -> Self::Tag;
84 fn from_tag(tag: Self::Tag) -> Self;
89}
90
91pub trait Enum {
93 type Kind: EnumKind;
95 fn kind(&self) -> Self::Kind;
97}
98
99pub trait EnumParse<I: ParseInput>: Enum + Parse<I> {
101 fn enum_parse(kind: Self::Kind, input: I) -> crate::Result<Self>;
103 fn parse_as_enum(mut input: I) -> crate::Result<Self>
105 where
106 <Self::Kind as EnumKind>::Tag: ParseInline<I>,
107 {
108 Self::enum_parse(Self::Kind::from_tag(input.parse_inline()?), input)
109 }
110}
111
112pub trait EnumParseInline<I: ParseInput>: Enum + ParseInline<I> {
114 fn enum_parse_inline(kind: Self::Kind, input: &mut I) -> crate::Result<Self>;
116 fn parse_as_inline_enum(input: &mut I) -> crate::Result<Self>
118 where
119 <Self::Kind as EnumKind>::Tag: ParseInline<I>,
120 {
121 Self::enum_parse_inline(Self::Kind::from_tag(input.parse_inline()?), input)
122 }
123}