Skip to main content

mux_media/types/config/
fields.rs

1use super::{Config, ConfigTarget};
2use crate::{
3    Chapters, DefaultDispositions, DispositionType, Dispositions, Field, ForcedDispositions,
4    LangMetadata, NameMetadata, Stream, Streams, Target,
5};
6use std::path::Path;
7
8impl Config {
9    /// Returns a field value for marker `F`:
10    ///
11    /// - From the first given target contains in [`Config::targets`], that has a Some value.
12    ///
13    /// - Otherwise, from the common (global) configuration.
14    pub fn target<F, T>(&self, _: F, t: T) -> &<Self as Field<F>>::FieldType
15    where
16        Self: Field<F>,
17        ConfigTarget: Field<F, FieldType = Option<<Self as Field<F>>::FieldType>>,
18        T: AsRef<Path>,
19    {
20        self.targets
21            .as_ref()
22            .and_then(|map| {
23                map.get(t.as_ref())
24                    .and_then(|v| <ConfigTarget as Field<F>>::field(v).as_ref())
25            })
26            .unwrap_or_else(|| <Self as Field<F>>::field(self))
27    }
28
29    // Returns (index, val)
30    pub(crate) fn stream_val<F, I, T>(
31        &self,
32        f: F,
33        target_paths: I,
34        stream: &Stream,
35    ) -> (usize, &<Self as Field<F>>::FieldType)
36    where
37        F: Copy,
38        Self: Field<F>,
39        ConfigTarget: Field<F, FieldType = Option<<Self as Field<F>>::FieldType>>,
40        I: IntoIterator<Item = T>,
41        T: AsRef<Path>,
42    {
43        if let Some(v) = self.get_targets(f, target_paths) {
44            (stream.i, v)
45        } else if let Some(v) = self.get_target(f, Target::Stream(stream.ty)) {
46            (stream.i_ty, v)
47        } else {
48            (stream.i, <Self as Field<F>>::field(self))
49        }
50    }
51
52    // Returns (index, val)
53    pub(crate) fn stream_val_dispositions<I, T>(
54        &self,
55        ty: DispositionType,
56        target_paths: I,
57        stream: &Stream,
58    ) -> (usize, &Dispositions)
59    where
60        I: IntoIterator<Item = T>,
61        T: AsRef<Path>,
62    {
63        match ty {
64            DispositionType::Default => {
65                let (i, xs) = self.stream_val(CfgDefaults, target_paths, stream);
66                (i, &xs.0)
67            }
68            DispositionType::Forced => {
69                let (i, xs) = self.stream_val(CfgForceds, target_paths, stream);
70                (i, &xs.0)
71            }
72        }
73    }
74
75    pub(crate) fn get_target<F, T>(&self, _: F, t: T) -> Option<&<Self as Field<F>>::FieldType>
76    where
77        Self: Field<F>,
78        ConfigTarget: Field<F, FieldType = Option<<Self as Field<F>>::FieldType>>,
79        T: AsRef<Path>,
80    {
81        self.targets.as_ref().and_then(|map| {
82            map.get(t.as_ref())
83                .and_then(|v| <ConfigTarget as Field<F>>::field(v).as_ref())
84        })
85    }
86
87    pub(crate) fn get_targets<F, I, T>(&self, f: F, ts: I) -> Option<&<Self as Field<F>>::FieldType>
88    where
89        F: Copy,
90        Self: Field<F>,
91        ConfigTarget: Field<F, FieldType = Option<<Self as Field<F>>::FieldType>>,
92        I: IntoIterator<Item = T>,
93        T: AsRef<Path>,
94    {
95        ts.into_iter().find_map(|t| self.get_target(f, t))
96    }
97
98    /// Gets a cloned [`Target`] key if its exists in [`Self::targets`].
99    ///
100    /// This operation avoids heap allocation: internally it either copies an enum variant
101    /// or increments the [`Arc`](std::sync::Arc) reference count.
102    pub(crate) fn get_key(&self, target: impl AsRef<Path>) -> Option<Target> {
103        self.targets.as_ref().and_then(|map| {
104            map.get_key_value(target.as_ref())
105                .map(|(key, _)| key.clone())
106        })
107    }
108}
109
110macro_rules! fields {
111    // Base type and optional (target) type
112    ($type:ident, $opt_type:ident;
113    $( $field:ident, $ty:ty => $marker:ident ),* $(,)?
114    ) => {
115        $(
116            #[doc = concat!("Marker of [`Config`] fields, that stores [`", stringify!($ty), "`].")]
117            #[derive(Copy, Clone)]
118            pub struct $marker;
119
120            impl Field<$marker> for $type {
121                type FieldType = $ty;
122
123                #[inline(always)]
124                fn field(&self) -> &Self::FieldType {
125                    &self.$field
126                }
127            }
128
129            impl Field<$marker> for $opt_type {
130                type FieldType = Option<$ty>;
131
132                #[inline(always)]
133                fn field(&self) -> &Self::FieldType {
134                    &self.$field
135                }
136            }
137        )*
138    };
139}
140
141fields! {
142    Config, ConfigTarget;
143    streams, Streams => CfgStreams,
144    chapters, Chapters => CfgChapters,
145    defaults, DefaultDispositions => CfgDefaults,
146    forceds, ForcedDispositions => CfgForceds,
147    names, NameMetadata => CfgNames,
148    langs, LangMetadata => CfgLangs,
149}