diff --git a/main/common-types/src/duration_in_quarter_notes.rs b/main/common-types/src/duration_in_quarter_notes.rs new file mode 100644 index 00000000..13d6c6ff --- /dev/null +++ b/main/common-types/src/duration_in_quarter_notes.rs @@ -0,0 +1,36 @@ +use nutype::nutype; + +/// This represents a duration expressed as positive amount of quarter notes. +#[nutype( + new_unchecked, + validate(finite, greater_or_equal = 0.0), + derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Debug, + Default, + Display, + FromStr, + Into, + TryFrom, + Serialize, + Deserialize + ), + default = 0.0 +)] +pub struct DurationInQuarterNotes(f64); + +impl DurationInQuarterNotes { + /// The minimum duration (zero, empty). + pub const ZERO: DurationInQuarterNotes = unsafe { DurationInQuarterNotes::new_unchecked(0.0) }; + + /// The maximum possible duration (highest possible floating-point number). + pub const MAX: DurationInQuarterNotes = + unsafe { DurationInQuarterNotes::new_unchecked(f64::MAX) }; + + nutype_additions!(f64); +} diff --git a/main/common-types/src/lib.rs b/main/common-types/src/lib.rs index 73af4413..eda5f0bd 100644 --- a/main/common-types/src/lib.rs +++ b/main/common-types/src/lib.rs @@ -8,6 +8,7 @@ pub use hex_literal::hex; mod bpm; mod db; mod duration_in_beats; +mod duration_in_quarter_notes; mod duration_in_seconds; mod hz; mod linear_volume_value; @@ -22,6 +23,7 @@ mod semitones; pub use bpm::*; pub use db::*; pub use duration_in_beats::*; +pub use duration_in_quarter_notes::*; pub use duration_in_seconds::*; pub use hz::*; pub use linear_volume_value::*; diff --git a/main/common-types/src/position_in_quarter_notes.rs b/main/common-types/src/position_in_quarter_notes.rs index 5a1d7c9b..461f002f 100644 --- a/main/common-types/src/position_in_quarter_notes.rs +++ b/main/common-types/src/position_in_quarter_notes.rs @@ -1,4 +1,6 @@ +use crate::DurationInQuarterNotes; use nutype::nutype; +use std::ops::{Add, Neg}; /// This represents a position expressed as an amount of quarter notes. /// @@ -32,3 +34,25 @@ impl PositionInQuarterNotes { nutype_additions!(f64); } + +impl From for PositionInQuarterNotes { + fn from(v: DurationInQuarterNotes) -> Self { + PositionInQuarterNotes::new_panic(v.get()) + } +} + +impl Add for PositionInQuarterNotes { + type Output = Self; + + fn add(self, rhs: DurationInQuarterNotes) -> Self { + PositionInQuarterNotes::new_panic(self.get() + rhs.get()) + } +} + +impl Neg for PositionInQuarterNotes { + type Output = Self; + + fn neg(self) -> Self { + Self::new_panic(-self.get()) + } +} diff --git a/main/medium/src/misc_newtypes.rs b/main/medium/src/misc_newtypes.rs index c6a9ac6e..68c83d2f 100644 --- a/main/medium/src/misc_newtypes.rs +++ b/main/medium/src/misc_newtypes.rs @@ -11,6 +11,7 @@ use std::num::NonZeroI32; pub use reaper_common_types::Bpm; pub use reaper_common_types::Db; pub use reaper_common_types::DurationInBeats; +pub use reaper_common_types::DurationInQuarterNotes; pub use reaper_common_types::DurationInSeconds; pub use reaper_common_types::Hz; pub use reaper_common_types::LinearVolumeValue as ReaperVolumeValue;