object_rainbow/
enumkind.rs1use crate::*;
2
3pub trait UsizeTag: Sized {
4 fn from_usize(n: usize) -> Self;
5 fn to_usize(&self) -> usize;
6 fn try_to_usize(&self) -> Option<usize>;
7}
8
9#[derive(ToOutput, Topological, Tagged, ParseAsInline, Size, MaybeHasNiche)]
10pub struct EnumTag<T, const MAX: usize>(T);
11
12impl<T: Deref<Target: UsizeTag> + From<T::Target>, const MAX: usize> UsizeTag for EnumTag<T, MAX> {
13 fn from_usize(n: usize) -> Self {
14 assert!(n < MAX);
15 Self(T::from(UsizeTag::from_usize(n)))
16 }
17
18 fn to_usize(&self) -> usize {
19 self.0.to_usize()
20 }
21
22 fn try_to_usize(&self) -> Option<usize> {
23 self.0.try_to_usize()
24 }
25}
26
27impl<T: Deref<Target: UsizeTag> + From<T::Target>, const MAX: usize> EnumTag<T, MAX> {
28 pub fn to_usize(&self) -> usize {
29 self.0.to_usize()
30 }
31
32 pub fn from_const<const N: usize>() -> Self {
33 assert!(N < MAX);
34 Self(T::from(UsizeTag::from_usize(N)))
35 }
36}
37
38impl<T: ParseInline<I> + Deref<Target: UsizeTag>, I: ParseInput, const MAX: usize> ParseInline<I>
39 for EnumTag<T, MAX>
40{
41 fn parse_inline(input: &mut I) -> crate::Result<Self> {
42 let n_raw = T::parse_inline(input)?;
43 let n: Option<usize> = n_raw.try_to_usize();
44 if let Some(n) = n {
45 if n < MAX {
46 return Ok(Self(n_raw));
47 }
48 }
49 Err(Error::DiscriminantOverflow)
50 }
51}
52
53pub trait EnumKind: Copy {
54 type Tag;
55 fn to_tag(self) -> Self::Tag;
56 fn from_tag(tag: Self::Tag) -> Self;
57}
58
59pub trait Enum {
60 type Kind: EnumKind;
61 fn kind(&self) -> Self::Kind;
62}
63
64pub trait EnumParse<I: ParseInput>: Enum + Parse<I> {
65 fn enum_parse(kind: Self::Kind, input: I) -> crate::Result<Self>;
66 fn parse_as_enum(mut input: I) -> crate::Result<Self>
67 where
68 <Self::Kind as EnumKind>::Tag: ParseInline<I>,
69 {
70 Self::enum_parse(Self::Kind::from_tag(input.parse_inline()?), input)
71 }
72}
73
74pub trait EnumParseInline<I: ParseInput>: Enum + ParseInline<I> {
75 fn enum_parse_inline(kind: Self::Kind, input: &mut I) -> crate::Result<Self>;
76 fn parse_as_inline_enum(input: &mut I) -> crate::Result<Self>
77 where
78 <Self::Kind as EnumKind>::Tag: ParseInline<I>,
79 {
80 Self::enum_parse_inline(Self::Kind::from_tag(input.parse_inline()?), input)
81 }
82}