notation_proto/
proto_entry.rs

1use std::fmt::Display;
2
3use serde::{Deserialize, Serialize};
4
5use notation_core::prelude::{CoreEntry, Duration, Entry, EntryPassMode, MetaEntry};
6use notation_fretted::prelude::{FrettedEntry4, FrettedEntry6};
7
8use crate::prelude::LyricEntry;
9
10#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
11pub enum ProtoEntry {
12    Mark(String),
13    Meta(MetaEntry),
14    Core(CoreEntry),
15    Lyric(LyricEntry),
16    Fretted6(FrettedEntry6),
17    Fretted4(FrettedEntry4),
18    Extra(String, String),
19}
20impl Display for ProtoEntry {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        match self {
23            ProtoEntry::Mark(x) => write!(f, "Mark({})", x),
24            ProtoEntry::Meta(x) => write!(f, "Meta({})", x),
25            ProtoEntry::Core(x) => write!(f, "Core({})", x),
26            ProtoEntry::Lyric(x) => write!(f, "Lyric({})", x),
27            ProtoEntry::Fretted6(x) => write!(f, "Fretted6({})", x),
28            ProtoEntry::Fretted4(x) => write!(f, "Fretted4({})", x),
29            ProtoEntry::Extra(x, y) => write!(f, "Extra({}, {})", x, y),
30        }
31    }
32}
33impl ProtoEntry {
34    pub fn duration(&self) -> Duration {
35        match self {
36            ProtoEntry::Mark(_) => Duration::Zero,
37            ProtoEntry::Meta(entry) => entry.duration(),
38            ProtoEntry::Core(entry) => entry.duration(),
39            ProtoEntry::Lyric(entry) => entry.duration(),
40            ProtoEntry::Fretted6(entry) => entry.duration(),
41            ProtoEntry::Fretted4(entry) => entry.duration(),
42            ProtoEntry::Extra(_, _) => Duration::Zero,
43        }
44    }
45    pub fn pass_mode(&self) -> EntryPassMode {
46        match self {
47            ProtoEntry::Mark(_) => EntryPassMode::Immediate,
48            ProtoEntry::Meta(entry) => entry.pass_mode(),
49            ProtoEntry::Core(entry) => entry.pass_mode(),
50            ProtoEntry::Lyric(entry) => entry.pass_mode(),
51            ProtoEntry::Fretted6(entry) => entry.pass_mode(),
52            ProtoEntry::Fretted4(entry) => entry.pass_mode(),
53            ProtoEntry::Extra(_, _) => EntryPassMode::Immediate,
54        }
55    }
56    /// Returns `true` if the proto_entry is [`Mark`].
57    pub fn is_mark(&self) -> bool {
58        matches!(self, Self::Mark(..))
59    }
60    pub fn is_mark_string(&self, val: &String) -> bool {
61        if let Self::Mark(v) = self {
62            v == val
63        } else {
64            false
65        }
66    }
67    pub fn is_mark_str(&self, val: &str) -> bool {
68        if let Self::Mark(v) = self {
69            v.as_str() == val
70        } else {
71            false
72        }
73    }
74    /// Returns `true` if the proto_entry is [`Meta`].
75    pub fn is_meta(&self) -> bool {
76        matches!(self, Self::Meta(..))
77    }
78    /// Returns `true` if the proto_entry is [`Core`].
79    pub fn is_core(&self) -> bool {
80        matches!(self, Self::Core(..))
81    }
82    /// Returns `true` if the proto_entry is [`Word`].
83    pub fn is_word(&self) -> bool {
84        matches!(self, Self::Lyric(..))
85    }
86    pub fn as_mark(&self) -> Option<&String> {
87        if let Self::Mark(v) = self {
88            Some(v)
89        } else {
90            None
91        }
92    }
93    pub fn as_meta(&self) -> Option<&MetaEntry> {
94        if let Self::Meta(v) = self {
95            Some(v)
96        } else {
97            None
98        }
99    }
100    pub fn as_core(&self) -> Option<&CoreEntry> {
101        if let Self::Core(v) = self {
102            Some(v)
103        } else {
104            None
105        }
106    }
107    pub fn try_into_core(self) -> Result<CoreEntry, Self> {
108        if let Self::Core(v) = self {
109            Ok(v)
110        } else {
111            Err(self)
112        }
113    }
114    /// Returns `true` if the proto_entry is [`FrettedSix`].
115    pub fn is_fretted6(&self) -> bool {
116        matches!(self, Self::Fretted6(..))
117    }
118    pub fn as_fretted6(&self) -> Option<&FrettedEntry6> {
119        if let Self::Fretted6(v) = self {
120            Some(v)
121        } else {
122            None
123        }
124    }
125    pub fn try_into_fretted6(self) -> Result<FrettedEntry6, Self> {
126        if let Self::Fretted6(v) = self {
127            Ok(v)
128        } else {
129            Err(self)
130        }
131    }
132    /// Returns `true` if the proto_entry is [`FrettedFour`].
133    pub fn is_fretted4(&self) -> bool {
134        matches!(self, Self::Fretted4(..))
135    }
136    pub fn as_fretted4(&self) -> Option<&FrettedEntry4> {
137        if let Self::Fretted4(v) = self {
138            Some(v)
139        } else {
140            None
141        }
142    }
143    pub fn try_into_fretted4(self) -> Result<FrettedEntry4, Self> {
144        if let Self::Fretted4(v) = self {
145            Ok(v)
146        } else {
147            Err(self)
148        }
149    }
150}
151impl ProtoEntry {
152    pub const COMMENT_CHAR: char = ';';
153    pub fn is_core_tie(&self) -> bool {
154        self.as_core().map(|x| x.is_tie()).unwrap_or(false)
155    }
156    pub fn trim_comments(mark: &String) -> String {
157        if let Some(index) = mark.find(Self::COMMENT_CHAR) {
158            return mark[..index].to_string();
159        }
160        mark.clone()
161    }
162}
163impl Entry for ProtoEntry {
164    fn duration(&self) -> Duration {
165        self.duration()
166    }
167    fn pass_mode(&self) -> EntryPassMode {
168        self.pass_mode()
169    }
170}
171
172impl From<String> for ProtoEntry {
173    fn from(v: String) -> Self {
174        ProtoEntry::Mark(v)
175    }
176}
177
178impl From<&str> for ProtoEntry {
179    fn from(v: &str) -> Self {
180        ProtoEntry::Mark(String::from(v))
181    }
182}
183
184impl From<(String, String)> for ProtoEntry {
185    fn from(v: (String, String)) -> Self {
186        ProtoEntry::Extra(v.0, v.1)
187    }
188}
189
190impl From<(&str, String)> for ProtoEntry {
191    fn from(v: (&str, String)) -> Self {
192        ProtoEntry::Extra(String::from(v.0), v.1)
193    }
194}
195
196impl From<(String, &str)> for ProtoEntry {
197    fn from(v: (String, &str)) -> Self {
198        ProtoEntry::Extra(v.0, String::from(v.1))
199    }
200}
201
202impl From<(&str, &str)> for ProtoEntry {
203    fn from(v: (&str, &str)) -> Self {
204        ProtoEntry::Extra(String::from(v.0), String::from(v.1))
205    }
206}
207
208impl From<MetaEntry> for ProtoEntry {
209    fn from(v: MetaEntry) -> Self {
210        ProtoEntry::Meta(v)
211    }
212}
213
214impl From<CoreEntry> for ProtoEntry {
215    fn from(v: CoreEntry) -> Self {
216        ProtoEntry::Core(v)
217    }
218}
219
220impl From<LyricEntry> for ProtoEntry {
221    fn from(v: LyricEntry) -> Self {
222        ProtoEntry::Lyric(v)
223    }
224}
225
226impl From<FrettedEntry6> for ProtoEntry {
227    fn from(v: FrettedEntry6) -> Self {
228        ProtoEntry::Fretted6(v)
229    }
230}
231
232impl From<FrettedEntry4> for ProtoEntry {
233    fn from(v: FrettedEntry4) -> Self {
234        ProtoEntry::Fretted4(v)
235    }
236}