1use std::fmt;
4
5use glib::translate::{FromGlib, GlibNoneError, IntoGlib, OptionIntoGlib, TryFromGlib};
6
7use super::{
8 Buffers, Bytes, ClockTime, CompatibleFormattedValue, Default, Format, FormattedValue,
9 FormattedValueError, FormattedValueFullRange, FormattedValueIntrinsic,
10 FormattedValueNoneBuilder, Percent, Signed, SignedIntrinsic, Undefined, UnsignedIntoSigned,
11};
12use crate::utils::Displayable;
13
14#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
15pub struct Other(u64);
16impl Other {
17 pub const MAX: Self = Self(u64::MAX - 1);
18}
19
20impl Other {
21 #[track_caller]
29 #[inline]
30 pub const fn from_u64(quantity: u64) -> Self {
31 if quantity == u64::MAX {
32 panic!("`Other` value out of range");
33 }
34
35 Other(quantity)
36 }
37
38 #[track_caller]
46 #[inline]
47 pub fn from_usize(quantity: usize) -> Self {
48 Other::from_u64(quantity.try_into().unwrap())
50 }
51}
52
53impl_common_ops_for_newtype_uint!(Other, u64);
54impl_signed_div_mul!(Other, u64);
55impl_signed_int_into_signed!(Other, u64);
56option_glib_newtype_from_to!(Other, u64::MAX);
57glib_newtype_display!(Other, DisplayableOptionOther);
58
59impl TryFrom<u64> for Other {
60 type Error = GlibNoneError;
61 #[inline]
62 fn try_from(val: u64) -> Result<Self, GlibNoneError> {
63 skip_assert_initialized!();
64 unsafe { Self::try_from_glib(val) }
65 }
66}
67
68impl TryFromGlib<i64> for Other {
69 type Error = GlibNoneError;
70 #[inline]
71 unsafe fn try_from_glib(val: i64) -> Result<Self, GlibNoneError> {
72 unsafe {
73 skip_assert_initialized!();
74 Self::try_from_glib(val as u64)
75 }
76 }
77}
78
79impl TryFrom<Other> for usize {
80 type Error = std::num::TryFromIntError;
81
82 fn try_from(value: Other) -> Result<Self, Self::Error> {
83 value.0.try_into()
84 }
85}
86
87pub trait OtherFormatConstructor {
91 fn other_format(self) -> Other;
94}
95
96impl OtherFormatConstructor for u64 {
97 #[track_caller]
98 #[inline]
99 fn other_format(self) -> Other {
100 Other::from_u64(self)
101 }
102}
103
104#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
105#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
106pub enum GenericFormattedValue {
107 Undefined(Undefined),
108 Default(Option<Default>),
109 Bytes(Option<Bytes>),
110 Time(Option<ClockTime>),
111 Buffers(Option<Buffers>),
112 Percent(Option<Percent>),
113 Other(Format, Option<Other>),
114}
115
116impl fmt::Display for GenericFormattedValue {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 match self {
119 Self::Undefined(val) => val.fmt(f),
120 Self::Default(val) => val.display().fmt(f),
121 Self::Bytes(val) => val.display().fmt(f),
122 Self::Time(val) => val.display().fmt(f),
123 Self::Buffers(val) => val.display().fmt(f),
124 Self::Percent(val) => val.display().fmt(f),
125 Self::Other(format, val) => {
126 val.display().fmt(f)?;
127 fmt::Write::write_char(f, ' ')?;
128 fmt::Display::fmt(&format, f)
129 }
130 }
131 }
132}
133
134impl Displayable for GenericFormattedValue {
135 type DisplayImpl = Self;
136 fn display(self) -> Self {
137 self
138 }
139}
140
141impl GenericFormattedValue {
142 #[inline]
143 pub fn new(format: Format, value: i64) -> Self {
144 skip_assert_initialized!();
145 match format {
146 Format::Undefined => Self::Undefined(value.into()),
147 Format::Default => Self::Default(unsafe { FromGlib::from_glib(value) }),
148 Format::Bytes => Self::Bytes(unsafe { FromGlib::from_glib(value) }),
149 Format::Time => Self::Time(unsafe { FromGlib::from_glib(value) }),
150 Format::Buffers => Self::Buffers(unsafe { FromGlib::from_glib(value) }),
151 Format::Percent => Self::Percent(unsafe { FromGlib::from_glib(value) }),
152 Format::__Unknown(_) => Self::Other(format, unsafe { FromGlib::from_glib(value) }),
153 }
154 }
155
156 #[doc(alias = "get_format")]
157 #[inline]
158 pub fn format(&self) -> Format {
159 match *self {
160 Self::Undefined(_) => Format::Undefined,
161 Self::Default(_) => Format::Default,
162 Self::Bytes(_) => Format::Bytes,
163 Self::Time(_) => Format::Time,
164 Self::Buffers(_) => Format::Buffers,
165 Self::Percent(_) => Format::Percent,
166 Self::Other(f, _) => f,
167 }
168 }
169
170 #[doc(alias = "get_value")]
171 #[inline]
172 pub fn value(&self) -> i64 {
173 unsafe {
174 match *self {
175 Self::Undefined(v) => *v,
176 Self::Default(v) => v.into_raw_value(),
177 Self::Bytes(v) => v.into_raw_value(),
178 Self::Time(v) => v.into_raw_value(),
179 Self::Buffers(v) => v.into_raw_value(),
180 Self::Percent(v) => v.into_raw_value(),
181 Self::Other(_, v) => v.into_glib() as i64,
182 }
183 }
184 }
185}
186
187impl FormattedValue for GenericFormattedValue {
188 type FullRange = GenericFormattedValue;
192
193 #[inline]
194 fn default_format() -> Format {
195 Format::Undefined
196 }
197
198 #[inline]
199 fn format(&self) -> Format {
200 self.format()
201 }
202
203 #[inline]
204 fn is_some(&self) -> bool {
205 match self {
206 Self::Undefined(_) => true,
207 Self::Default(v) => v.is_some(),
208 Self::Bytes(v) => v.is_some(),
209 Self::Time(v) => v.is_some(),
210 Self::Buffers(v) => v.is_some(),
211 Self::Percent(v) => v.is_some(),
212 Self::Other(_, v) => v.is_some(),
213 }
214 }
215
216 #[inline]
217 unsafe fn into_raw_value(self) -> i64 {
218 self.value()
219 }
220}
221
222impl FormattedValueFullRange for GenericFormattedValue {
223 #[inline]
224 unsafe fn from_raw(format: Format, value: i64) -> Self {
225 GenericFormattedValue::new(format, value)
226 }
227}
228
229impl FormattedValueIntrinsic for GenericFormattedValue {}
230impl SignedIntrinsic for GenericFormattedValue {}
231
232impl FormattedValueNoneBuilder for GenericFormattedValue {
233 #[track_caller]
234 fn none() -> Self {
235 panic!(concat!(
236 "`GenericFormattedValue` can't build `None` without knowing",
237 "the target format. Use `GenericFormattedValue::none_for_format`",
238 ));
239 }
240
241 #[track_caller]
242 #[inline]
243 fn none_for_format(format: Format) -> Self {
244 skip_assert_initialized!();
245 match format {
246 Format::Undefined => panic!("`None` can't be represented by `Undefined`"),
247 Format::Default => Self::Default(None),
248 Format::Bytes => Self::Bytes(None),
249 Format::Time => Self::Time(None),
250 Format::Buffers => Self::Buffers(None),
251 Format::Percent => Self::Percent(None),
252 unknown => Self::Other(unknown, Other::NONE),
253 }
254 }
255}
256
257impl UnsignedIntoSigned for GenericFormattedValue {
258 type Signed = GenericSignedFormattedValue;
259
260 #[track_caller]
261 #[inline]
262 fn into_positive(self) -> Self::Signed {
263 use Signed::Positive;
264 match self {
265 Self::Undefined(_) => {
266 unimplemented!("`GenericFormattedValue::Undefined` is already signed")
267 }
268 Self::Default(val) => Self::Signed::Default(val.map(Positive)),
269 Self::Bytes(val) => Self::Signed::Bytes(val.map(Positive)),
270 Self::Time(val) => Self::Signed::Time(val.map(Positive)),
271 Self::Buffers(val) => Self::Signed::Buffers(val.map(Positive)),
272 Self::Percent(val) => Self::Signed::Percent(val.map(Positive)),
273 Self::Other(format, val) => Self::Signed::Other(format, val.map(Positive)),
274 }
275 }
276
277 #[track_caller]
278 #[inline]
279 fn into_negative(self) -> Self::Signed {
280 use Signed::Negative;
281 match self {
282 Self::Undefined(_) => {
283 unimplemented!("`GenericFormattedValue::Undefined` is already signed")
284 }
285 Self::Default(val) => Self::Signed::Default(val.map(Negative)),
286 Self::Bytes(val) => Self::Signed::Bytes(val.map(Negative)),
287 Self::Time(val) => Self::Signed::Time(val.map(Negative)),
288 Self::Buffers(val) => Self::Signed::Buffers(val.map(Negative)),
289 Self::Percent(val) => Self::Signed::Percent(val.map(Negative)),
290 Self::Other(format, val) => Self::Signed::Other(format, val.map(Negative)),
291 }
292 }
293}
294
295impl CompatibleFormattedValue<GenericFormattedValue> for GenericFormattedValue {
296 type Original = Self;
297 #[inline]
298 fn try_into_checked(self, other: GenericFormattedValue) -> Result<Self, FormattedValueError> {
299 skip_assert_initialized!();
300 if self.format() == other.format() {
301 Ok(self)
302 } else {
303 Err(FormattedValueError(self.format()))
304 }
305 }
306
307 #[inline]
308 fn try_into_checked_explicit(
309 self,
310 format: Format,
311 ) -> Result<Self::Original, FormattedValueError> {
312 skip_assert_initialized!();
313 if self.format() == format {
314 Ok(self)
315 } else {
316 Err(FormattedValueError(self.format()))
317 }
318 }
319}
320
321#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
322#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
323pub enum GenericSignedFormattedValue {
324 Default(Option<Signed<Default>>),
325 Bytes(Option<Signed<Bytes>>),
326 Time(Option<Signed<ClockTime>>),
327 Buffers(Option<Signed<Buffers>>),
328 Percent(Option<Signed<Percent>>),
329 Other(Format, Option<Signed<Other>>),
330}
331
332impl GenericSignedFormattedValue {
333 #[doc(alias = "get_format")]
334 #[inline]
335 pub fn format(&self) -> Format {
336 match *self {
337 Self::Default(_) => Format::Default,
338 Self::Bytes(_) => Format::Bytes,
339 Self::Time(_) => Format::Time,
340 Self::Buffers(_) => Format::Buffers,
341 Self::Percent(_) => Format::Percent,
342 Self::Other(format, _) => format,
343 }
344 }
345
346 #[inline]
347 pub fn abs(self) -> GenericFormattedValue {
348 use GenericFormattedValue as Unsigned;
349 match self {
350 Self::Default(opt_signed) => Unsigned::Default(opt_signed.map(Signed::abs)),
351 Self::Bytes(opt_signed) => Unsigned::Bytes(opt_signed.map(Signed::abs)),
352 Self::Time(opt_signed) => Unsigned::Time(opt_signed.map(Signed::abs)),
353 Self::Buffers(opt_signed) => Unsigned::Buffers(opt_signed.map(Signed::abs)),
354 Self::Percent(opt_signed) => Unsigned::Percent(opt_signed.map(Signed::abs)),
355 Self::Other(format, opt_signed) => Unsigned::Other(format, opt_signed.map(Signed::abs)),
356 }
357 }
358
359 #[inline]
360 pub fn is_some(&self) -> bool {
361 match self {
362 Self::Default(v) => v.is_some(),
363 Self::Bytes(v) => v.is_some(),
364 Self::Time(v) => v.is_some(),
365 Self::Buffers(v) => v.is_some(),
366 Self::Percent(v) => v.is_some(),
367 Self::Other(_, v) => v.is_some(),
368 }
369 }
370
371 #[inline]
372 pub fn is_none(&self) -> bool {
373 !self.is_some()
374 }
375
376 #[track_caller]
377 #[inline]
378 pub fn none_for_format(format: Format) -> Self {
379 skip_assert_initialized!();
380 match format {
381 Format::Default => Self::Default(None),
382 Format::Bytes => Self::Bytes(None),
383 Format::Time => Self::Time(None),
384 Format::Buffers => Self::Buffers(None),
385 Format::Percent => Self::Percent(None),
386 Format::Undefined => {
387 panic!("`Undefined` is already signed, use `GenericFormattedValue`")
388 }
389 other => Self::Other(other, None),
390 }
391 }
392}
393
394macro_rules! impl_gsfv_fn_opt_ret(
395 ($fn:ident(self) -> Option<$ret_ty:ty>) => {
396 #[inline]
397 pub fn $fn(self) -> Option<$ret_ty> {
398 match self {
399 Self::Default(opt_signed) => opt_signed.map(|signed| signed.$fn()),
400 Self::Bytes(opt_signed) => opt_signed.map(|signed| signed.$fn()),
401 Self::Time(opt_signed) => opt_signed.map(|signed| signed.$fn()),
402 Self::Buffers(opt_signed) => opt_signed.map(|signed| signed.$fn()),
403 Self::Percent(opt_signed) => opt_signed.map(|signed| signed.$fn()),
404 Self::Other(_, opt_signed) => opt_signed.map(|signed| signed.$fn()),
405 }
406 }
407 };
408);
409
410impl GenericSignedFormattedValue {
411 impl_gsfv_fn_opt_ret!(is_positive(self) -> Option<bool>);
412 impl_gsfv_fn_opt_ret!(is_negative(self) -> Option<bool>);
413 impl_gsfv_fn_opt_ret!(signum(self) -> Option<i32>);
414}
415
416impl std::ops::Neg for GenericSignedFormattedValue {
417 type Output = Self;
418
419 #[inline]
420 fn neg(self) -> Self {
421 use std::ops::Neg;
422 match self {
423 Self::Default(opt_signed) => Self::Default(opt_signed.map(Neg::neg)),
424 Self::Bytes(opt_signed) => Self::Bytes(opt_signed.map(Neg::neg)),
425 Self::Time(opt_signed) => Self::Time(opt_signed.map(Neg::neg)),
426 Self::Buffers(opt_signed) => Self::Buffers(opt_signed.map(Neg::neg)),
427 Self::Percent(opt_signed) => Self::Percent(opt_signed.map(Neg::neg)),
428 Self::Other(format, opt_signed) => Self::Other(format, opt_signed.map(Neg::neg)),
429 }
430 }
431}
432
433impl fmt::Display for GenericSignedFormattedValue {
434 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
435 match self {
436 Self::Default(opt_signed) => opt_signed.display().fmt(f),
437 Self::Bytes(opt_signed) => opt_signed.display().fmt(f),
438 Self::Time(opt_signed) => opt_signed.display().fmt(f),
439 Self::Buffers(opt_signed) => opt_signed.display().fmt(f),
440 Self::Percent(opt_signed) => opt_signed.display().fmt(f),
441 Self::Other(format, opt_signed) => {
442 opt_signed.display().fmt(f)?;
443 fmt::Write::write_char(f, ' ')?;
444 fmt::Display::fmt(&format, f)
445 }
446 }
447 }
448}
449
450impl Displayable for GenericSignedFormattedValue {
451 type DisplayImpl = Self;
452
453 fn display(self) -> Self::DisplayImpl {
454 self
455 }
456}
457
458#[cfg(test)]
459mod tests {
460 use super::*;
461
462 #[test]
463 #[allow(clippy::eq_op, clippy::op_ref)]
464 fn other() {
465 use opt_ops::prelude::*;
469
470 let other_none: Option<Other> = Other::try_from(u64::MAX).ok();
471 assert!(other_none.is_none());
472
473 let other_10 = Other::from_u64(10);
474 let other_20 = Other::from_usize(20);
475 let other_30 = 30.other_format();
476
477 assert_eq!(other_10 + other_20, other_30);
478 assert_eq!(other_30 - other_20, other_10);
479
480 assert!(other_10 < Other::MAX);
481
482 assert_eq!(Some(other_10).opt_add(other_20), Some(other_30));
483 }
484
485 #[test]
486 #[allow(clippy::eq_op, clippy::op_ref)]
487 fn generic_other() {
488 let gen_other_42: GenericFormattedValue =
489 GenericFormattedValue::new(Format::__Unknown(128), 42);
490 assert_eq!(
491 gen_other_42,
492 GenericFormattedValue::Other(Format::__Unknown(128), Other::try_from(42).ok())
493 );
494 assert_eq!(gen_other_42.format(), Format::__Unknown(128));
495 assert_eq!(gen_other_42.value(), 42);
496 assert!(gen_other_42.is_some());
497
498 let other_none: Option<Other> = Other::NONE;
499 assert!(other_none.is_none());
500
501 let gen_other_none: GenericFormattedValue =
502 GenericFormattedValue::none_for_format(Format::__Unknown(128));
503 assert!(gen_other_none.is_none());
504 assert_eq!(
505 gen_other_none,
506 GenericFormattedValue::Other(Format::__Unknown(128), None)
507 );
508 }
509
510 #[test]
511 #[allow(clippy::eq_op, clippy::op_ref)]
512 fn generic_signed_other() {
513 let gen_other_42: GenericFormattedValue =
514 GenericFormattedValue::new(Format::__Unknown(128), 42);
515
516 let p_gen_other_42 = gen_other_42.into_positive();
517 assert_eq!(
518 p_gen_other_42,
519 GenericSignedFormattedValue::Other(
520 Format::__Unknown(128),
521 Some(Signed::Positive(42.other_format())),
522 ),
523 );
524
525 let n_gen_other_42 = gen_other_42.into_negative();
526 assert_eq!(
527 n_gen_other_42,
528 GenericSignedFormattedValue::Other(
529 Format::__Unknown(128),
530 Some(Signed::Negative(42.other_format())),
531 ),
532 );
533 }
534}