inarybay_runtime/
lib.rs

1#[inline]
2pub fn read(source: &mut dyn std::io::Read, len: usize) -> std::io::Result<Vec<u8>> {
3    let mut out = vec![];
4    if len == 0 {
5        source.read_to_end(&mut out)?;
6    } else {
7        out.resize(len, 0u8);
8        source.read_exact(&mut out)?;
9    }
10    return Ok(out);
11}
12
13#[inline]
14pub fn read_delimited(source: &mut dyn std::io::BufRead, delimiter: &[u8]) -> std::io::Result<Vec<u8>> {
15    let mut out = vec![];
16    let mut delim_buffer = vec![];
17    delim_buffer.resize(delimiter.len() - 1, 0u8);
18    loop {
19        // Read up to first delimiter byte
20        source.read_until(delimiter[0], &mut out)?;
21
22        // Read rest of delimiter
23        let mut delim_size = 0usize;
24        while delim_size < delimiter.len() - 1 {
25            let count = source.read(&mut delim_buffer[delim_size..])?;
26            if count == 0 {
27                // EOF, delimiter wasn't read, return everything
28                out.extend(delim_buffer);
29                return Ok(out);
30            }
31            delim_size += count;
32        }
33
34        // If the whole delimiter was read return
35        if delim_buffer == delimiter[1..] {
36            out.pop();
37            return Ok(out);
38        }
39
40        // Something that wasn't the delimiter was read, treat as data and continue
41        out.extend(&delim_buffer);
42    }
43}
44
45#[cfg(feature = "async")]
46pub mod async_ {
47    pub use futures::io::{
48        AsyncReadExt,
49        AsyncBufReadExt,
50        AsyncWriteExt,
51    };
52
53    #[inline]
54    pub async fn read<T: futures::io::AsyncReadExt + Unpin>(source: &mut T, len: usize) -> std::io::Result<Vec<u8>> {
55        let mut out = vec![];
56        if len == 0 {
57            source.read_to_end(&mut out).await?;
58        } else {
59            out.resize(len, 0u8);
60            source.read_exact(&mut out).await?;
61        }
62        return Ok(out);
63    }
64
65    #[inline]
66    pub async fn read_delimited<
67        T: futures::io::AsyncBufReadExt + Unpin,
68    >(source: &mut T, delimiter: &[u8]) -> std::io::Result<Vec<u8>> {
69        let mut out = vec![];
70        let mut delim_buffer = vec![];
71        delim_buffer.resize(delimiter.len() - 1, 0u8);
72        loop {
73            // Read up to first delimiter byte
74            source.read_until(delimiter[0], &mut out).await?;
75
76            // Read rest of delimiter
77            let mut delim_size = 0usize;
78            while delim_size < delimiter.len() - 1 {
79                let count = source.read(&mut delim_buffer[delim_size..]).await?;
80                if count == 0 {
81                    // EOF, delimiter wasn't read, return everything
82                    out.extend(delim_buffer);
83                    return Ok(out);
84                }
85                delim_size += count;
86            }
87
88            // If the whole delimiter was read return
89            if delim_buffer == delimiter[1..] {
90                out.pop();
91                return Ok(out);
92            }
93
94            // Something that wasn't the delimiter was read, treat as data and continue
95            out.extend(&delim_buffer);
96        }
97    }
98}
99
100pub mod lowheap_error {
101    use std::fmt::Display;
102
103    #[derive(Debug)]
104    pub enum ReadErrorInner {
105        Io(std::io::Error),
106        Other(&'static str),
107    }
108
109    #[derive(Debug)]
110    pub struct ReadError {
111        pub node: &'static str,
112        pub inner: ReadErrorInner,
113    }
114
115    impl Display for ReadError {
116        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117            return format_args!("Error reading in node {}: {:?}", self.node, self.inner).fmt(f);
118        }
119    }
120
121    impl std::error::Error for ReadError { }
122
123    impl ReadError {
124        pub fn new(node: &'static str, text: &'static str) -> ReadError {
125            return ReadError {
126                node: node,
127                inner: ReadErrorInner::Other(text),
128            };
129        }
130    }
131
132    pub trait ReadErrCtx<T> {
133        fn errorize(self, node: &'static str, text: &'static str) -> Result<T, ReadError>;
134    }
135
136    impl<T, E> ReadErrCtx<T> for Result<T, E> {
137        fn errorize(self, node: &'static str, text: &'static str) -> Result<T, ReadError> {
138            match self {
139                Err(_) => return Err(ReadError {
140                    node: node,
141                    inner: ReadErrorInner::Other(text),
142                }),
143                Ok(v) => return Ok(v),
144            }
145        }
146    }
147
148    pub trait ReadErrCtxIo<T> {
149        fn errorize_io(self, node: &'static str) -> Result<T, ReadError>;
150    }
151
152    impl<T> ReadErrCtxIo<T> for Result<T, std::io::Error> {
153        fn errorize_io(self, node: &'static str) -> Result<T, ReadError> {
154            match self {
155                Err(e) => return Err(ReadError {
156                    node: node,
157                    inner: ReadErrorInner::Io(e),
158                }),
159                Ok(v) => return Ok(v),
160            }
161        }
162    }
163}
164
165#[cfg(not(noheap))]
166pub mod error {
167    use std::fmt::Display;
168
169    #[derive(Debug)]
170    pub enum ReadErrorInner {
171        Io(std::io::Error),
172        Other(String),
173    }
174
175    #[derive(Debug)]
176    pub struct ReadError {
177        pub node: &'static str,
178        pub inner: ReadErrorInner,
179    }
180
181    impl Display for ReadError {
182        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183            return format_args!("Error reading in node {}: {:?}", self.node, self.inner).fmt(f);
184        }
185    }
186
187    impl std::error::Error for ReadError { }
188
189    impl ReadError {
190        pub fn new(node: &'static str, text: impl Into<String>) -> ReadError {
191            return ReadError {
192                node: node,
193                inner: ReadErrorInner::Other(text.into()),
194            };
195        }
196    }
197
198    pub trait ReadErrCtx<T> {
199        fn errorize(self, node: &'static str) -> Result<T, ReadError>;
200    }
201
202    impl<T, E: Display> ReadErrCtx<T> for Result<T, E> {
203        fn errorize(self, node: &'static str) -> Result<T, ReadError> {
204            match self {
205                Err(e) => return Err(ReadError {
206                    node: node,
207                    inner: ReadErrorInner::Other(e.to_string()),
208                }),
209                Ok(v) => return Ok(v),
210            }
211        }
212    }
213
214    pub trait ReadErrCtxIo<T> {
215        fn errorize_io(self, node: &'static str) -> Result<T, ReadError>;
216    }
217
218    impl<T> ReadErrCtxIo<T> for Result<T, std::io::Error> {
219        fn errorize_io(self, node: &'static str) -> Result<T, ReadError> {
220            match self {
221                Err(e) => return Err(ReadError {
222                    node: node,
223                    inner: ReadErrorInner::Io(e),
224                }),
225                Ok(v) => return Ok(v),
226            }
227        }
228    }
229}