1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
13pub enum Recognized<T, Raw = String> {
14 Known(T),
15 Unknown(Raw),
16}
17
18impl<T: Copy, Raw: Copy> Copy for Recognized<T, Raw> {}
19
20impl<T, Raw> Recognized<T, Raw> {
21 pub fn known(&self) -> Option<&T> {
22 match self {
23 Recognized::Known(t) => Some(t),
24 Recognized::Unknown(_) => None,
25 }
26 }
27
28 pub fn into_known(self) -> Option<T> {
29 match self {
30 Recognized::Known(t) => Some(t),
31 Recognized::Unknown(_) => None,
32 }
33 }
34
35 pub fn unknown(&self) -> Option<&Raw> {
36 match self {
37 Recognized::Known(_) => None,
38 Recognized::Unknown(raw) => Some(raw),
39 }
40 }
41
42 pub fn into_unknown(self) -> Option<Raw> {
43 match self {
44 Recognized::Known(_) => None,
45 Recognized::Unknown(raw) => Some(raw),
46 }
47 }
48
49 pub fn is_known(&self) -> bool {
50 matches!(self, Recognized::Known(_))
51 }
52
53 pub fn is_unknown(&self) -> bool {
54 matches!(self, Recognized::Unknown(_))
55 }
56
57 pub fn unwrap(self) -> T
58 where
59 Raw: fmt::Debug,
60 {
61 match self {
62 Recognized::Known(t) => t,
63 Recognized::Unknown(raw) => {
64 panic!("called `Recognized::unwrap()` on an `Unknown` value: {raw:?}")
65 }
66 }
67 }
68
69 pub fn expect(self, msg: &str) -> T
70 where
71 Raw: fmt::Debug,
72 {
73 match self {
74 Recognized::Known(t) => t,
75 Recognized::Unknown(raw) => panic!("{msg}: {raw:?}"),
76 }
77 }
78
79 pub fn unwrap_or(self, default: T) -> T {
80 match self {
81 Recognized::Known(t) => t,
82 Recognized::Unknown(_) => default,
83 }
84 }
85
86 pub fn unwrap_or_else<F: FnOnce(Raw) -> T>(self, f: F) -> T {
87 match self {
88 Recognized::Known(t) => t,
89 Recognized::Unknown(raw) => f(raw),
90 }
91 }
92
93 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Recognized<U, Raw> {
94 match self {
95 Recognized::Known(t) => Recognized::Known(f(t)),
96 Recognized::Unknown(raw) => Recognized::Unknown(raw),
97 }
98 }
99
100 pub fn map_unknown<U, F: FnOnce(Raw) -> U>(self, f: F) -> Recognized<T, U> {
101 match self {
102 Recognized::Known(t) => Recognized::Known(t),
103 Recognized::Unknown(raw) => Recognized::Unknown(f(raw)),
104 }
105 }
106
107 pub fn and_then<U, F: FnOnce(T) -> Recognized<U, Raw>>(self, f: F) -> Recognized<U, Raw> {
108 match self {
109 Recognized::Known(t) => f(t),
110 Recognized::Unknown(raw) => Recognized::Unknown(raw),
111 }
112 }
113
114 pub fn as_ref(&self) -> Recognized<&T, &Raw> {
115 match self {
116 Recognized::Known(t) => Recognized::Known(t),
117 Recognized::Unknown(raw) => Recognized::Unknown(raw),
118 }
119 }
120}
121
122impl<T, Raw> From<T> for Recognized<T, Raw> {
123 fn from(value: T) -> Self {
124 Recognized::Known(value)
125 }
126}
127
128impl<T: fmt::Display, Raw: fmt::Display> fmt::Display for Recognized<T, Raw> {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 match self {
131 Recognized::Known(t) => t.fmt(f),
132 Recognized::Unknown(raw) => raw.fmt(f),
133 }
134 }
135}