1use std::fmt::{self, Write};
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)]
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 fmt::Debug for GenericFormattedValue {
135 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136 let specific: Option<&dyn fmt::Debug> = match &self {
137 Self::Undefined(val) => {
138 f.write_str("Undefined(")?;
139 val.fmt(f)?;
140 return f.write_char(')');
141 }
142 Self::Other(format, val) => {
143 fmt::write(f, format_args!("{:?}(", format))?;
144 val.fmt(f)?;
145 return f.write_char(')');
146 }
147 Self::Time(val) => {
148 if let Some(inner) = val {
149 f.write_str("Time(")?;
150 inner.display().fmt(f)?;
151 return f.write_char(')');
152 } else {
153 return f.write_str("Time(None)");
154 }
155 }
156 Self::Default(val) => val.as_ref().map(|inner| inner as &dyn fmt::Debug),
157 Self::Bytes(val) => val.as_ref().map(|inner| inner as &dyn fmt::Debug),
158 Self::Buffers(val) => val.as_ref().map(|inner| inner as &dyn fmt::Debug),
159 Self::Percent(val) => val.as_ref().map(|inner| inner as &dyn fmt::Debug),
160 };
161
162 if let Some(inner) = specific {
163 inner.fmt(f)
164 } else {
165 fmt::write(f, format_args!("{:?}(None)", self.format()))
166 }
167 }
168}
169
170impl Displayable for GenericFormattedValue {
171 type DisplayImpl = Self;
172 fn display(self) -> Self {
173 self
174 }
175}
176
177impl GenericFormattedValue {
178 #[inline]
179 pub fn new(format: Format, value: i64) -> Self {
180 skip_assert_initialized!();
181 match format {
182 Format::Undefined => Self::Undefined(value.into()),
183 Format::Default => Self::Default(unsafe { FromGlib::from_glib(value) }),
184 Format::Bytes => Self::Bytes(unsafe { FromGlib::from_glib(value) }),
185 Format::Time => Self::Time(unsafe { FromGlib::from_glib(value) }),
186 Format::Buffers => Self::Buffers(unsafe { FromGlib::from_glib(value) }),
187 Format::Percent => Self::Percent(unsafe { FromGlib::from_glib(value) }),
188 Format::__Unknown(_) => Self::Other(format, unsafe { FromGlib::from_glib(value) }),
189 }
190 }
191
192 #[doc(alias = "get_format")]
193 #[inline]
194 pub fn format(&self) -> Format {
195 match *self {
196 Self::Undefined(_) => Format::Undefined,
197 Self::Default(_) => Format::Default,
198 Self::Bytes(_) => Format::Bytes,
199 Self::Time(_) => Format::Time,
200 Self::Buffers(_) => Format::Buffers,
201 Self::Percent(_) => Format::Percent,
202 Self::Other(f, _) => f,
203 }
204 }
205
206 #[doc(alias = "get_value")]
207 #[inline]
208 pub fn value(&self) -> i64 {
209 unsafe {
210 match *self {
211 Self::Undefined(v) => *v,
212 Self::Default(v) => v.into_raw_value(),
213 Self::Bytes(v) => v.into_raw_value(),
214 Self::Time(v) => v.into_raw_value(),
215 Self::Buffers(v) => v.into_raw_value(),
216 Self::Percent(v) => v.into_raw_value(),
217 Self::Other(_, v) => v.into_glib() as i64,
218 }
219 }
220 }
221}
222
223impl FormattedValue for GenericFormattedValue {
224 type FullRange = GenericFormattedValue;
228
229 #[inline]
230 fn default_format() -> Format {
231 Format::Undefined
232 }
233
234 #[inline]
235 fn format(&self) -> Format {
236 self.format()
237 }
238
239 #[inline]
240 fn is_some(&self) -> bool {
241 match self {
242 Self::Undefined(_) => true,
243 Self::Default(v) => v.is_some(),
244 Self::Bytes(v) => v.is_some(),
245 Self::Time(v) => v.is_some(),
246 Self::Buffers(v) => v.is_some(),
247 Self::Percent(v) => v.is_some(),
248 Self::Other(_, v) => v.is_some(),
249 }
250 }
251
252 #[inline]
253 unsafe fn into_raw_value(self) -> i64 {
254 self.value()
255 }
256}
257
258impl FormattedValueFullRange for GenericFormattedValue {
259 #[inline]
260 unsafe fn from_raw(format: Format, value: i64) -> Self {
261 GenericFormattedValue::new(format, value)
262 }
263}
264
265impl FormattedValueIntrinsic for GenericFormattedValue {}
266impl SignedIntrinsic for GenericFormattedValue {}
267
268impl FormattedValueNoneBuilder for GenericFormattedValue {
269 #[track_caller]
270 fn none() -> Self {
271 panic!(concat!(
272 "`GenericFormattedValue` can't build `None` without knowing",
273 "the target format. Use `GenericFormattedValue::none_for_format`",
274 ));
275 }
276
277 #[track_caller]
278 #[inline]
279 fn none_for_format(format: Format) -> Self {
280 skip_assert_initialized!();
281 match format {
282 Format::Undefined => panic!("`None` can't be represented by `Undefined`"),
283 Format::Default => Self::Default(None),
284 Format::Bytes => Self::Bytes(None),
285 Format::Time => Self::Time(None),
286 Format::Buffers => Self::Buffers(None),
287 Format::Percent => Self::Percent(None),
288 unknown => Self::Other(unknown, Other::NONE),
289 }
290 }
291}
292
293impl UnsignedIntoSigned for GenericFormattedValue {
294 type Signed = GenericSignedFormattedValue;
295
296 #[track_caller]
297 #[inline]
298 fn into_positive(self) -> Self::Signed {
299 use Signed::Positive;
300 match self {
301 Self::Undefined(_) => {
302 unimplemented!("`GenericFormattedValue::Undefined` is already signed")
303 }
304 Self::Default(val) => Self::Signed::Default(val.map(Positive)),
305 Self::Bytes(val) => Self::Signed::Bytes(val.map(Positive)),
306 Self::Time(val) => Self::Signed::Time(val.map(Positive)),
307 Self::Buffers(val) => Self::Signed::Buffers(val.map(Positive)),
308 Self::Percent(val) => Self::Signed::Percent(val.map(Positive)),
309 Self::Other(format, val) => Self::Signed::Other(format, val.map(Positive)),
310 }
311 }
312
313 #[track_caller]
314 #[inline]
315 fn into_negative(self) -> Self::Signed {
316 use Signed::Negative;
317 match self {
318 Self::Undefined(_) => {
319 unimplemented!("`GenericFormattedValue::Undefined` is already signed")
320 }
321 Self::Default(val) => Self::Signed::Default(val.map(Negative)),
322 Self::Bytes(val) => Self::Signed::Bytes(val.map(Negative)),
323 Self::Time(val) => Self::Signed::Time(val.map(Negative)),
324 Self::Buffers(val) => Self::Signed::Buffers(val.map(Negative)),
325 Self::Percent(val) => Self::Signed::Percent(val.map(Negative)),
326 Self::Other(format, val) => Self::Signed::Other(format, val.map(Negative)),
327 }
328 }
329}
330
331impl CompatibleFormattedValue<GenericFormattedValue> for GenericFormattedValue {
332 type Original = Self;
333 #[inline]
334 fn try_into_checked(self, other: GenericFormattedValue) -> Result<Self, FormattedValueError> {
335 skip_assert_initialized!();
336 if self.format() == other.format() {
337 Ok(self)
338 } else {
339 Err(FormattedValueError(self.format()))
340 }
341 }
342
343 #[inline]
344 fn try_into_checked_explicit(
345 self,
346 format: Format,
347 ) -> Result<Self::Original, FormattedValueError> {
348 skip_assert_initialized!();
349 if self.format() == format {
350 Ok(self)
351 } else {
352 Err(FormattedValueError(self.format()))
353 }
354 }
355}
356
357#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
358#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
359pub enum GenericSignedFormattedValue {
360 Default(Option<Signed<Default>>),
361 Bytes(Option<Signed<Bytes>>),
362 Time(Option<Signed<ClockTime>>),
363 Buffers(Option<Signed<Buffers>>),
364 Percent(Option<Signed<Percent>>),
365 Other(Format, Option<Signed<Other>>),
366}
367
368impl GenericSignedFormattedValue {
369 #[doc(alias = "get_format")]
370 #[inline]
371 pub fn format(&self) -> Format {
372 match *self {
373 Self::Default(_) => Format::Default,
374 Self::Bytes(_) => Format::Bytes,
375 Self::Time(_) => Format::Time,
376 Self::Buffers(_) => Format::Buffers,
377 Self::Percent(_) => Format::Percent,
378 Self::Other(format, _) => format,
379 }
380 }
381
382 #[inline]
383 pub fn abs(self) -> GenericFormattedValue {
384 use GenericFormattedValue as Unsigned;
385 match self {
386 Self::Default(opt_signed) => Unsigned::Default(opt_signed.map(Signed::abs)),
387 Self::Bytes(opt_signed) => Unsigned::Bytes(opt_signed.map(Signed::abs)),
388 Self::Time(opt_signed) => Unsigned::Time(opt_signed.map(Signed::abs)),
389 Self::Buffers(opt_signed) => Unsigned::Buffers(opt_signed.map(Signed::abs)),
390 Self::Percent(opt_signed) => Unsigned::Percent(opt_signed.map(Signed::abs)),
391 Self::Other(format, opt_signed) => Unsigned::Other(format, opt_signed.map(Signed::abs)),
392 }
393 }
394
395 #[inline]
396 pub fn is_some(&self) -> bool {
397 match self {
398 Self::Default(v) => v.is_some(),
399 Self::Bytes(v) => v.is_some(),
400 Self::Time(v) => v.is_some(),
401 Self::Buffers(v) => v.is_some(),
402 Self::Percent(v) => v.is_some(),
403 Self::Other(_, v) => v.is_some(),
404 }
405 }
406
407 #[inline]
408 pub fn is_none(&self) -> bool {
409 !self.is_some()
410 }
411
412 #[track_caller]
413 #[inline]
414 pub fn none_for_format(format: Format) -> Self {
415 skip_assert_initialized!();
416 match format {
417 Format::Default => Self::Default(None),
418 Format::Bytes => Self::Bytes(None),
419 Format::Time => Self::Time(None),
420 Format::Buffers => Self::Buffers(None),
421 Format::Percent => Self::Percent(None),
422 Format::Undefined => {
423 panic!("`Undefined` is already signed, use `GenericFormattedValue`")
424 }
425 other => Self::Other(other, None),
426 }
427 }
428}
429
430macro_rules! impl_gsfv_fn_opt_ret(
431 ($fn:ident(self) -> Option<$ret_ty:ty>) => {
432 #[inline]
433 pub fn $fn(self) -> Option<$ret_ty> {
434 match self {
435 Self::Default(opt_signed) => opt_signed.map(|signed| signed.$fn()),
436 Self::Bytes(opt_signed) => opt_signed.map(|signed| signed.$fn()),
437 Self::Time(opt_signed) => opt_signed.map(|signed| signed.$fn()),
438 Self::Buffers(opt_signed) => opt_signed.map(|signed| signed.$fn()),
439 Self::Percent(opt_signed) => opt_signed.map(|signed| signed.$fn()),
440 Self::Other(_, opt_signed) => opt_signed.map(|signed| signed.$fn()),
441 }
442 }
443 };
444);
445
446impl GenericSignedFormattedValue {
447 impl_gsfv_fn_opt_ret!(is_positive(self) -> Option<bool>);
448 impl_gsfv_fn_opt_ret!(is_negative(self) -> Option<bool>);
449 impl_gsfv_fn_opt_ret!(signum(self) -> Option<i32>);
450}
451
452impl std::ops::Neg for GenericSignedFormattedValue {
453 type Output = Self;
454
455 #[inline]
456 fn neg(self) -> Self {
457 use std::ops::Neg;
458 match self {
459 Self::Default(opt_signed) => Self::Default(opt_signed.map(Neg::neg)),
460 Self::Bytes(opt_signed) => Self::Bytes(opt_signed.map(Neg::neg)),
461 Self::Time(opt_signed) => Self::Time(opt_signed.map(Neg::neg)),
462 Self::Buffers(opt_signed) => Self::Buffers(opt_signed.map(Neg::neg)),
463 Self::Percent(opt_signed) => Self::Percent(opt_signed.map(Neg::neg)),
464 Self::Other(format, opt_signed) => Self::Other(format, opt_signed.map(Neg::neg)),
465 }
466 }
467}
468
469impl fmt::Display for GenericSignedFormattedValue {
470 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
471 match self {
472 Self::Default(opt_signed) => opt_signed.display().fmt(f),
473 Self::Bytes(opt_signed) => opt_signed.display().fmt(f),
474 Self::Time(opt_signed) => opt_signed.display().fmt(f),
475 Self::Buffers(opt_signed) => opt_signed.display().fmt(f),
476 Self::Percent(opt_signed) => opt_signed.display().fmt(f),
477 Self::Other(format, opt_signed) => {
478 opt_signed.display().fmt(f)?;
479 fmt::Write::write_char(f, ' ')?;
480 fmt::Display::fmt(&format, f)
481 }
482 }
483 }
484}
485
486impl Displayable for GenericSignedFormattedValue {
487 type DisplayImpl = Self;
488
489 fn display(self) -> Self::DisplayImpl {
490 self
491 }
492}
493
494#[cfg(test)]
495mod tests {
496 use super::*;
497
498 #[test]
499 #[allow(clippy::eq_op, clippy::op_ref)]
500 fn other() {
501 use opt_ops::prelude::*;
505
506 let other_none: Option<Other> = Other::try_from(u64::MAX).ok();
507 assert!(other_none.is_none());
508
509 let other_10 = Other::from_u64(10);
510 let other_20 = Other::from_usize(20);
511 let other_30 = 30.other_format();
512
513 assert_eq!(other_10 + other_20, other_30);
514 assert_eq!(other_30 - other_20, other_10);
515
516 assert!(other_10 < Other::MAX);
517
518 assert_eq!(Some(other_10).opt_add(other_20), Some(other_30));
519 }
520
521 #[test]
522 #[allow(clippy::eq_op, clippy::op_ref)]
523 fn generic_other() {
524 let gen_other_42: GenericFormattedValue =
525 GenericFormattedValue::new(Format::__Unknown(128), 42);
526 assert_eq!(
527 gen_other_42,
528 GenericFormattedValue::Other(Format::__Unknown(128), Other::try_from(42).ok())
529 );
530 assert_eq!(gen_other_42.format(), Format::__Unknown(128));
531 assert_eq!(gen_other_42.value(), 42);
532 assert!(gen_other_42.is_some());
533
534 let other_none: Option<Other> = Other::NONE;
535 assert!(other_none.is_none());
536
537 let gen_other_none: GenericFormattedValue =
538 GenericFormattedValue::none_for_format(Format::__Unknown(128));
539 assert!(gen_other_none.is_none());
540 assert_eq!(
541 gen_other_none,
542 GenericFormattedValue::Other(Format::__Unknown(128), None)
543 );
544 }
545
546 #[test]
547 #[allow(clippy::eq_op, clippy::op_ref)]
548 fn generic_signed_other() {
549 let gen_other_42: GenericFormattedValue =
550 GenericFormattedValue::new(Format::__Unknown(128), 42);
551
552 let p_gen_other_42 = gen_other_42.into_positive();
553 assert_eq!(
554 p_gen_other_42,
555 GenericSignedFormattedValue::Other(
556 Format::__Unknown(128),
557 Some(Signed::Positive(42.other_format())),
558 ),
559 );
560
561 let n_gen_other_42 = gen_other_42.into_negative();
562 assert_eq!(
563 n_gen_other_42,
564 GenericSignedFormattedValue::Other(
565 Format::__Unknown(128),
566 Some(Signed::Negative(42.other_format())),
567 ),
568 );
569 }
570}