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#[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}