1use crate::common::*;
2use crate::data::packet::Packet;
3use crate::data::value::*;
4use std::any::Any;
5use std::io::{Cursor, Seek, SeekFrom, Write};
6use std::sync::Arc;
7
8use crate::error::*;
9
10pub struct Writer<W = Cursor<Vec<u8>>> {
13 writer: W,
14 bytes_written: usize,
15}
16
17impl<W: Write> Writer<W> {
18 pub fn new(inner: W) -> Self {
20 Self {
21 writer: inner,
22 bytes_written: 0,
23 }
24 }
25}
26
27impl<W: Write> Writer<W> {
28 pub fn position(&mut self) -> usize {
30 self.bytes_written
31 }
32
33 pub fn as_ref(&self) -> (&W, usize) {
35 (&self.writer, self.bytes_written)
36 }
37}
38
39impl<W: Write> Write for Writer<W> {
40 fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
41 let result = self.writer.write(bytes);
42
43 if let Ok(written) = result {
44 self.bytes_written += written;
45 }
46
47 result
48 }
49
50 fn flush(&mut self) -> std::io::Result<()> {
51 self.writer.flush()
52 }
53}
54
55impl<W: Write> Seek for Writer<W>
56where
57 W: Seek,
58{
59 fn seek(&mut self, seek: SeekFrom) -> std::io::Result<u64> {
60 let res = self.writer.seek(seek)?;
61 self.bytes_written = res as usize;
62 Ok(res)
63 }
64}
65
66pub trait Muxer: Send {
68 fn configure(&mut self) -> Result<()>;
70 fn write_header<W: Write>(&mut self, out: &mut Writer<W>) -> Result<()>;
73 fn write_packet<W: Write>(&mut self, out: &mut Writer<W>, pkt: Arc<Packet>) -> Result<()>;
76 fn write_trailer<W: Write>(&mut self, out: &mut Writer<W>) -> Result<()>;
79
80 fn set_global_info(&mut self, info: GlobalInfo) -> Result<()>;
82 fn set_option(&mut self, key: &str, val: Value) -> Result<()>;
87}
88
89pub struct Context<M: Muxer + Send, W: Write> {
92 muxer: M,
93 writer: Writer<W>,
94 pub user_private: Option<Box<dyn Any + Send + Sync>>,
98}
99
100impl<M: Muxer, W: Write> Context<M, W> {
101 pub fn new(muxer: M, writer: Writer<W>) -> Self {
103 Context {
104 muxer,
105 writer,
106 user_private: None,
107 }
108 }
109
110 pub fn configure(&mut self) -> Result<()> {
112 self.muxer.configure()
113 }
114
115 pub fn write_header(&mut self) -> Result<()> {
118 self.muxer.write_header(&mut self.writer)
119 }
120
121 pub fn write_packet(&mut self, pkt: Arc<Packet>) -> Result<()> {
124 self.muxer.write_packet(&mut self.writer, pkt)
125 }
126
127 pub fn write_trailer(&mut self) -> Result<()> {
130 self.muxer.write_trailer(&mut self.writer)?;
131 self.writer.flush()?;
132
133 Ok(())
134 }
135
136 pub fn set_global_info(&mut self, info: GlobalInfo) -> Result<()> {
138 self.muxer.set_global_info(info)
139 }
140
141 pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
146 where
147 V: Into<Value<'a>>,
148 {
149 self.muxer.set_option(key, val.into())
150 }
151
152 pub fn writer(&self) -> &Writer<W> {
154 &self.writer
155 }
156
157 pub fn into_writer(self) -> Writer<W> {
159 self.writer
160 }
161}
162
163#[derive(Clone, Debug, PartialEq, Eq)]
167pub struct Descr {
168 pub name: &'static str,
170 pub demuxer: &'static str,
172 pub description: &'static str,
174 pub extensions: &'static [&'static str],
176 pub mime: &'static [&'static str],
178}
179
180pub trait Descriptor {
182 type OutputMuxer: Muxer + Send;
184
185 fn create(&self) -> Self::OutputMuxer;
187 fn describe(&self) -> &Descr;
189}
190
191pub trait Lookup<T: Descriptor + ?Sized> {
193 fn by_name(&self, name: &str) -> Option<&'static T>;
195}
196
197impl<T: Descriptor + ?Sized> Lookup<T> for [&'static T] {
198 fn by_name(&self, name: &str) -> Option<&'static T> {
199 self.iter().find(|&&d| d.describe().name == name).copied()
200 }
201}
202
203#[cfg(test)]
204mod test {
205 use super::*;
206
207 const DUMMY_HEADER_LENGTH: usize = 12;
208 const DUMMY_PACKET_LENGTH: usize = 2;
209 const DUMMY_PACKETS_NUMBER: usize = 2;
210 const DUMMY_TRAILER_LENGTH: usize = 13;
211
212 struct DummyDes {
213 d: Descr,
214 }
215
216 struct DummyMuxer {}
217
218 impl DummyMuxer {
219 pub fn new() -> Self {
220 Self {}
221 }
222 }
223
224 impl Muxer for DummyMuxer {
225 fn configure(&mut self) -> Result<()> {
226 Ok(())
227 }
228
229 fn write_header<W: Write>(&mut self, out: &mut Writer<W>) -> Result<()> {
230 let buf = b"Dummy header";
231 out.write_all(buf.as_slice()).unwrap();
232 Ok(())
233 }
234
235 fn write_packet<W: Write>(&mut self, out: &mut Writer<W>, pkt: Arc<Packet>) -> Result<()> {
236 out.write_all(&pkt.data).unwrap();
237 Ok(())
238 }
239
240 fn write_trailer<W: Write>(&mut self, out: &mut Writer<W>) -> Result<()> {
241 let buf = b"Dummy trailer";
242 out.write_all(buf.as_slice()).unwrap();
243 Ok(())
244 }
245
246 fn set_global_info(&mut self, _info: GlobalInfo) -> Result<()> {
247 Ok(())
248 }
249
250 fn set_option(&mut self, _key: &str, _val: Value) -> Result<()> {
251 Ok(())
252 }
253 }
254
255 impl Descriptor for DummyDes {
256 type OutputMuxer = DummyMuxer;
257
258 fn create(&self) -> Self::OutputMuxer {
259 DummyMuxer {}
260 }
261 fn describe(&self) -> &Descr {
262 &self.d
263 }
264 }
265
266 const DUMMY_DES: &dyn Descriptor<OutputMuxer = DummyMuxer> = &DummyDes {
267 d: Descr {
268 name: "dummy",
269 demuxer: "dummy",
270 description: "Dummy mux",
271 extensions: &["mx", "mux"],
272 mime: &["application/dummy"],
273 },
274 };
275
276 #[test]
277 fn lookup() {
278 let muxers: &[&dyn Descriptor<OutputMuxer = DummyMuxer>] = &[DUMMY_DES];
279
280 muxers.by_name("dummy").unwrap();
281 }
282
283 fn run_muxer<W: Write>(writer: Writer<W>) -> Context<DummyMuxer, W> {
284 let mux = DummyMuxer::new();
285
286 let mut muxer = Context::new(mux, writer);
287
288 muxer.configure().unwrap();
289 muxer.write_header().unwrap();
290
291 for _ in 0..DUMMY_PACKETS_NUMBER {
293 let packet = Packet::zeroed(DUMMY_PACKET_LENGTH);
294 muxer.write_packet(Arc::new(packet)).unwrap();
295 }
296
297 muxer.write_trailer().unwrap();
298 muxer
299 }
300
301 fn check_underlying_buffer(buffer: &[u8]) {
302 assert_eq!(
303 buffer.get(..DUMMY_HEADER_LENGTH).unwrap(),
304 b"Dummy header".as_slice()
305 );
306
307 assert_eq!(
308 buffer
309 .get(
311 DUMMY_HEADER_LENGTH
312 ..DUMMY_HEADER_LENGTH + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)
313 )
314 .unwrap(),
315 &[0, 0, 0, 0]
316 );
317
318 assert_eq!(
319 buffer
320 .get(DUMMY_HEADER_LENGTH + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)..)
322 .unwrap(),
323 b"Dummy trailer".as_slice()
324 );
325 }
326
327 #[test]
328 fn vec_muxer() {
329 let muxer = run_muxer(Writer::new(Vec::new()));
330 let (buffer, index) = muxer.writer().as_ref();
331 check_underlying_buffer(buffer);
332 assert_eq!(
333 index,
334 DUMMY_HEADER_LENGTH
335 + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)
336 + DUMMY_TRAILER_LENGTH
337 );
338 }
339
340 #[test]
341 fn stdout_muxer() {
342 use std::io::stdout;
343
344 let muxer = run_muxer(Writer::new(stdout()));
345 let (_buffer, index) = muxer.writer().as_ref();
346 assert_eq!(
347 index,
348 DUMMY_HEADER_LENGTH
349 + (DUMMY_PACKETS_NUMBER * DUMMY_PACKET_LENGTH)
350 + DUMMY_TRAILER_LENGTH
351 );
352 }
353
354 #[cfg(not(target_arch = "wasm32"))] #[test]
357 fn file_muxer() {
358 let file = tempfile::tempfile().unwrap();
359 let muxer = run_muxer(Writer::new(file));
360 let mut writer = muxer.into_writer();
361 writer.seek(SeekFrom::Start(3)).unwrap();
362 assert!(writer.bytes_written == 3);
363 assert!(writer.as_ref().0.metadata().unwrap().len() != 0);
364 }
365}