1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use std::{
    fmt,
    ops::{Div, Mul},
    time::Duration,
};

use crate::{Bytes, System};

mod sealed {
    use derive_more::Display;

    use crate::System;

    /// An audio time span, measured by the number of samples contained in it.
    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
    #[repr(transparent)]
    pub struct Samples<const SYS: System>(usize);

    impl<const SYS: System> Samples<SYS> {
        #[inline]
        pub const fn new(n: usize) -> Self {
            Self(n)
        }

        #[inline]
        pub const fn get(&self) -> usize {
            self.0
        }
    }
}

pub use self::sealed::Samples;

impl<const SYS: System> fmt::Debug for Samples<SYS> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.get(), f)
    }
}

impl<const SYS: System> Samples<SYS> {
    /// Equivalent to `Duration::try_from(samples).unwrap()`.
    #[inline]
    #[track_caller]
    pub const fn into_duration(self) -> Duration {
        match self.try_into() {
            Ok(dur) => dur,
            Err(_) => {
                panic!("Overflowed trying to convert samples to duration")
            }
        }
    }

    /// Equivalent to `Samples::try_from(duration).unwrap()`.
    #[inline]
    #[track_caller]
    pub const fn from_duration(dur: Duration) -> Self {
        match dur.try_into() {
            Ok(samples) => samples,
            Err(_) => {
                panic!("Overflowed trying to convert duration to samples")
            }
        }
    }

    /// Equivalent to `Bytes::try_from(samples).unwrap()`.
    #[inline]
    #[track_caller]
    pub const fn into_bytes(self) -> Bytes<SYS> {
        match self.try_into() {
            Ok(bytes) => bytes,
            Err(_) => {
                panic!("Overflowed trying to convert samples to duration")
            }
        }
    }

    /// Equivalent to `Samples::from(bytes)`.
    #[inline]
    #[track_caller]
    pub const fn from_bytes(bytes: Bytes<SYS>) -> Self {
        bytes.into()
    }
}

impl<const SYS: System> const From<usize> for Samples<SYS> {
    #[inline]
    fn from(value: usize) -> Self {
        Self::new(value)
    }
}

impl<const SYS: System> const From<Samples<SYS>> for usize {
    #[inline]
    fn from(value: Samples<SYS>) -> Self {
        value.get()
    }
}

impl<const SYS: System> const Mul for Samples<SYS> {
    type Output = Self;

    #[inline]
    #[track_caller]
    fn mul(self, rhs: Self) -> Self::Output {
        Self::new(self.get().mul(rhs.get()))
    }
}

impl<const SYS: System, T> const Mul<T> for Samples<SYS>
where
    usize: ~const Mul<T, Output = usize>,
{
    type Output = Self;

    #[inline]
    #[track_caller]
    fn mul(self, rhs: T) -> Self::Output {
        Self::new(self.get().mul(rhs))
    }
}

impl<const SYS: System> const Div for Samples<SYS> {
    type Output = Self;

    #[inline]
    #[track_caller]
    fn div(self, rhs: Self) -> Self::Output {
        Self::new(self.get().div(rhs.get()))
    }
}

impl<const SYS: System, T> const Div<T> for Samples<SYS>
where
    usize: ~const Div<T, Output = usize>,
{
    type Output = Self;

    #[inline]
    #[track_caller]
    fn div(self, rhs: T) -> Self::Output {
        Self::new(self.get().div(rhs))
    }
}