Skip to main content

apple_quant_algorithmic/volume/
zeroable.rs

1mod checked;
2mod ext;
3mod unchecked;
4mod volume;
5
6use std::borrow::Borrow;
7
8use std::{
9	ops::{Deref, DerefMut},
10	fmt::Debug, hash::Hash,
11};
12
13use apple_quant_core::{AddUnchecked, SubUnchecked};
14
15pub use checked::*;
16pub use ext::*;
17pub use unchecked::*;
18pub use volume::*;
19
20#[cfg(debug_assertions)]
21pub type ZeroableType<T> = ZeroableChecked<T>;
22
23#[cfg(not(debug_assertions))]
24pub type ZeroableType<T> = ZeroableUnchecked<T>;
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
27pub struct Zeroable<T: ZeroableVolume>(ZeroableType<T>);
28
29impl<T: ZeroableVolume> Zeroable<T> {
30	pub const ZERO: Self = Self(ZeroableType::ZERO);
31
32	/// Always safe regardless of `debug_assertions` and `T` zeroed state.
33	pub fn from_optional(
34		t: Option<T>,
35	) -> Self {
36		#[cfg(not(debug_assertions))]
37		let t = t.unwrap_or(T::ZERO);
38
39		#[cfg(debug_assertions)]
40		let t = if let Some(
41			t,
42		) = t && t.is_zero() {
43			// Sanitize `T` to `None`.
44			None
45		} else {
46			t
47		};
48
49		Self(ZeroableType::new(t))
50	}
51
52	/// Always safe regardless of `debug_assertions` and `T` zeroed state.
53	pub fn from_zeroable(
54		t: T,
55	) -> Self {
56		#[cfg(debug_assertions)]
57		let t = if t.is_zero() {
58			None
59		} else {
60			Some(t)
61		};
62
63		Self(ZeroableType::new(t))
64	}
65
66	pub fn is_zero(
67		&self,
68	) -> bool {
69		self.0.as_optional_nonzero_ref().is_none()
70	}
71}
72
73impl<T: ZeroableVolume> ZeroableExt<T> for Zeroable<T> {
74	fn as_optional_nonzero_ref(
75		&self,
76	) -> Option<&T> {
77		self.0.as_optional_nonzero_ref()
78	}
79
80	fn as_optional_nonzero_mut(
81		&mut self,
82	) -> Option<&mut T> {
83		self.0.as_optional_nonzero_mut()
84	}
85
86	fn into_optional_nonzero(
87		self,
88	) -> Option<T> {
89		self.0.into_optional_nonzero()
90	}
91
92	fn as_zeroable(
93		&self,
94	) -> T {
95		self.0.as_zeroable()
96	}
97
98	fn into_zeroable(
99		self,
100	) -> T {
101		self.0.into_zeroable()
102	}
103
104	fn as_nonzero_unchecked_ref(
105		&self,
106	) -> &T {
107		self.0.as_nonzero_unchecked_ref()
108	}
109
110	fn as_nonzero_unchecked_mut(
111		&mut self,
112	) -> &mut T {
113		self.0.as_nonzero_unchecked_mut()
114	}
115
116	fn into_nonzero_unchecked(
117		self,
118	) -> T {
119		self.0.into_nonzero_unchecked()
120	}
121}
122
123impl<T: ZeroableVolume> Deref for Zeroable<T> {
124	type Target = ZeroableType<T>;
125
126	fn deref(
127		&self,
128	) -> &Self::Target {
129		&self.0
130	}
131}
132
133impl<T: ZeroableVolume> DerefMut for Zeroable<T> {
134	fn deref_mut(
135		&mut self,
136	) -> &mut Self::Target {
137		&mut self.0
138	}
139}
140
141impl<T: ZeroableVolume> From<Zeroable<T>> for Result<Zeroable<T>, ()> {
142	fn from(
143		value: Zeroable<T>,
144	) -> Self {
145		Ok(value)
146	}
147}
148
149// Manual implementation because we only want unchecked impls.
150impl<T: ZeroableVolume> AddUnchecked<Zeroable<T>, Zeroable<T>> for Zeroable<T> {
151	fn add_unchecked(
152		self,
153		rhs: impl Borrow<Zeroable<T>>,
154	) -> Zeroable<T> {
155		let lhs = self.as_zeroable();
156		let rhs = rhs.borrow().as_zeroable();
157
158		Zeroable::from_zeroable(lhs.add_unchecked(rhs))
159	}
160}
161
162// Manual implementation because we only want unchecked impls.
163impl<T: ZeroableVolume> AddUnchecked<Zeroable<T>, Zeroable<T>> for &Zeroable<T> {
164	fn add_unchecked(
165		self,
166		rhs: impl Borrow<Zeroable<T>>,
167	) -> Zeroable<T> {
168		(*self).add_unchecked(rhs)
169	}
170}
171
172// Manual implementation because we only want unchecked impls.
173impl<T: ZeroableVolume> SubUnchecked<Zeroable<T>, Zeroable<T>> for Zeroable<T> {
174	fn sub_unchecked(
175		self,
176		rhs: impl Borrow<Zeroable<T>>,
177	) -> Zeroable<T> {
178		let lhs = self.as_zeroable();
179		let rhs = rhs.borrow().as_zeroable();
180
181		Zeroable::from_zeroable(lhs.sub_unchecked(rhs))
182	}
183}
184
185// Manual implementation because we only want unchecked impls.
186impl<T: ZeroableVolume> SubUnchecked<Zeroable<T>, Zeroable<T>> for &Zeroable<T> {
187	fn sub_unchecked(
188		self,
189		rhs: impl Borrow<Zeroable<T>>,
190	) -> Zeroable<T> {
191		(*self).sub_unchecked(rhs)
192	}
193}