1use crate::internal::*;
3use crate::lib::std::io::Write;
4
5macro_rules! try_write(($out:ident, $len:ident, $data:expr) => (
6 match $out.write($data) {
7 Err(io) => Err(GenError::IoError(io)),
8 Ok(n) if n < $len => Err(GenError::BufferTooSmall($len - n)),
9 Ok(_) => Ok($out)
10 }
11));
12
13pub fn slice<S: AsRef<[u8]>, W: Write>(data: S) -> impl SerializeFn<W> {
29 let len = data.as_ref().len();
30
31 move |mut out: WriteContext<W>| try_write!(out, len, data.as_ref())
32}
33
34pub fn string<S: AsRef<str>, W: Write>(data: S) -> impl SerializeFn<W> {
50 let len = data.as_ref().len();
51
52 move |mut out: WriteContext<W>| try_write!(out, len, data.as_ref().as_bytes())
53}
54
55#[cfg(feature = "std")]
57pub fn hex<S: crate::lib::std::fmt::UpperHex, W: Write>(data: S) -> impl SerializeFn<W> {
71 move |mut out: WriteContext<W>| match write!(out, "{:X}", data) {
72 Err(io) => Err(GenError::IoError(io)),
73 Ok(()) => Ok(out),
74 }
75}
76
77pub fn skip<W: Write + Skip>(len: usize) -> impl SerializeFn<W> {
90 move |out: WriteContext<W>| W::skip(out, len)
91}
92
93pub fn cond<F, W: Write>(condition: bool, f: F) -> impl SerializeFn<W>
109where
110 F: SerializeFn<W>,
111{
112 move |out: WriteContext<W>| {
113 if condition {
114 f(out)
115 } else {
116 Ok(out)
117 }
118 }
119}
120
121pub fn back_to_the_buffer<W: BackToTheBuffer, Tmp, Gen, Before>(
140 reserved: usize,
141 gen: Gen,
142 before: Before,
143) -> impl SerializeFn<W>
144where
145 Gen: Fn(WriteContext<W>) -> Result<(WriteContext<W>, Tmp), GenError>,
146 Before: Fn(WriteContext<W>, Tmp) -> GenResult<W>,
147{
148 move |w: WriteContext<W>| W::reserve_write_use(w, reserved, &gen, &before)
149}
150
151#[cfg(test)]
162mod test {
163 use super::*;
164 use crate::bytes::{be_u32, be_u8};
165 use crate::sequence::tuple;
166
167 #[test]
168 fn test_gen_with_length() {
169 let mut buf = [0; 8];
170 {
171 let (len_buf, buf) = buf.split_at_mut(4);
172 let (_, pos) = gen(string("test"), buf).unwrap();
173 gen(be_u32(pos as u32), len_buf).unwrap();
174 }
175 assert_eq!(&buf, &[0, 0, 0, 4, b't', b'e', b's', b't']);
176 }
177
178 #[test]
179 fn test_back_to_the_buffer() {
180 let mut buf = [0; 9];
181
182 let new_buf = gen_simple(
183 tuple((
184 back_to_the_buffer(
185 4,
186 move |buf| gen(string("test"), buf),
187 move |buf, len| gen_simple(be_u32(len as u32), buf),
188 ),
189 be_u8(42),
190 )),
191 &mut buf[..],
192 )
193 .unwrap();
194
195 assert!(new_buf.is_empty());
196 assert_eq!(&buf, &[0, 0, 0, 4, b't', b'e', b's', b't', 42]);
197 }
198
199 #[cfg(feature = "std")]
200 #[test]
201 fn test_back_to_the_buffer_vec() {
202 let buf = Vec::new();
203
204 let buf = gen_simple(
205 tuple((
206 back_to_the_buffer(
207 4,
208 move |buf| gen(string("test"), buf),
209 move |buf, len| gen_simple(be_u32(len as u32), buf),
210 ),
211 be_u8(42),
212 )),
213 buf,
214 )
215 .unwrap();
216
217 assert_eq!(&buf[..], &[0, 0, 0, 4, b't', b'e', b's', b't', 42]);
218 }
219
220 #[test]
221 fn test_back_to_the_buffer_cursor() {
222 let mut buf = [0; 9];
223 {
224 let cursor = crate::lib::std::io::Cursor::new(&mut buf[..]);
225 let cursor = gen_simple(
226 tuple((
227 back_to_the_buffer(
228 4,
229 move |buf| gen(string("test"), buf),
230 move |buf, len| gen_simple(be_u32(len as u32), buf),
231 ),
232 be_u8(42),
233 )),
234 cursor,
235 )
236 .unwrap();
237 assert_eq!(cursor.position(), 9);
238 }
239 assert_eq!(&buf, &[0, 0, 0, 4, b't', b'e', b's', b't', 42]);
240 }
241
242 #[test]
243 fn test_back_to_the_buffer_cursor_counter() {
244 let mut buf = [0; 10];
245 {
246 let cursor = crate::lib::std::io::Cursor::new(&mut buf[..]);
247 let (cursor, pos) = gen(
248 tuple((
249 be_u8(64),
250 back_to_the_buffer(
251 4,
252 &move |buf| gen(string("test"), buf),
253 &move |buf, len| gen_simple(be_u32(len as u32), buf),
254 ),
255 be_u8(42),
256 )),
257 cursor,
258 )
259 .unwrap();
260 assert_eq!(pos, 10);
261 assert_eq!(cursor.position(), 10);
262 }
263 assert_eq!(&buf, &[64, 0, 0, 0, 4, b't', b'e', b's', b't', 42]);
264 }
265}