1use std::fmt;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43#[non_exhaustive]
44pub enum SampleFormat {
45 U8,
48 I16,
50 I32,
52 F32,
54 F64,
56
57 U8p,
60 I16p,
62 I32p,
64 F32p,
66 F64p,
68
69 Other(u32),
72}
73
74impl SampleFormat {
75 #[must_use]
87 pub const fn name(&self) -> &'static str {
88 match self {
89 Self::U8 => "u8",
90 Self::I16 => "s16",
91 Self::I32 => "s32",
92 Self::F32 => "flt",
93 Self::F64 => "dbl",
94 Self::U8p => "u8p",
95 Self::I16p => "s16p",
96 Self::I32p => "s32p",
97 Self::F32p => "fltp",
98 Self::F64p => "dblp",
99 Self::Other(_) => "unknown",
100 }
101 }
102
103 #[must_use]
122 pub const fn bytes_per_sample(&self) -> usize {
123 match self {
124 Self::U8 | Self::U8p => 1,
125 Self::I16 | Self::I16p => 2,
126 Self::I32 | Self::I32p | Self::F32 | Self::F32p | Self::Other(_) => 4,
127 Self::F64 | Self::F64p => 8,
128 }
129 }
130
131 #[must_use]
148 pub const fn is_planar(&self) -> bool {
149 matches!(
150 self,
151 Self::U8p | Self::I16p | Self::I32p | Self::F32p | Self::F64p
152 )
153 }
154
155 #[must_use]
172 pub const fn is_packed(&self) -> bool {
173 !self.is_planar()
174 }
175
176 #[must_use]
194 pub const fn is_float(&self) -> bool {
195 matches!(self, Self::F32 | Self::F64 | Self::F32p | Self::F64p)
196 }
197
198 #[must_use]
212 pub const fn is_integer(&self) -> bool {
213 matches!(
214 self,
215 Self::U8 | Self::I16 | Self::I32 | Self::U8p | Self::I16p | Self::I32p
216 )
217 }
218
219 #[must_use]
233 pub const fn is_signed(&self) -> bool {
234 !matches!(self, Self::U8 | Self::U8p | Self::Other(_))
235 }
236
237 #[must_use]
251 pub const fn packed_equivalent(&self) -> Self {
252 match self {
253 Self::U8p => Self::U8,
254 Self::I16p => Self::I16,
255 Self::I32p => Self::I32,
256 Self::F32p => Self::F32,
257 Self::F64p => Self::F64,
258 other => *other,
260 }
261 }
262
263 #[must_use]
277 pub const fn planar_equivalent(&self) -> Self {
278 match self {
279 Self::U8 => Self::U8p,
280 Self::I16 => Self::I16p,
281 Self::I32 => Self::I32p,
282 Self::F32 => Self::F32p,
283 Self::F64 => Self::F64p,
284 other => *other,
286 }
287 }
288
289 #[must_use]
302 pub const fn bit_depth(&self) -> usize {
303 self.bytes_per_sample() * 8
304 }
305}
306
307impl fmt::Display for SampleFormat {
308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309 write!(f, "{}", self.name())
310 }
311}
312
313impl Default for SampleFormat {
314 fn default() -> Self {
319 Self::F32
320 }
321}
322
323#[cfg(test)]
324mod tests {
325 use super::*;
326
327 #[test]
328 fn test_format_names() {
329 assert_eq!(SampleFormat::U8.name(), "u8");
330 assert_eq!(SampleFormat::I16.name(), "s16");
331 assert_eq!(SampleFormat::I32.name(), "s32");
332 assert_eq!(SampleFormat::F32.name(), "flt");
333 assert_eq!(SampleFormat::F64.name(), "dbl");
334 assert_eq!(SampleFormat::U8p.name(), "u8p");
335 assert_eq!(SampleFormat::I16p.name(), "s16p");
336 assert_eq!(SampleFormat::I32p.name(), "s32p");
337 assert_eq!(SampleFormat::F32p.name(), "fltp");
338 assert_eq!(SampleFormat::F64p.name(), "dblp");
339 assert_eq!(SampleFormat::Other(999).name(), "unknown");
340 }
341
342 #[test]
343 fn test_bytes_per_sample() {
344 assert_eq!(SampleFormat::U8.bytes_per_sample(), 1);
346 assert_eq!(SampleFormat::U8p.bytes_per_sample(), 1);
347
348 assert_eq!(SampleFormat::I16.bytes_per_sample(), 2);
350 assert_eq!(SampleFormat::I16p.bytes_per_sample(), 2);
351
352 assert_eq!(SampleFormat::I32.bytes_per_sample(), 4);
354 assert_eq!(SampleFormat::I32p.bytes_per_sample(), 4);
355 assert_eq!(SampleFormat::F32.bytes_per_sample(), 4);
356 assert_eq!(SampleFormat::F32p.bytes_per_sample(), 4);
357
358 assert_eq!(SampleFormat::F64.bytes_per_sample(), 8);
360 assert_eq!(SampleFormat::F64p.bytes_per_sample(), 8);
361
362 assert_eq!(SampleFormat::Other(123).bytes_per_sample(), 4);
364 }
365
366 #[test]
367 fn test_is_planar() {
368 assert!(!SampleFormat::U8.is_planar());
370 assert!(!SampleFormat::I16.is_planar());
371 assert!(!SampleFormat::I32.is_planar());
372 assert!(!SampleFormat::F32.is_planar());
373 assert!(!SampleFormat::F64.is_planar());
374 assert!(!SampleFormat::Other(0).is_planar());
375
376 assert!(SampleFormat::U8p.is_planar());
378 assert!(SampleFormat::I16p.is_planar());
379 assert!(SampleFormat::I32p.is_planar());
380 assert!(SampleFormat::F32p.is_planar());
381 assert!(SampleFormat::F64p.is_planar());
382 }
383
384 #[test]
385 fn test_is_packed() {
386 assert!(SampleFormat::U8.is_packed());
388 assert!(SampleFormat::I16.is_packed());
389 assert!(SampleFormat::I32.is_packed());
390 assert!(SampleFormat::F32.is_packed());
391 assert!(SampleFormat::F64.is_packed());
392
393 assert!(!SampleFormat::U8p.is_packed());
395 assert!(!SampleFormat::I16p.is_packed());
396 assert!(!SampleFormat::I32p.is_packed());
397 assert!(!SampleFormat::F32p.is_packed());
398 assert!(!SampleFormat::F64p.is_packed());
399 }
400
401 #[test]
402 fn test_is_float() {
403 assert!(SampleFormat::F32.is_float());
405 assert!(SampleFormat::F64.is_float());
406 assert!(SampleFormat::F32p.is_float());
407 assert!(SampleFormat::F64p.is_float());
408
409 assert!(!SampleFormat::U8.is_float());
411 assert!(!SampleFormat::I16.is_float());
412 assert!(!SampleFormat::I32.is_float());
413 assert!(!SampleFormat::U8p.is_float());
414 assert!(!SampleFormat::I16p.is_float());
415 assert!(!SampleFormat::I32p.is_float());
416 assert!(!SampleFormat::Other(0).is_float());
417 }
418
419 #[test]
420 fn test_is_integer() {
421 assert!(SampleFormat::U8.is_integer());
423 assert!(SampleFormat::I16.is_integer());
424 assert!(SampleFormat::I32.is_integer());
425 assert!(SampleFormat::U8p.is_integer());
426 assert!(SampleFormat::I16p.is_integer());
427 assert!(SampleFormat::I32p.is_integer());
428
429 assert!(!SampleFormat::F32.is_integer());
431 assert!(!SampleFormat::F64.is_integer());
432 assert!(!SampleFormat::F32p.is_integer());
433 assert!(!SampleFormat::F64p.is_integer());
434 assert!(!SampleFormat::Other(0).is_integer());
435 }
436
437 #[test]
438 fn test_is_signed() {
439 assert!(SampleFormat::I16.is_signed());
441 assert!(SampleFormat::I32.is_signed());
442 assert!(SampleFormat::F32.is_signed());
443 assert!(SampleFormat::F64.is_signed());
444 assert!(SampleFormat::I16p.is_signed());
445 assert!(SampleFormat::I32p.is_signed());
446 assert!(SampleFormat::F32p.is_signed());
447 assert!(SampleFormat::F64p.is_signed());
448
449 assert!(!SampleFormat::U8.is_signed());
451 assert!(!SampleFormat::U8p.is_signed());
452 assert!(!SampleFormat::Other(0).is_signed());
453 }
454
455 #[test]
456 fn test_packed_equivalent() {
457 assert_eq!(SampleFormat::U8p.packed_equivalent(), SampleFormat::U8);
459 assert_eq!(SampleFormat::I16p.packed_equivalent(), SampleFormat::I16);
460 assert_eq!(SampleFormat::I32p.packed_equivalent(), SampleFormat::I32);
461 assert_eq!(SampleFormat::F32p.packed_equivalent(), SampleFormat::F32);
462 assert_eq!(SampleFormat::F64p.packed_equivalent(), SampleFormat::F64);
463
464 assert_eq!(SampleFormat::U8.packed_equivalent(), SampleFormat::U8);
466 assert_eq!(SampleFormat::I16.packed_equivalent(), SampleFormat::I16);
467 assert_eq!(SampleFormat::F32.packed_equivalent(), SampleFormat::F32);
468
469 assert_eq!(
471 SampleFormat::Other(42).packed_equivalent(),
472 SampleFormat::Other(42)
473 );
474 }
475
476 #[test]
477 fn test_planar_equivalent() {
478 assert_eq!(SampleFormat::U8.planar_equivalent(), SampleFormat::U8p);
480 assert_eq!(SampleFormat::I16.planar_equivalent(), SampleFormat::I16p);
481 assert_eq!(SampleFormat::I32.planar_equivalent(), SampleFormat::I32p);
482 assert_eq!(SampleFormat::F32.planar_equivalent(), SampleFormat::F32p);
483 assert_eq!(SampleFormat::F64.planar_equivalent(), SampleFormat::F64p);
484
485 assert_eq!(SampleFormat::U8p.planar_equivalent(), SampleFormat::U8p);
487 assert_eq!(SampleFormat::I16p.planar_equivalent(), SampleFormat::I16p);
488 assert_eq!(SampleFormat::F32p.planar_equivalent(), SampleFormat::F32p);
489
490 assert_eq!(
492 SampleFormat::Other(42).planar_equivalent(),
493 SampleFormat::Other(42)
494 );
495 }
496
497 #[test]
498 fn test_bit_depth() {
499 assert_eq!(SampleFormat::U8.bit_depth(), 8);
500 assert_eq!(SampleFormat::U8p.bit_depth(), 8);
501 assert_eq!(SampleFormat::I16.bit_depth(), 16);
502 assert_eq!(SampleFormat::I16p.bit_depth(), 16);
503 assert_eq!(SampleFormat::I32.bit_depth(), 32);
504 assert_eq!(SampleFormat::F32.bit_depth(), 32);
505 assert_eq!(SampleFormat::F64.bit_depth(), 64);
506 assert_eq!(SampleFormat::F64p.bit_depth(), 64);
507 }
508
509 #[test]
510 fn test_display() {
511 assert_eq!(format!("{}", SampleFormat::F32), "flt");
512 assert_eq!(format!("{}", SampleFormat::I16), "s16");
513 assert_eq!(format!("{}", SampleFormat::F32p), "fltp");
514 assert_eq!(format!("{}", SampleFormat::Other(123)), "unknown");
515 }
516
517 #[test]
518 fn test_default() {
519 assert_eq!(SampleFormat::default(), SampleFormat::F32);
520 }
521
522 #[test]
523 fn test_debug() {
524 assert_eq!(format!("{:?}", SampleFormat::F32), "F32");
525 assert_eq!(format!("{:?}", SampleFormat::I16p), "I16p");
526 assert_eq!(format!("{:?}", SampleFormat::Other(42)), "Other(42)");
527 }
528
529 #[test]
530 fn test_equality_and_hash() {
531 use std::collections::HashSet;
532
533 assert_eq!(SampleFormat::F32, SampleFormat::F32);
534 assert_ne!(SampleFormat::F32, SampleFormat::F32p);
535 assert_eq!(SampleFormat::Other(1), SampleFormat::Other(1));
536 assert_ne!(SampleFormat::Other(1), SampleFormat::Other(2));
537
538 let mut set = HashSet::new();
540 set.insert(SampleFormat::F32);
541 set.insert(SampleFormat::I16);
542 assert!(set.contains(&SampleFormat::F32));
543 assert!(!set.contains(&SampleFormat::F64));
544 }
545
546 #[test]
547 fn test_copy() {
548 let format = SampleFormat::F32;
549 let copied = format;
550 assert_eq!(format, copied);
552 assert_eq!(format.name(), copied.name());
553 }
554
555 #[test]
556 fn test_round_trip_equivalents() {
557 let packed_formats = [
559 SampleFormat::U8,
560 SampleFormat::I16,
561 SampleFormat::I32,
562 SampleFormat::F32,
563 SampleFormat::F64,
564 ];
565 for format in packed_formats {
566 assert_eq!(format.planar_equivalent().packed_equivalent(), format);
567 }
568
569 let planar_formats = [
571 SampleFormat::U8p,
572 SampleFormat::I16p,
573 SampleFormat::I32p,
574 SampleFormat::F32p,
575 SampleFormat::F64p,
576 ];
577 for format in planar_formats {
578 assert_eq!(format.packed_equivalent().planar_equivalent(), format);
579 }
580 }
581}