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