mkv_element/
io.rs

1//! I/O utilities.
2
3/// blocking I/O implementations, supporting reading and writing.
4pub mod blocking_impl {
5    use crate::{
6        base::Header,
7        element::Element,
8        functional::Encode,
9        master::{Cluster, Segment},
10    };
11    use std::io::{Read, Write};
12
13    /// Read from a reader.
14    pub trait ReadFrom: Sized {
15        /// Read Self from a reader.
16        fn read_from<R: Read>(r: &mut R) -> crate::Result<Self>;
17    }
18
19    /// Read an element from a reader provided the header.
20    pub trait ReadElement: Sized + Element {
21        /// Read an element from a reader provided the header.
22        fn read_element<R: Read>(header: &Header, r: &mut R) -> crate::Result<Self> {
23            let body = header.read_body(r)?;
24            Self::decode_body(&mut &body[..])
25        }
26    }
27    impl<T: Element> ReadElement for T {}
28
29    impl Header {
30        /// Read the body of the element from a reader into memory.
31        pub(crate) fn read_body<R: Read>(&self, r: &mut R) -> crate::Result<Vec<u8>> {
32            // Segment and Cluster can have unknown size, but we don't support that here.
33            let size = if self.size.is_unknown && [Segment::ID, Cluster::ID].contains(&self.id) {
34                return Err(crate::Error::ElementBodySizeUnknown(self.id));
35            } else {
36                *self.size
37            };
38            // we allocate 4096 bytes upfront and grow as needed
39            let cap = size.min(4096) as usize;
40            let mut buf = Vec::with_capacity(cap);
41            let n = std::io::copy(&mut r.take(size), &mut buf)?;
42            if size != n {
43                return Err(crate::Error::OutOfBounds);
44            }
45            Ok(buf)
46        }
47    }
48
49    /// Write to a writer.
50    pub trait WriteTo {
51        /// Write to a writer.
52        fn write_to<W: Write>(&self, w: &mut W) -> crate::Result<()>;
53    }
54
55    impl<T: Encode> WriteTo for T {
56        fn write_to<W: Write>(&self, w: &mut W) -> crate::Result<()> {
57            //TODO should avoid the extra allocation here
58            let mut buf = vec![];
59            self.encode(&mut buf)?;
60            w.write_all(&buf)?;
61            Ok(())
62        }
63    }
64
65    /// Write an element to a writer provided the header.
66    pub trait WriteElement: Sized + Element {
67        /// Write an element to a writer.
68        fn write_element<W: Write>(&self, header: &Header, w: &mut W) -> crate::Result<()> {
69            header.write_to(w)?;
70            let mut buf = vec![];
71            self.encode_body(&mut buf)?;
72            w.write_all(&buf)?;
73            Ok(())
74        }
75    }
76    impl<T: Element> WriteElement for T {}
77}
78/// tokio non-blocking I/O implementations, supporting async reading and writing.
79#[cfg(feature = "tokio")]
80#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
81pub mod tokio_impl {
82    use crate::{
83        base::Header,
84        element::Element,
85        master::{Cluster, Segment},
86    };
87
88    use std::future::Future;
89    use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt};
90
91    /// Read from a reader asynchronously.
92    pub trait AsyncReadFrom: Sized {
93        /// Read Self from a reader.
94        fn async_read_from<R: tokio::io::AsyncRead + Unpin>(
95            r: &mut R,
96        ) -> impl Future<Output = crate::Result<Self>>;
97    }
98
99    /// Read an element from a reader provided the header asynchronously.
100    pub trait AsyncReadElement: Sized + Element {
101        /// Read an element from a reader provided the header.
102        fn async_read_element<R: tokio::io::AsyncRead + Unpin>(
103            header: &Header,
104            r: &mut R,
105        ) -> impl std::future::Future<Output = crate::Result<Self>> {
106            async {
107                let body = header.read_body_tokio(r).await?;
108                Self::decode_body(&mut &body[..])
109            }
110        }
111    }
112    impl<T: Element> AsyncReadElement for T {}
113
114    /// Write to a writer asynchronously.
115    pub trait AsyncWriteTo {
116        /// Write to a writer asynchronously.
117        fn async_write_to<W: tokio::io::AsyncWrite + Unpin>(
118            &self,
119            w: &mut W,
120        ) -> impl std::future::Future<Output = crate::Result<()>>;
121    }
122
123    impl<T: crate::functional::Encode> AsyncWriteTo for T {
124        async fn async_write_to<W: tokio::io::AsyncWrite + Unpin>(
125            &self,
126            w: &mut W,
127        ) -> crate::Result<()> {
128            //TODO should avoid the extra allocation here
129            let mut buf = vec![];
130            self.encode(&mut buf)?;
131            Ok(w.write_all(&buf).await?)
132        }
133    }
134
135    /// Write an element to a writer provided the header asynchronously.
136    pub trait AsyncWriteElement: Sized + Element {
137        /// Write an element to a writer asynchronously.
138        fn async_write_element<W: tokio::io::AsyncWrite + Unpin>(
139            &self,
140            header: &Header,
141            w: &mut W,
142        ) -> impl std::future::Future<Output = crate::Result<()>> {
143            async {
144                header.async_write_to(w).await?;
145                let mut buf = vec![];
146                self.encode_body(&mut buf)?;
147                Ok(w.write_all(&buf).await?)
148            }
149        }
150    }
151    impl<T: Element> AsyncWriteElement for T {}
152
153    impl Header {
154        /// Read the body of the element from a reader into memory.
155        pub(crate) async fn read_body_tokio<R: AsyncRead + Unpin>(
156            &self,
157            r: &mut R,
158        ) -> crate::Result<Vec<u8>> {
159            // Segment and Cluster can have unknown size, but we don't support that here.
160            let size = if self.size.is_unknown && [Segment::ID, Cluster::ID].contains(&self.id) {
161                return Err(crate::Error::ElementBodySizeUnknown(self.id));
162            } else {
163                *self.size
164            };
165            // we allocate 4096 bytes upfront and grow as needed
166            let cap = size.min(4096) as usize;
167            let mut buf = Vec::with_capacity(cap);
168            let n = tokio::io::copy(&mut r.take(size), &mut buf).await?;
169            if size != n {
170                return Err(crate::Error::OutOfBounds);
171            }
172            Ok(buf)
173        }
174    }
175}