osom_lib_primitives/
coption.rs1#![allow(clippy::derivable_impls)]
3
4use core::fmt::Display;
5use core::hash::Hash;
6use core::{mem::forget, ptr};
7
8use osom_lib_reprc::{macros::reprc, traits::ReprC};
9use osom_lib_try_clone::TryClone;
10
11#[reprc]
17#[repr(u8)]
18#[derive(Debug)]
19#[must_use]
20pub enum COption<TValue>
21where
22 TValue: ReprC,
23{
24 None = 0,
25 Some(TValue) = 1,
26}
27
28impl<TValue> COption<TValue>
29where
30 TValue: ReprC,
31{
32 #[inline]
35 pub const fn is_some(&self) -> bool {
36 match self {
37 COption::Some(_) => true,
38 COption::None => false,
39 }
40 }
41
42 #[inline]
45 pub const fn is_none(&self) -> bool {
46 !self.is_some()
47 }
48
49 #[inline]
55 pub fn expect(self, message: &str) -> TValue {
56 match &self {
57 COption::Some(value) => {
58 let data = unsafe { ptr::read(value) };
59 forget(self);
60 data
61 }
62 COption::None => {
63 panic!("`COption::expect()`: {}.", message);
64 }
65 }
66 }
67
68 #[inline]
74 pub const fn unwrap(self) -> TValue {
75 match &self {
76 COption::Some(value) => {
77 let data = unsafe { ptr::read(value) };
78 forget(self);
79 data
80 }
81 COption::None => {
82 panic!("called `COption::unwrap()` on a `None` value.");
83 }
84 }
85 }
86
87 #[inline]
94 pub const unsafe fn unwrap_unchecked(self) -> TValue {
95 match &self {
96 COption::Some(value) => {
97 let data = unsafe { ptr::read(value) };
98 forget(self);
99 data
100 }
101 COption::None => {
102 unsafe { core::hint::unreachable_unchecked() };
103 }
104 }
105 }
106
107 #[inline]
109 pub const fn into_option(self) -> Option<TValue> {
110 match &self {
111 COption::Some(value) => {
112 let data = unsafe { ptr::read(value) };
113 forget(self);
114 Some(data)
115 }
116 COption::None => {
117 forget(self);
118 None
119 }
120 }
121 }
122
123 #[inline]
125 #[allow(clippy::single_match_else)]
126 pub const fn from_option(option: Option<TValue>) -> Self {
127 match &option {
128 Some(value) => {
129 let data = unsafe { ptr::read(value) };
130 forget(option);
131 COption::Some(data)
132 }
133 None => {
134 forget(option);
135 COption::None
136 }
137 }
138 }
139
140 #[inline]
142 pub const fn as_ref(&self) -> COption<&TValue> {
143 match *self {
144 COption::Some(ref value) => COption::Some(value),
145 COption::None => COption::None,
146 }
147 }
148
149 #[inline]
151 pub const fn as_mut(&mut self) -> COption<&mut TValue> {
152 match *self {
153 COption::Some(ref mut value) => COption::Some(value),
154 COption::None => COption::None,
155 }
156 }
157}
158
159impl<TValue: ReprC> From<Option<TValue>> for COption<TValue> {
160 fn from(option: Option<TValue>) -> Self {
161 COption::from_option(option)
162 }
163}
164
165impl<TValue: ReprC> From<COption<TValue>> for Option<TValue> {
166 fn from(option: COption<TValue>) -> Self {
167 option.into_option()
168 }
169}
170
171impl<TValue: ReprC> Default for COption<TValue> {
172 fn default() -> Self {
173 COption::None
174 }
175}
176
177impl<TValue: ReprC + Clone> Clone for COption<TValue> {
178 fn clone(&self) -> Self {
179 match self {
180 COption::Some(value) => COption::Some(value.clone()),
181 COption::None => COption::None,
182 }
183 }
184}
185
186impl<TValue: ReprC + TryClone> TryClone for COption<TValue> {
187 type Error = <TValue as TryClone>::Error;
188 fn try_clone(&self) -> Result<Self, Self::Error> {
189 match self {
190 COption::Some(value) => Ok(COption::Some(value.try_clone()?)),
191 COption::None => Ok(COption::None),
192 }
193 }
194}
195
196impl<TValue: ReprC + PartialEq> PartialEq for COption<TValue> {
197 fn eq(&self, other: &Self) -> bool {
198 match (self, other) {
199 (Self::Some(l0), Self::Some(r0)) => l0 == r0,
200 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
201 }
202 }
203}
204
205impl<TValue: ReprC + Eq> Eq for COption<TValue> {}
206
207impl<TValue: ReprC + Hash> Hash for COption<TValue> {
208 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
209 core::mem::discriminant(self).hash(state);
210 if let COption::Some(value) = self {
211 value.hash(state);
212 }
213 }
214}
215
216impl<TValue: ReprC + Display> Display for COption<TValue> {
217 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
218 match self {
219 COption::Some(value) => {
220 f.write_str("Some(")?;
221 value.fmt(f)?;
222 f.write_str(")")?;
223 Ok(())
224 }
225 COption::None => write!(f, "None"),
226 }
227 }
228}