gstreamer/format/
signed.rs
1use std::fmt;
4
5use super::{Format, FormattedValueNoneBuilder};
6use crate::utils::Displayable;
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub enum Signed<T> {
18 Negative(T),
19 Positive(T),
20}
21
22impl<T> Signed<T> {
23 #[inline]
24 pub fn is_positive(self) -> bool {
25 matches!(self, Signed::Positive(_))
26 }
27
28 #[inline]
32 pub fn positive(self) -> Option<T> {
33 match self {
34 Signed::Positive(val) => Some(val),
35 Signed::Negative(_) => None,
36 }
37 }
38
39 #[inline]
43 pub fn positive_or<E>(self, err: E) -> Result<T, E> {
44 match self {
45 Signed::Positive(val) => Ok(val),
46 Signed::Negative(_) => Err(err),
47 }
48 }
49
50 #[inline]
54 pub fn positive_or_else<E, F: FnOnce(T) -> E>(self, err: F) -> Result<T, E> {
55 match self {
56 Signed::Positive(val) => Ok(val),
57 Signed::Negative(val) => Err(err(val)),
58 }
59 }
60
61 #[inline]
62 pub fn is_negative(self) -> bool {
63 matches!(self, Signed::Negative(_))
64 }
65
66 #[inline]
70 pub fn negative(self) -> Option<T> {
71 match self {
72 Signed::Negative(val) => Some(val),
73 Signed::Positive(_) => None,
74 }
75 }
76
77 #[inline]
81 pub fn negative_or<E>(self, err: E) -> Result<T, E> {
82 match self {
83 Signed::Negative(val) => Ok(val),
84 Signed::Positive(_) => Err(err),
85 }
86 }
87
88 #[inline]
92 pub fn negative_or_else<E, F: FnOnce(T) -> E>(self, err: F) -> Result<T, E> {
93 match self {
94 Signed::Negative(val) => Ok(val),
95 Signed::Positive(val) => Err(err(val)),
96 }
97 }
98
99 #[inline]
102 pub fn abs(self) -> T {
103 match self {
104 Signed::Positive(val) | Signed::Negative(val) => val,
105 }
106 }
107}
108
109impl<T> std::ops::Neg for Signed<T> {
110 type Output = Signed<T>;
111
112 #[inline]
113 fn neg(self) -> Self {
114 match self {
115 Signed::Positive(val) => Signed::Negative(val),
116 Signed::Negative(val) => Signed::Positive(val),
117 }
118 }
119}
120
121pub trait SignedIntrinsic {}
122
123impl<T> fmt::Display for Signed<T>
124where
125 T: fmt::Display + SignedIntrinsic,
126{
127 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128 use std::fmt::Write;
129
130 let (sign, val) = match self {
131 Signed::Positive(val) => ('+', val),
132 Signed::Negative(val) => ('-', val),
133 };
134
135 f.write_char(sign)?;
136 fmt::Display::fmt(&val, f)
137 }
138}
139
140impl<T> Displayable for Signed<T>
141where
142 T: fmt::Display + SignedIntrinsic,
143{
144 type DisplayImpl = Signed<T>;
145
146 fn display(self) -> Self::DisplayImpl {
147 self
148 }
149}
150
151impl<T> Signed<Option<T>> {
152 #[inline]
157 pub fn transpose(self) -> Option<Signed<T>> {
158 use Signed::*;
159
160 match self {
161 Positive(Some(val)) => Some(Positive(val)),
162 Negative(Some(val)) => Some(Negative(val)),
163 _ => None,
164 }
165 }
166}
167
168pub struct DisplayableOptionSigned<T>(Option<Signed<T>>);
169
170impl<T> fmt::Display for DisplayableOptionSigned<T>
171where
172 T: fmt::Display + SignedIntrinsic,
173 Option<T>: Displayable,
174{
175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176 match self.0 {
177 Some(ref signed) => fmt::Display::fmt(signed, f),
178 None => fmt::Display::fmt(&Option::<T>::None.display(), f),
179 }
180 }
181}
182
183impl<T> Displayable for Option<Signed<T>>
184where
185 T: fmt::Display + SignedIntrinsic,
186 Option<T>: Displayable,
187{
188 type DisplayImpl = DisplayableOptionSigned<T>;
189
190 fn display(self) -> Self::DisplayImpl {
191 DisplayableOptionSigned(self)
192 }
193}
194
195impl<T> Displayable for Signed<Option<T>>
196where
197 T: fmt::Display + SignedIntrinsic,
198 Option<T>: Displayable,
199{
200 type DisplayImpl = DisplayableOptionSigned<T>;
201
202 fn display(self) -> Self::DisplayImpl {
203 DisplayableOptionSigned(self.transpose())
204 }
205}
206
207pub trait UnsignedIntoSigned: Copy + Sized {
210 type Signed;
211
212 fn into_signed(self, sign: i32) -> Self::Signed {
215 if sign.is_positive() {
216 self.into_positive()
217 } else {
218 self.into_negative()
219 }
220 }
221
222 fn into_positive(self) -> Self::Signed;
225
226 fn into_negative(self) -> Self::Signed;
229}
230
231impl_unsigned_int_into_signed!(u64);
232impl_signed_ops!(u64);
233impl_signed_div_mul!(u64);
234impl_signed_int_into_signed!(u64);
235
236impl_unsigned_int_into_signed!(u32);
237impl_signed_ops!(u32);
238impl_signed_div_mul!(u32);
239impl_signed_int_into_signed!(u32);
240
241impl_unsigned_int_into_signed!(usize);
242impl_signed_ops!(usize);
243impl_signed_div_mul!(usize);
244impl_signed_int_into_signed!(usize);
245
246pub trait NoneSignedBuilder: FormattedValueNoneBuilder {
247 type Signed;
248
249 fn none_signed() -> Self::Signed;
258
259 fn none_signed_for_format(format: Format) -> Self::Signed;
269}
270
271impl<T> NoneSignedBuilder for T
272where
273 T: UnsignedIntoSigned + FormattedValueNoneBuilder,
274{
275 type Signed = <T as UnsignedIntoSigned>::Signed;
276
277 #[inline]
278 fn none_signed() -> Self::Signed {
279 Self::none().into_positive()
280 }
281
282 #[inline]
283 fn none_signed_for_format(format: Format) -> Self::Signed {
284 skip_assert_initialized!();
285 Self::none_for_format(format).into_positive()
286 }
287}