amll_lyric/
lib.rs

1#[cfg(feature = "ass")]
2pub mod ass;
3#[cfg(feature = "eqrc")]
4pub mod eqrc;
5#[cfg(feature = "eslrc")]
6pub mod eslrc;
7#[cfg(feature = "lrc")]
8pub mod lrc;
9#[cfg(feature = "lys")]
10pub mod lys;
11#[cfg(feature = "qrc")]
12pub mod qrc;
13#[cfg(feature = "ttml")]
14pub mod ttml;
15#[cfg(feature = "yrc")]
16pub mod yrc;
17
18pub mod utils;
19#[cfg(target_arch = "wasm32")]
20mod types {
21    include!(concat!(env!("OUT_DIR"), "/types.rs"));
22}
23
24use std::borrow::Cow;
25
26#[cfg(feature = "serde")]
27use serde::*;
28
29// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
30// allocator.
31#[cfg(all(target_arch = "wasm32", feature = "wee_alloc"))]
32#[global_allocator]
33static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
34
35#[derive(Debug, Clone, PartialEq, Default)]
36#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
37#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
38pub struct LyricWord<'a> {
39    pub start_time: u64,
40    pub end_time: u64,
41    pub word: Cow<'a, str>,
42}
43
44#[derive(Debug, Clone, PartialEq, Default)]
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
46#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
47pub struct LyricWordOwned {
48    pub start_time: u64,
49    pub end_time: u64,
50    pub word: String,
51}
52
53impl<'a> From<LyricWord<'a>> for LyricWordOwned {
54    fn from(value: LyricWord<'a>) -> Self {
55        Self {
56            start_time: value.start_time,
57            end_time: value.end_time,
58            word: value.word.into_owned(),
59        }
60    }
61}
62
63impl LyricWord<'_> {
64    pub fn to_owned(&self) -> LyricWordOwned {
65        LyricWordOwned {
66            start_time: self.start_time,
67            end_time: self.end_time,
68            word: self.word.clone().into_owned(),
69        }
70    }
71
72    pub fn is_empty(&self) -> bool {
73        self.word.trim().is_empty()
74    }
75}
76
77impl LyricWordOwned {
78    pub fn to_ref(&self) -> LyricWord {
79        LyricWord {
80            start_time: self.start_time,
81            end_time: self.end_time,
82            word: self.word.as_str().into(),
83        }
84    }
85
86    pub fn is_empty(&self) -> bool {
87        self.word.trim().is_empty()
88    }
89}
90
91#[derive(Debug, Clone, PartialEq, Default)]
92#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
93#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
94pub struct LyricLine<'a> {
95    pub words: Vec<LyricWord<'a>>,
96    #[cfg_attr(feature = "serde", serde(default))]
97    pub translated_lyric: Cow<'a, str>,
98    #[cfg_attr(feature = "serde", serde(default))]
99    pub roman_lyric: Cow<'a, str>,
100    #[cfg_attr(feature = "serde", serde(default, rename = "isBG"))]
101    pub is_bg: bool,
102    #[cfg_attr(feature = "serde", serde(default))]
103    pub is_duet: bool,
104    #[cfg_attr(feature = "serde", serde(default))]
105    pub start_time: u64,
106    #[cfg_attr(feature = "serde", serde(default))]
107    pub end_time: u64,
108}
109
110#[derive(Debug, Clone, PartialEq, Default)]
111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
112#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
113pub struct LyricLineOwned {
114    pub words: Vec<LyricWordOwned>,
115    pub translated_lyric: String,
116    pub roman_lyric: String,
117    pub is_bg: bool,
118    pub is_duet: bool,
119    pub start_time: u64,
120    pub end_time: u64,
121}
122
123impl<'a> From<LyricLine<'a>> for LyricLineOwned {
124    fn from(value: LyricLine<'a>) -> Self {
125        Self {
126            words: value.words.iter().map(|w| w.to_owned()).collect(),
127            translated_lyric: value.translated_lyric.into_owned(),
128            roman_lyric: value.roman_lyric.into_owned(),
129            is_bg: value.is_bg,
130            is_duet: value.is_duet,
131            start_time: value.start_time,
132            end_time: value.end_time,
133        }
134    }
135}
136
137impl LyricLine<'_> {
138    pub fn to_owned(&self) -> LyricLineOwned {
139        LyricLineOwned {
140            words: self.words.iter().map(|w| w.to_owned()).collect(),
141            translated_lyric: self.translated_lyric.clone().into_owned(),
142            roman_lyric: self.roman_lyric.clone().into_owned(),
143            is_bg: self.is_bg,
144            is_duet: self.is_duet,
145            start_time: self.start_time,
146            end_time: self.end_time,
147        }
148    }
149
150    pub fn to_line(&self) -> String {
151        self.words
152            .iter()
153            .map(|x| x.word.to_string())
154            .collect::<Vec<_>>()
155            .join(" ")
156    }
157
158    pub fn is_empty(&self) -> bool {
159        self.words.is_empty() || self.words.iter().all(|x| x.is_empty())
160    }
161}
162
163impl LyricLineOwned {
164    pub fn to_ref(&self) -> LyricLine {
165        LyricLine {
166            words: self.words.iter().map(|w| w.to_ref()).collect(),
167            translated_lyric: self.translated_lyric.as_str().into(),
168            roman_lyric: self.roman_lyric.as_str().into(),
169            is_bg: self.is_bg,
170            is_duet: self.is_duet,
171            start_time: self.start_time,
172            end_time: self.end_time,
173        }
174    }
175
176    pub fn to_line(&self) -> String {
177        self.words
178            .iter()
179            .map(|x| x.word.to_string())
180            .collect::<Vec<_>>()
181            .join(" ")
182    }
183
184    pub fn is_empty(&self) -> bool {
185        self.words.is_empty() || self.words.iter().all(|x| x.is_empty())
186    }
187}