1use glib::translate::{FromGlib, GlibNoneError, IntoGlib, OptionIntoGlib, TryFromGlib};
4
5use super::{
6 Format, FormattedValue, FormattedValueError, FormattedValueFullRange, FormattedValueIntrinsic,
7 FormattedValueNoneBuilder, GenericFormattedValue,
8};
9use crate::ffi;
10
11pub trait SpecificFormattedValue: FormattedValue {}
12
13pub trait SpecificFormattedValueFullRange: FormattedValueFullRange {}
14
15pub trait SpecificFormattedValueIntrinsic: TryFromGlib<i64> + FormattedValueIntrinsic {}
23
24#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
25pub struct Buffers(u64);
26impl Buffers {
27 #[doc(alias = "GST_BUFFER_OFFSET_NONE")]
28 pub const OFFSET_NONE: u64 = ffi::GST_BUFFER_OFFSET_NONE;
29 pub const MAX: Self = Self(Self::OFFSET_NONE - 1);
30}
31
32impl Buffers {
33 #[track_caller]
41 #[inline]
42 pub const fn from_u64(buffers: u64) -> Self {
43 if buffers == ffi::GST_BUFFER_OFFSET_NONE {
44 panic!("`Buffers` value out of range");
45 }
46
47 Buffers(buffers)
48 }
49
50 #[track_caller]
58 #[inline]
59 pub fn from_usize(buffers: usize) -> Self {
60 Buffers::from_u64(buffers.try_into().unwrap())
61 }
62}
63
64impl_common_ops_for_newtype_uint!(Buffers, u64);
65impl_signed_div_mul!(Buffers, u64);
66impl_signed_int_into_signed!(Buffers, u64);
67impl_format_value_traits!(Buffers, Buffers, Buffers, u64);
68option_glib_newtype_from_to!(Buffers, Buffers::OFFSET_NONE);
69glib_newtype_display!(Buffers, DisplayableOptionBuffers, Format::Buffers);
70
71impl TryFrom<Buffers> for usize {
72 type Error = std::num::TryFromIntError;
73
74 fn try_from(value: Buffers) -> Result<Self, Self::Error> {
75 value.0.try_into()
76 }
77}
78
79pub trait BuffersFormatConstructor {
83 fn buffers(self) -> Buffers;
86}
87
88impl BuffersFormatConstructor for u64 {
89 #[track_caller]
90 #[inline]
91 fn buffers(self) -> Buffers {
92 Buffers::from_u64(self)
93 }
94}
95
96#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
97pub struct Bytes(u64);
98impl Bytes {
99 #[allow(non_upper_case_globals)]
100 #[allow(non_upper_case_globals)]
103 pub const KiB: Self = Self(1024);
104 #[allow(non_upper_case_globals)]
107 pub const MiB: Self = Self(1024 * 1024);
108 #[allow(non_upper_case_globals)]
111 pub const GiB: Self = Self(1024 * 1024 * 1024);
112 pub const MAX: Self = Self(u64::MAX - 1);
113}
114
115impl Bytes {
116 #[track_caller]
124 #[inline]
125 pub const fn from_u64(bytes: u64) -> Self {
126 if bytes == u64::MAX {
127 panic!("`Bytes` value out of range");
128 }
129
130 Bytes(bytes)
131 }
132
133 #[track_caller]
141 #[inline]
142 pub fn from_usize(bytes: usize) -> Self {
143 Bytes::from_u64(bytes.try_into().unwrap())
145 }
146}
147
148impl_common_ops_for_newtype_uint!(Bytes, u64);
149impl_signed_div_mul!(Bytes, u64);
150impl_signed_int_into_signed!(Bytes, u64);
151impl_format_value_traits!(Bytes, Bytes, Bytes, u64);
152option_glib_newtype_from_to!(Bytes, u64::MAX);
153glib_newtype_display!(Bytes, DisplayableOptionBytes, Format::Bytes);
154
155impl TryFrom<Bytes> for usize {
156 type Error = std::num::TryFromIntError;
157
158 fn try_from(value: Bytes) -> Result<Self, Self::Error> {
159 value.0.try_into()
160 }
161}
162
163pub trait BytesFormatConstructor {
171 fn bytes(self) -> Bytes;
174
175 fn kibibytes(self) -> Bytes;
178
179 fn mebibytes(self) -> Bytes;
182
183 fn gibibytes(self) -> Bytes;
186}
187
188impl BytesFormatConstructor for u64 {
189 #[track_caller]
190 #[inline]
191 fn bytes(self) -> Bytes {
192 Bytes::from_u64(self)
193 }
194
195 #[track_caller]
196 #[inline]
197 fn kibibytes(self) -> Bytes {
198 Bytes::from_u64(self * 1024)
199 }
200
201 #[track_caller]
202 #[inline]
203 fn mebibytes(self) -> Bytes {
204 Bytes::from_u64(self * 1024 * 1024)
205 }
206
207 #[track_caller]
208 #[inline]
209 fn gibibytes(self) -> Bytes {
210 Bytes::from_u64(self * 1024 * 1024 * 1024)
211 }
212}
213
214#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
215pub struct Default(u64);
216impl Default {
217 pub const MAX: Self = Self(u64::MAX - 1);
218}
219
220impl Default {
221 #[track_caller]
229 #[inline]
230 pub const fn from_u64(quantity: u64) -> Self {
231 if quantity == u64::MAX {
232 panic!("`Default` value out of range");
233 }
234
235 Default(quantity)
236 }
237
238 #[track_caller]
246 #[inline]
247 pub fn from_usize(quantity: usize) -> Self {
248 Default::from_u64(quantity.try_into().unwrap())
250 }
251}
252
253impl_common_ops_for_newtype_uint!(Default, u64);
254impl_signed_div_mul!(Default, u64);
255impl_signed_int_into_signed!(Default, u64);
256impl_format_value_traits!(Default, Default, Default, u64);
257option_glib_newtype_from_to!(Default, u64::MAX);
258glib_newtype_display!(Default, DisplayableOptionDefault, Format::Default);
259
260impl TryFrom<Default> for usize {
261 type Error = std::num::TryFromIntError;
262
263 fn try_from(value: Default) -> Result<Self, Self::Error> {
264 value.0.try_into()
265 }
266}
267
268pub trait DefaultFormatConstructor {
272 fn default_format(self) -> Default;
275}
276
277impl DefaultFormatConstructor for u64 {
278 #[track_caller]
279 #[inline]
280 fn default_format(self) -> Default {
281 Default::from_u64(self)
282 }
283}
284
285pub type Time = super::ClockTime;
286
287#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Default)]
288pub struct Percent(u32);
289impl Percent {
290 #[doc(alias = "GST_FORMAT_PERCENT_MAX")]
291 pub const MAX: Self = Self(ffi::GST_FORMAT_PERCENT_MAX as u32);
292 #[doc(alias = "GST_FORMAT_PERCENT_SCALE")]
293 pub const SCALE: Self = Self(ffi::GST_FORMAT_PERCENT_SCALE as u32);
294
295 #[track_caller]
302 #[inline]
303 pub const fn from_percent(percent: u32) -> Self {
304 if percent > 100 {
305 panic!("`Percent` value out of range");
306 }
307
308 Percent(ffi::GST_FORMAT_PERCENT_SCALE as u32 * percent)
309 }
310
311 #[track_caller]
318 #[inline]
319 pub const fn from_ppm(ppm: u32) -> Self {
320 if ppm > ffi::GST_FORMAT_PERCENT_MAX as u32 {
321 panic!("`Percent` ppm value out of range");
322 }
323
324 Percent(ppm)
325 }
326
327 #[track_caller]
334 #[inline]
335 pub fn from_ratio(ratio: f32) -> Self {
336 Percent::try_from(ratio).expect("`Percent` ratio out of range")
338 }
339
340 #[track_caller]
343 #[inline]
344 pub fn percent(&self) -> u32 {
345 self.0 / ffi::GST_FORMAT_PERCENT_SCALE as u32
346 }
347
348 #[track_caller]
351 #[inline]
352 pub fn ppm(&self) -> u32 {
353 self.0
354 }
355
356 #[track_caller]
359 #[inline]
360 pub fn ratio(&self) -> f32 {
361 self.0 as f32 / ffi::GST_FORMAT_PERCENT_MAX as f32
362 }
363}
364
365impl_common_ops_for_newtype_uint!(Percent, u32, one: ffi::GST_FORMAT_PERCENT_SCALE as u32);
366impl_signed_div_mul!(Percent, u32);
367impl_signed_int_into_signed!(Percent, u32);
368
369impl FormattedValue for Option<Percent> {
370 type FullRange = Option<Percent>;
371
372 #[inline]
373 fn default_format() -> Format {
374 Format::Percent
375 }
376
377 #[inline]
378 fn format(&self) -> Format {
379 Format::Percent
380 }
381
382 #[inline]
383 fn is_some(&self) -> bool {
384 Option::is_some(self)
385 }
386
387 #[inline]
388 unsafe fn into_raw_value(self) -> i64 {
389 self.map_or(-1, |v| v.0 as i64)
390 }
391}
392
393impl FormattedValueFullRange for Option<Percent> {
394 #[inline]
395 unsafe fn from_raw(format: Format, value: i64) -> Self {
396 debug_assert_eq!(format, Format::Percent);
397 Percent::try_from_glib(value).ok()
398 }
399}
400
401impl From<Option<Percent>> for GenericFormattedValue {
402 #[inline]
403 fn from(v: Option<Percent>) -> Self {
404 skip_assert_initialized!();
405 GenericFormattedValue::Percent(v)
406 }
407}
408
409impl From<Percent> for GenericFormattedValue {
410 #[inline]
411 fn from(v: Percent) -> Self {
412 skip_assert_initialized!();
413 GenericFormattedValue::Percent(Some(v))
414 }
415}
416
417impl FormattedValue for Percent {
418 type FullRange = Option<Percent>;
419
420 #[inline]
421 fn default_format() -> Format {
422 Format::Percent
423 }
424
425 #[inline]
426 fn format(&self) -> Format {
427 Format::Percent
428 }
429
430 #[inline]
431 fn is_some(&self) -> bool {
432 true
433 }
434
435 #[inline]
436 unsafe fn into_raw_value(self) -> i64 {
437 self.0 as i64
438 }
439}
440
441impl TryFrom<u64> for Percent {
442 type Error = GlibNoneError;
443
444 #[inline]
445 fn try_from(v: u64) -> Result<Percent, GlibNoneError> {
446 skip_assert_initialized!();
447 unsafe { Self::try_from_glib(v as i64) }
448 }
449}
450
451impl TryFromGlib<i64> for Percent {
452 type Error = GlibNoneError;
453 #[inline]
454 unsafe fn try_from_glib(value: i64) -> Result<Self, Self::Error> {
455 skip_assert_initialized!();
456 if value < 0 || value > ffi::GST_FORMAT_PERCENT_MAX {
457 Err(GlibNoneError)
458 } else {
459 Ok(Percent(value as u32))
460 }
461 }
462}
463
464impl TryFrom<u32> for Percent {
465 type Error = FormattedValueError;
466
467 #[inline]
468 fn try_from(value: u32) -> Result<Self, Self::Error> {
469 skip_assert_initialized!();
470 if value > ffi::GST_FORMAT_PERCENT_MAX as u32 {
471 Err(FormattedValueError(Format::Percent))
472 } else {
473 Ok(Percent(value))
474 }
475 }
476}
477
478impl TryFrom<GenericFormattedValue> for Option<Percent> {
479 type Error = FormattedValueError;
480
481 #[inline]
482 fn try_from(v: GenericFormattedValue) -> Result<Option<Percent>, Self::Error> {
483 skip_assert_initialized!();
484 if let GenericFormattedValue::Percent(v) = v {
485 Ok(v)
486 } else {
487 Err(FormattedValueError(v.format()))
488 }
489 }
490}
491
492impl FormattedValueIntrinsic for Percent {}
493impl SpecificFormattedValue for Option<Percent> {}
494impl SpecificFormattedValueFullRange for Option<Percent> {}
495impl SpecificFormattedValueIntrinsic for Percent {}
496impl FormattedValueNoneBuilder for Option<Percent> {
497 #[inline]
498 fn none() -> Option<Percent> {
499 None
500 }
501}
502
503#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
504#[error("value out of range")]
505pub struct TryPercentFromFloatError(());
506
507impl TryFrom<f64> for Percent {
508 type Error = TryPercentFromFloatError;
509
510 #[inline]
511 fn try_from(v: f64) -> Result<Self, Self::Error> {
512 skip_assert_initialized!();
513 if v < 0.0 || v > 1.0 {
514 Err(TryPercentFromFloatError(()))
515 } else {
516 Ok(Percent(
517 (v * ffi::GST_FORMAT_PERCENT_MAX as f64).round() as u32
518 ))
519 }
520 }
521}
522
523impl TryFrom<f32> for Percent {
524 type Error = TryPercentFromFloatError;
525
526 #[inline]
527 fn try_from(v: f32) -> Result<Self, Self::Error> {
528 skip_assert_initialized!();
529 if v < 0.0 || v > 1.0 {
530 Err(TryPercentFromFloatError(()))
531 } else {
532 Ok(Percent(
533 (v * ffi::GST_FORMAT_PERCENT_MAX as f32).round() as u32
534 ))
535 }
536 }
537}
538
539pub trait PercentFormatIntegerConstructor {
543 fn percent(self) -> Percent;
546
547 fn ppm(self) -> Percent;
550}
551
552impl PercentFormatIntegerConstructor for u32 {
553 #[track_caller]
554 #[inline]
555 fn percent(self) -> Percent {
556 Percent::from_percent(self)
557 }
558
559 #[track_caller]
560 #[inline]
561 fn ppm(self) -> Percent {
562 Percent::from_ppm(self)
563 }
564}
565
566pub trait PercentFormatFloatConstructor {
570 fn percent_ratio(self) -> Percent;
573}
574
575impl PercentFormatFloatConstructor for f32 {
576 #[track_caller]
577 #[inline]
578 fn percent_ratio(self) -> Percent {
579 Percent::try_from(self).unwrap()
580 }
581}
582
583impl std::fmt::Display for Percent {
584 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
585 std::fmt::Display::fmt(&(self.0 as f32 / (*Percent::SCALE) as f32), f)?;
586 f.write_str(" %")
587 }
588}
589
590impl crate::utils::Displayable for Percent {
591 type DisplayImpl = Self;
592 fn display(self) -> Self {
593 self
594 }
595}
596pub struct DisplayableOptionPercent(Option<Percent>);
597
598impl std::fmt::Display for DisplayableOptionPercent {
599 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
600 if let Some(val) = self.0.as_ref() {
601 std::fmt::Display::fmt(val, f)
602 } else {
603 f.write_str("undef. %")
604 }
605 }
606}
607
608impl crate::utils::Displayable for Option<Percent> {
609 type DisplayImpl = DisplayableOptionPercent;
610 fn display(self) -> Self::DisplayImpl {
611 DisplayableOptionPercent(self)
612 }
613}