use std::ops::{RangeFrom, RangeInclusive, RangeToInclusive}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; /// A capability specifying a range of supported values. /// /// # W3C Spec Compliance /// /// There exists no direct corresponding type in the /// W3C ["Media Capture and Streams"][media_capture_and_streams_spec] spec, /// since the `MediaTrackValueRangeCapability` type aims to be a /// generalization over multiple types in the W3C spec: /// /// | Rust | W3C | /// | ------------------------------------- | ----------------------------- | /// | `MediaTrackValueRangeCapability` | [`ULongRange`][ulong_range] | /// | `MediaTrackValueRangeCapability` | [`DoubleRange`][double_range] | /// /// [double_range]: https://www.w3.org/TR/mediacapture-streams/#dom-doublerange /// [media_capture_and_streams_spec]: https://www.w3.org/TR/mediacapture-streams/ /// [ulong_range]: https://www.w3.org/TR/mediacapture-streams/#dom-ulongrange #[derive(Debug, Clone, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] pub struct MediaTrackValueRangeCapability { #[cfg_attr( feature = "serde", serde(skip_serializing_if = "core::option::Option::is_none") )] pub min: Option, #[cfg_attr( feature = "serde", serde(skip_serializing_if = "core::option::Option::is_none") )] pub max: Option, } impl Default for MediaTrackValueRangeCapability { fn default() -> Self { Self { min: Default::default(), max: Default::default(), } } } impl From> for MediaTrackValueRangeCapability { fn from(range: RangeInclusive) -> Self { let (min, max) = range.into_inner(); Self { min: Some(min), max: Some(max), } } } impl From> for MediaTrackValueRangeCapability { fn from(range: RangeFrom) -> Self { Self { min: Some(range.start), max: None, } } } impl From> for MediaTrackValueRangeCapability { fn from(range: RangeToInclusive) -> Self { Self { min: None, max: Some(range.end), } } } impl MediaTrackValueRangeCapability { pub fn contains(&self, value: &T) -> bool where T: PartialOrd, { // FIXME(regexident): replace with if-let-chain, once stabilized: // Tracking issue: https://github.com/rust-lang/rust/issues/53667 if let Some(ref min) = self.min { if min > value { return false; } } // FIXME(regexident): replace with if-let-chain, once stabilized: // Tracking issue: https://github.com/rust-lang/rust/issues/53667 if let Some(ref max) = self.max { if max < value { return false; } } true } } #[cfg(test)] mod tests { use super::*; type Subject = MediaTrackValueRangeCapability; #[test] fn default() { let subject = Subject::default(); assert_eq!(subject.min, None); assert_eq!(subject.max, None); } mod from { use super::*; #[test] fn range_inclusive() { let subject = Subject::from(1..=5); assert_eq!(subject.min, Some(1)); assert_eq!(subject.max, Some(5)); } #[test] fn range_from() { let subject = Subject::from(1..); assert_eq!(subject.min, Some(1)); assert_eq!(subject.max, None); } #[test] fn range_to_inclusive() { let subject = Subject::from(..=5); assert_eq!(subject.min, None); assert_eq!(subject.max, Some(5)); } } mod contains { use super::*; #[test] fn default() { let subject = Subject::default(); assert!(subject.contains(&0)); assert!(subject.contains(&1)); assert!(subject.contains(&5)); assert!(subject.contains(&6)); } #[test] fn from_range_inclusive() { let subject = Subject::from(1..=5); assert!(!subject.contains(&0)); assert!(subject.contains(&1)); assert!(subject.contains(&5)); assert!(!subject.contains(&6)); } #[test] fn from_range_from() { let subject = Subject::from(1..); assert!(!subject.contains(&0)); assert!(subject.contains(&1)); assert!(subject.contains(&5)); assert!(subject.contains(&6)); } #[test] fn from_range_to_inclusive() { let subject = Subject::from(..=5); assert!(subject.contains(&0)); assert!(subject.contains(&1)); assert!(subject.contains(&5)); assert!(!subject.contains(&6)); } } } #[cfg(feature = "serde")] #[cfg(test)] mod serde_tests { use crate::macros::test_serde_symmetry; use super::*; type Subject = MediaTrackValueRangeCapability; #[test] fn customized() { let subject = Subject { min: Some(12), max: Some(34), }; let json = serde_json::json!({ "min": 12, "max": 34, }); test_serde_symmetry!(subject: subject, json: json); } }