Skip to main content

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 + ?Sized>(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 + ?Sized>(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 + ?Sized>(&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 + ?Sized>(&self, w: &mut W) -> crate::Result<()>;
53    }
54
55    impl<T: Encode> WriteTo for T {
56        fn write_to<W: Write + ?Sized>(&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 + ?Sized>(
69            &self,
70            header: &Header,
71            w: &mut W,
72        ) -> crate::Result<()> {
73            header.write_to(w)?;
74            let mut buf = vec![];
75            self.encode_body(&mut buf)?;
76            w.write_all(&buf)?;
77            Ok(())
78        }
79    }
80    impl<T: Element> WriteElement for T {}
81}
82/// tokio non-blocking I/O implementations, supporting async reading and writing.
83#[cfg(feature = "tokio")]
84#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
85pub mod tokio_impl {
86    use crate::{
87        base::Header,
88        element::Element,
89        master::{Cluster, Segment},
90    };
91
92    use std::future::Future;
93    use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt};
94
95    /// Read from a reader asynchronously.
96    pub trait AsyncReadFrom: Sized {
97        /// Read Self from a reader.
98        fn async_read_from<R: tokio::io::AsyncRead + Unpin + ?Sized>(
99            r: &mut R,
100        ) -> impl Future<Output = crate::Result<Self>>;
101    }
102
103    /// Read an element from a reader provided the header asynchronously.
104    pub trait AsyncReadElement: Sized + Element {
105        /// Read an element from a reader provided the header.
106        fn async_read_element<R: tokio::io::AsyncRead + Unpin + ?Sized>(
107            header: &Header,
108            r: &mut R,
109        ) -> impl std::future::Future<Output = crate::Result<Self>> {
110            async {
111                let body = header.read_body_tokio(r).await?;
112                Self::decode_body(&mut &body[..])
113            }
114        }
115    }
116    impl<T: Element> AsyncReadElement for T {}
117
118    /// Write to a writer asynchronously.
119    pub trait AsyncWriteTo {
120        /// Write to a writer asynchronously.
121        fn async_write_to<W: tokio::io::AsyncWrite + Unpin + ?Sized>(
122            &self,
123            w: &mut W,
124        ) -> impl std::future::Future<Output = crate::Result<()>>;
125    }
126
127    impl<T: crate::functional::Encode> AsyncWriteTo for T {
128        async fn async_write_to<W: tokio::io::AsyncWrite + Unpin + ?Sized>(
129            &self,
130            w: &mut W,
131        ) -> crate::Result<()> {
132            //TODO should avoid the extra allocation here
133            let mut buf = vec![];
134            self.encode(&mut buf)?;
135            Ok(w.write_all(&buf).await?)
136        }
137    }
138
139    /// Write an element to a writer provided the header asynchronously.
140    pub trait AsyncWriteElement: Sized + Element {
141        /// Write an element to a writer asynchronously.
142        fn async_write_element<W: tokio::io::AsyncWrite + Unpin + ?Sized>(
143            &self,
144            header: &Header,
145            w: &mut W,
146        ) -> impl std::future::Future<Output = crate::Result<()>> {
147            async {
148                header.async_write_to(w).await?;
149                let mut buf = vec![];
150                self.encode_body(&mut buf)?;
151                Ok(w.write_all(&buf).await?)
152            }
153        }
154    }
155    impl<T: Element> AsyncWriteElement for T {}
156
157    impl Header {
158        /// Read the body of the element from a reader into memory.
159        pub(crate) async fn read_body_tokio<R: AsyncRead + Unpin + ?Sized>(
160            &self,
161            r: &mut R,
162        ) -> crate::Result<Vec<u8>> {
163            // Segment and Cluster can have unknown size, but we don't support that here.
164            let size = if self.size.is_unknown && [Segment::ID, Cluster::ID].contains(&self.id) {
165                return Err(crate::Error::ElementBodySizeUnknown(self.id));
166            } else {
167                *self.size
168            };
169            // we allocate 4096 bytes upfront and grow as needed
170            let cap = size.min(4096) as usize;
171            let mut buf = Vec::with_capacity(cap);
172            let n = tokio::io::copy(&mut r.take(size), &mut buf).await?;
173            if size != n {
174                return Err(crate::Error::OutOfBounds);
175            }
176            Ok(buf)
177        }
178    }
179}