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, InlineOutput, ListHashes, Topological, Tagged, ParseAsInline, Size, MaybeHasNiche,
20)]
21pub struct EnumTag<T, const MAX: usize>(T);
22
23impl<T: UsizeTag, const MAX: usize> UsizeTag for EnumTag<T, MAX> {
24 fn from_usize(n: usize) -> Self {
25 assert!(n < MAX);
26 Self(UsizeTag::from_usize(n))
27 }
28
29 fn to_usize(&self) -> usize {
30 self.0.to_usize()
31 }
32
33 fn try_to_usize(&self) -> Option<usize> {
34 self.0.try_to_usize()
35 }
36}
37
38impl<T: UsizeTag, const MAX: usize> EnumTag<T, MAX> {
39 pub fn to_usize(&self) -> usize {
41 self.0.to_usize()
42 }
43
44 pub fn from_const<const N: usize>() -> Self {
46 assert!(N < MAX);
47 Self(UsizeTag::from_usize(N))
48 }
49}
50
51impl<T: ParseInline<I> + UsizeTag, I: ParseInput, const MAX: usize> ParseInline<I>
52 for EnumTag<T, MAX>
53{
54 fn parse_inline(input: &mut I) -> crate::Result<Self> {
55 let n_raw = T::parse_inline(input)?;
56 let n: Option<usize> = n_raw.try_to_usize();
57 if let Some(n) = n
58 && n < MAX
59 {
60 return Ok(Self(n_raw));
61 }
62 Err(Error::DiscriminantOverflow)
63 }
64}
65
66pub trait EnumKind: Copy {
68 type Tag;
70 fn to_tag(self) -> Self::Tag;
72 fn from_tag(tag: Self::Tag) -> Self;
77}
78
79pub trait Enum {
81 type Kind: EnumKind;
83 fn kind(&self) -> Self::Kind;
85}
86
87pub trait EnumParse<I: ParseInput>: Enum + Parse<I> {
89 fn enum_parse(kind: Self::Kind, input: I) -> crate::Result<Self>;
91 fn parse_as_enum(mut input: I) -> crate::Result<Self>
93 where
94 <Self::Kind as EnumKind>::Tag: ParseInline<I>,
95 {
96 Self::enum_parse(Self::Kind::from_tag(input.parse_inline()?), input)
97 }
98}
99
100pub trait EnumParseInline<I: ParseInput>: Enum + ParseInline<I> {
102 fn enum_parse_inline(kind: Self::Kind, input: &mut I) -> crate::Result<Self>;
104 fn parse_as_inline_enum(input: &mut I) -> crate::Result<Self>
106 where
107 <Self::Kind as EnumKind>::Tag: ParseInline<I>,
108 {
109 Self::enum_parse_inline(Self::Kind::from_tag(input.parse_inline()?), input)
110 }
111}