Skip to main content

audiotags_macro/
lib.rs

1#[macro_export]
2macro_rules! impl_audiotag_config {
3    ($tag:ident) => {
4        impl AudioTagConfig for $tag {
5            fn config(&self) -> &Config {
6                &self.config
7            }
8            fn set_config(&mut self, config: Config) {
9                self.config = config.clone();
10            }
11        }
12    };
13}
14
15#[macro_export]
16macro_rules! impl_tag {
17    ($tag:ident , $inner:ident, $tag_type:expr) => {
18        #[derive(Default)]
19        pub struct $tag {
20            inner: $inner,
21            config: Config,
22        }
23        impl $tag {
24            pub fn new() -> Self {
25                Self::default()
26            }
27            pub fn read_from_path(path: impl AsRef<Path>) -> crate::Result<Self> {
28                Ok(Self {
29                    inner: $inner::read_from_path(path)?,
30                    config: Config::default(),
31                })
32            }
33        }
34        impl_audiotag_config!($tag);
35
36        use std::any::Any;
37
38        impl ToAnyTag for $tag {
39            fn to_anytag(&self) -> AnyTag<'_> {
40                self.into()
41            }
42        }
43
44        impl ToAny for $tag {
45            fn to_any(&self) -> &dyn Any {
46                self
47            }
48            fn to_any_mut(&mut self) -> &mut dyn Any {
49                self
50            }
51        }
52
53        impl AudioTag for $tag {}
54
55        // From wrapper to inner (same type)
56        impl From<$tag> for $inner {
57            fn from(inp: $tag) -> Self {
58                inp.inner
59            }
60        }
61
62        // From inner to wrapper (same type)
63        impl From<$inner> for $tag {
64            fn from(inp: $inner) -> Self {
65                Self {
66                    inner: inp,
67                    config: Config::default(),
68                }
69            }
70        }
71
72        // From dyn AudioTag to wrapper (any type)
73        impl From<Box<dyn AudioTag + Send + Sync>> for $tag {
74            fn from(inp: Box<dyn AudioTag + Send + Sync>) -> Self {
75                let mut inp = inp;
76                if let Some(t_refmut) = inp.to_any_mut().downcast_mut::<$tag>() {
77                    let t = std::mem::replace(t_refmut, $tag::new()); // TODO: can we avoid creating the dummy tag?
78                    t
79                } else {
80                    let mut t = inp.to_dyn_tag($tag_type);
81                    let t_refmut = t.to_any_mut().downcast_mut::<$tag>().unwrap();
82                    let t = std::mem::replace(t_refmut, $tag::new());
83                    t
84                }
85            }
86        }
87        // From dyn AudioTag to inner (any type)
88        impl std::convert::From<Box<dyn AudioTag + Send + Sync>> for $inner {
89            fn from(inp: Box<dyn AudioTag + Send + Sync>) -> Self {
90                let t: $tag = inp.into();
91                t.into()
92            }
93        }
94    };
95}