use std::{
iter::FromIterator,
ops::{Deref, DerefMut},
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
MediaTrackConstraint, MediaTrackConstraintResolutionStrategy, MediaTrackProperty,
MediaTrackSupportedConstraints, ResolvedMediaTrackConstraint, SanitizedMediaTrackConstraint,
};
use super::constraint_set::GenericMediaTrackConstraintSet;
pub type MandatoryMediaTrackConstraints =
GenericMandatoryMediaTrackConstraints<MediaTrackConstraint>;
pub type ResolvedMandatoryMediaTrackConstraints =
GenericMandatoryMediaTrackConstraints<ResolvedMediaTrackConstraint>;
pub type SanitizedMandatoryMediaTrackConstraints =
GenericMandatoryMediaTrackConstraints<SanitizedMediaTrackConstraint>;
#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct GenericMandatoryMediaTrackConstraints<T>(GenericMediaTrackConstraintSet<T>);
impl<T> GenericMandatoryMediaTrackConstraints<T> {
pub fn new(constraints: GenericMediaTrackConstraintSet<T>) -> Self {
Self(constraints)
}
pub fn into_inner(self) -> GenericMediaTrackConstraintSet<T> {
self.0
}
}
impl GenericMandatoryMediaTrackConstraints<ResolvedMediaTrackConstraint> {
pub fn basic(&self) -> GenericMediaTrackConstraintSet<ResolvedMediaTrackConstraint> {
self.basic_or_required(false)
}
pub fn required(&self) -> GenericMediaTrackConstraintSet<ResolvedMediaTrackConstraint> {
self.basic_or_required(true)
}
fn basic_or_required(
&self,
required: bool,
) -> GenericMediaTrackConstraintSet<ResolvedMediaTrackConstraint> {
GenericMediaTrackConstraintSet::new(
self.0
.iter()
.filter_map(|(property, constraint)| {
if constraint.is_required() == required {
Some((property.clone(), constraint.clone()))
} else {
None
}
})
.collect(),
)
}
}
impl<T> Deref for GenericMandatoryMediaTrackConstraints<T> {
type Target = GenericMediaTrackConstraintSet<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for GenericMandatoryMediaTrackConstraints<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> Default for GenericMandatoryMediaTrackConstraints<T> {
fn default() -> Self {
Self(Default::default())
}
}
impl<T, U> FromIterator<(U, T)> for GenericMandatoryMediaTrackConstraints<T>
where
U: Into<MediaTrackProperty>,
{
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (U, T)>,
{
Self::new(iter.into_iter().map(|(k, v)| (k.into(), v)).collect())
}
}
impl<T> IntoIterator for GenericMandatoryMediaTrackConstraints<T> {
type Item = (MediaTrackProperty, T);
type IntoIter = indexmap::map::IntoIter<MediaTrackProperty, T>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl MandatoryMediaTrackConstraints {
pub fn to_resolved(&self) -> ResolvedMandatoryMediaTrackConstraints {
self.clone().into_resolved()
}
pub fn into_resolved(self) -> ResolvedMandatoryMediaTrackConstraints {
let strategy = MediaTrackConstraintResolutionStrategy::BareToIdeal;
ResolvedMandatoryMediaTrackConstraints::new(self.0.into_resolved(strategy))
}
}
impl ResolvedMandatoryMediaTrackConstraints {
pub fn to_sanitized(
&self,
supported_constraints: &MediaTrackSupportedConstraints,
) -> SanitizedMandatoryMediaTrackConstraints {
self.clone().into_sanitized(supported_constraints)
}
pub fn into_sanitized(
self,
supported_constraints: &MediaTrackSupportedConstraints,
) -> SanitizedMandatoryMediaTrackConstraints {
SanitizedMandatoryMediaTrackConstraints::new(self.0.into_sanitized(supported_constraints))
}
}
#[cfg(test)]
mod tests {
use crate::{
property::all::name::*, ResolvedMediaTrackConstraintSet, ResolvedValueConstraint,
ResolvedValueRangeConstraint,
};
use super::*;
#[test]
fn basic() {
let mandatory = ResolvedMandatoryMediaTrackConstraints::new(
ResolvedMediaTrackConstraintSet::from_iter([
(
&DEVICE_ID,
ResolvedValueConstraint::default()
.exact("device-id".to_owned())
.into(),
),
(
&AUTO_GAIN_CONTROL,
ResolvedValueConstraint::default().ideal(true).into(),
),
(
&CHANNEL_COUNT,
ResolvedValueRangeConstraint::default()
.exact(2)
.ideal(3)
.into(),
),
]),
);
let actual = mandatory.basic();
let expected = ResolvedMediaTrackConstraintSet::from_iter([(
&AUTO_GAIN_CONTROL,
ResolvedValueConstraint::default().ideal(true).into(),
)]);
assert_eq!(actual, expected);
}
#[test]
fn required() {
let mandatory = ResolvedMandatoryMediaTrackConstraints::new(
ResolvedMediaTrackConstraintSet::from_iter([
(
&DEVICE_ID,
ResolvedValueConstraint::default()
.exact("device-id".to_owned())
.into(),
),
(
&AUTO_GAIN_CONTROL,
ResolvedValueConstraint::default().ideal(true).into(),
),
(
&CHANNEL_COUNT,
ResolvedValueRangeConstraint::default()
.exact(2)
.ideal(3)
.into(),
),
]),
);
let actual = mandatory.required();
let expected = ResolvedMediaTrackConstraintSet::from_iter([
(
&DEVICE_ID,
ResolvedValueConstraint::default()
.exact("device-id".to_owned())
.into(),
),
(
&CHANNEL_COUNT,
ResolvedValueRangeConstraint::default()
.exact(2)
.ideal(3)
.into(),
),
]);
assert_eq!(actual, expected);
}
}
#[cfg(feature = "serde")]
#[cfg(test)]
mod serde_tests {
use crate::{property::all::name::*, MediaTrackConstraintSet};
use super::*;
#[test]
fn serialize_default() {
let mandatory = MandatoryMediaTrackConstraints::default();
let actual = serde_json::to_value(mandatory).unwrap();
let expected = serde_json::json!({});
assert_eq!(actual, expected);
}
#[test]
fn deserialize_default() {
let json = serde_json::json!({});
let actual: MandatoryMediaTrackConstraints = serde_json::from_value(json).unwrap();
let expected = MandatoryMediaTrackConstraints::default();
assert_eq!(actual, expected);
}
#[test]
fn serialize() {
let mandatory = MandatoryMediaTrackConstraints::new(MediaTrackConstraintSet::from_iter([
(&DEVICE_ID, "device-id".into()),
(&AUTO_GAIN_CONTROL, true.into()),
(&CHANNEL_COUNT, 2.into()),
(&LATENCY, 0.123.into()),
]));
let actual = serde_json::to_value(mandatory).unwrap();
let expected = serde_json::json!(
{
"deviceId": "device-id".to_owned(),
"autoGainControl": true,
"channelCount": 2,
"latency": 0.123,
}
);
assert_eq!(actual, expected);
}
#[test]
fn deserialize() {
let json = serde_json::json!(
{
"deviceId": "device-id".to_owned(),
"autoGainControl": true,
"channelCount": 2,
"latency": 0.123,
}
);
let actual: MandatoryMediaTrackConstraints = serde_json::from_value(json).unwrap();
let expected = MandatoryMediaTrackConstraints::new(MediaTrackConstraintSet::from_iter([
(&DEVICE_ID, "device-id".into()),
(&AUTO_GAIN_CONTROL, true.into()),
(&CHANNEL_COUNT, 2.into()),
(&LATENCY, 0.123.into()),
]));
assert_eq!(actual, expected);
}
}