crispy_iptv_types/
stream.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct StreamUrl {
8 pub url: String,
10 pub protocol: StreamProtocol,
12}
13
14impl StreamUrl {
15 pub fn parse(url: &str) -> Self {
17 let protocol = StreamProtocol::detect(url);
18 Self {
19 url: url.to_string(),
20 protocol,
21 }
22 }
23}
24
25#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
27pub enum StreamProtocol {
28 Http,
29 Https,
30 Hls,
31 Dash,
32 Rtmp,
33 Rtsp,
34 Udp,
35 Rtp,
36 Mms,
37 #[default]
38 Unknown,
39}
40
41impl StreamProtocol {
42 pub fn detect(url: &str) -> Self {
44 let lower = url.to_ascii_lowercase();
45 if lower.starts_with("rtmp://") || lower.starts_with("rtmps://") {
46 return Self::Rtmp;
47 }
48 if lower.starts_with("rtsp://") {
49 return Self::Rtsp;
50 }
51 if lower.starts_with("udp://") {
52 return Self::Udp;
53 }
54 if lower.starts_with("rtp://") {
55 return Self::Rtp;
56 }
57 if lower.starts_with("mms://") || lower.starts_with("mmsh://") {
58 return Self::Mms;
59 }
60 if lower.contains(".m3u8") || lower.contains("/hls/") {
62 return Self::Hls;
63 }
64 if lower.contains(".mpd") || lower.contains("/dash/") {
65 return Self::Dash;
66 }
67 if lower.starts_with("https://") {
68 return Self::Https;
69 }
70 if lower.starts_with("http://") {
71 return Self::Http;
72 }
73 Self::Unknown
74 }
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct StreamStatus {
80 pub available: bool,
82 pub status_code: Option<u16>,
84 pub response_time_ms: Option<u64>,
86 pub content_type: Option<String>,
88 pub error: Option<String>,
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn detect_hls() {
98 assert_eq!(
99 StreamProtocol::detect("http://example.com/live/stream.m3u8"),
100 StreamProtocol::Hls,
101 );
102 }
103
104 #[test]
105 fn detect_rtmp() {
106 assert_eq!(
107 StreamProtocol::detect("rtmp://cdn.example.com/live/key"),
108 StreamProtocol::Rtmp,
109 );
110 }
111
112 #[test]
113 fn detect_http() {
114 assert_eq!(
115 StreamProtocol::detect("http://example.com/stream.ts"),
116 StreamProtocol::Http,
117 );
118 }
119
120 #[test]
121 fn detect_udp() {
122 assert_eq!(
123 StreamProtocol::detect("udp://239.0.0.1:5000"),
124 StreamProtocol::Udp,
125 );
126 }
127
128 #[test]
129 fn detect_dash() {
130 assert_eq!(
131 StreamProtocol::detect("https://cdn.example.com/manifest.mpd"),
132 StreamProtocol::Dash,
133 );
134 }
135
136 #[test]
137 fn detect_unknown() {
138 assert_eq!(
139 StreamProtocol::detect("ftp://example.com/file"),
140 StreamProtocol::Unknown,
141 );
142 }
143
144 #[test]
145 fn stream_url_parse() {
146 let s = StreamUrl::parse("https://cdn.example.com/live/stream.m3u8");
147 assert_eq!(s.protocol, StreamProtocol::Hls);
148 }
149}