apple_quant_algorithmic/volume/
zeroable.rs1mod 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 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 None
45 } else {
46 t
47 };
48
49 Self(ZeroableType::new(t))
50 }
51
52 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
149impl<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
162impl<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
172impl<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
185impl<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}