1#[cfg(feature = "ass")]
2pub mod ass;
3pub mod config;
4#[cfg(feature = "ebu_stl")]
5pub mod ebu_stl;
6pub mod encoding;
7pub mod error;
8#[cfg(feature = "lrc")]
9pub mod lrc;
10#[cfg(feature = "microdvd")]
11pub mod microdvd;
12pub mod model;
13#[cfg(feature = "mpl2")]
14pub mod mpl2;
15pub mod normalize;
16pub mod pipeline;
17pub mod quality;
18#[cfg(feature = "sami")]
19pub mod sami;
20#[cfg(feature = "sbv")]
21pub mod sbv;
22#[cfg(feature = "scc")]
23pub mod scc;
24#[cfg(feature = "srt")]
25pub mod srt;
26#[cfg(feature = "subviewer")]
27pub mod subviewer;
28#[cfg(feature = "ttml")]
29pub mod ttml;
30pub mod types;
31pub mod utils;
32#[cfg(feature = "vtt")]
33pub mod vtt;
34
35pub use model::SubtitleFormat;
36
37pub use model::{
39 Format, ParseConfig, StreamingParser, Subtitle, SubtitleFile, SubtitleFileBuilder, TextPart,
40 WritePolicy,
41};
42
43pub fn detect_format(data: &[u8]) -> Option<Format> {
44 #[cfg(feature = "srt")]
45 let f = srt::detect_format(data);
46 #[cfg(not(feature = "srt"))]
47 let f: Option<Format> = None;
48
49 #[cfg(feature = "vtt")]
50 let f = f.or_else(|| vtt::detect_format(data));
51 #[cfg(feature = "ass")]
52 let f = f.or_else(|| ass::detect_format(data));
53 #[cfg(feature = "microdvd")]
54 let f = f.or_else(|| microdvd::detect_format(data));
55 #[cfg(feature = "subviewer")]
56 let f = f.or_else(|| subviewer::detect_format(data));
57 #[cfg(feature = "ttml")]
58 let f = f.or_else(|| ttml::detect_format(data));
59 #[cfg(feature = "sbv")]
60 let f = f.or_else(|| sbv::detect_format(data));
61 #[cfg(feature = "lrc")]
62 let f = f.or_else(|| lrc::detect_format(data));
63 #[cfg(feature = "sami")]
64 let f = f.or_else(|| sami::detect_format(data));
65 #[cfg(feature = "mpl2")]
66 let f = f.or_else(|| mpl2::detect_format(data));
67 #[cfg(feature = "scc")]
68 let f = f.or_else(|| scc::detect_format(data));
69 #[cfg(feature = "ebu_stl")]
70 let f = f.or_else(|| ebu_stl::detect_format(data));
71 f
72}
73
74pub fn parse_bytes(data: &[u8]) -> Result<model::SubtitleFile, error::ParseError> {
76 let fmt = detect_format(data).ok_or(error::ParseError::UnknownFormat)?;
77 parse_bytes_as(data, fmt)
78}
79
80pub fn parse_bytes_as(data: &[u8], fmt: Format) -> Result<model::SubtitleFile, error::ParseError> {
82 match fmt {
83 #[cfg(feature = "srt")]
84 Format::Srt => Ok(srt::parse_bytes(data)?),
85 #[cfg(feature = "vtt")]
86 Format::Vtt => Ok(vtt::parse_bytes(data)?),
87 #[cfg(feature = "ass")]
88 Format::Ass => Ok(ass::parse_bytes(data)?),
89 #[cfg(feature = "ssa")]
90 Format::Ssa => match ass::parse_bytes(data)? {
91 model::SubtitleFile::Ass(data) => Ok(model::SubtitleFile::Ssa(data)),
92 other => Ok(other),
93 },
94 #[cfg(feature = "microdvd")]
95 Format::MicroDvd => {
96 let file = microdvd::parse_bytes(data, None)?;
97 Ok(file)
98 }
99 #[cfg(feature = "subviewer")]
100 Format::SubViewer => Ok(subviewer::parse_bytes(data)?),
101 #[cfg(feature = "ttml")]
102 Format::Ttml => Ok(ttml::parse_bytes(data)?),
103 #[cfg(feature = "sbv")]
104 Format::Sbv => Ok(sbv::parse_bytes(data)?),
105 #[cfg(feature = "lrc")]
106 Format::Lrc => Ok(lrc::parse_bytes(data)?),
107 #[cfg(feature = "sami")]
108 Format::Sami => Ok(sami::parse_bytes(data)?),
109 #[cfg(feature = "mpl2")]
110 Format::Mpl2 => Ok(mpl2::parse_bytes(data)?),
111 #[cfg(feature = "scc")]
112 Format::Scc => Ok(scc::parse_bytes(data)?),
113 #[cfg(feature = "ebu_stl")]
114 Format::EbuStl => Ok(ebu_stl::parse_bytes(data)?),
115 #[allow(unreachable_patterns)]
116 _ => Err(error::ParseError::Unsupported(fmt)),
117 }
118}
119
120#[cfg(not(target_arch = "wasm32"))]
122pub async fn parse_file(
123 path: impl AsRef<std::path::Path>,
124) -> Result<model::SubtitleFile, error::ParseError> {
125 let data = tokio::fs::read(path).await?;
126 parse_bytes(&data)
127}
128
129#[cfg(feature = "http")]
132pub async fn parse_url(url: &str) -> Result<model::SubtitleFile, error::ParseError> {
133 let client = reqwest::Client::new();
134 parse_url_with(url, &client).await
135}
136
137#[cfg(feature = "http")]
140pub async fn parse_url_with(
141 url: &str,
142 client: &reqwest::Client,
143) -> Result<model::SubtitleFile, error::ParseError> {
144 let response = client.get(url).send().await?;
145 let bytes = response.bytes().await?;
146 parse_bytes(&bytes)
147}
148
149#[cfg(target_arch = "wasm32")]
150pub mod wasm;