handy_async/io/
write_pattern.rs

1use std::io::{Write, Result, Error};
2use futures::{Poll, Future};
3use byteorder::{ByteOrder, NativeEndian, BigEndian, LittleEndian};
4
5use pattern::{Buf, Window};
6use pattern::write::{self, U24, I24, U40, I40, U48, I48, U56, I56};
7use pattern::combinators::{PartialBuf, LE, BE};
8use matcher::{AsyncMatch, Matcher};
9use io::{AsyncWrite, AsyncIoError};
10
11/// A matcher to write patterns into the inner writer `W`.
12///
13/// This is mainly used to define your own writing patterns.
14/// See the example of the [`WriteInto`](./trait.WriteInto.html) trait.
15pub struct PatternWriter<W>(W);
16impl<W: Write> PatternWriter<W> {
17    /// Makes new `PatternWriter` instance.
18    pub fn new(inner: W) -> Self {
19        PatternWriter(inner)
20    }
21}
22impl<W: Write> Write for PatternWriter<W> {
23    fn write(&mut self, buf: &[u8]) -> Result<usize> {
24        self.0.write(buf)
25    }
26    fn flush(&mut self) -> Result<()> {
27        self.0.flush()
28    }
29}
30impl<W> Matcher for PatternWriter<W> {
31    type Error = Error;
32}
33
34/// The `WriteInto` trait allows for writing
35/// a value of this pattern to a sink asynchronously.
36///
37/// # Notice
38///
39/// For executing asynchronously, we assume the writer `W` returns
40/// `the std::io::ErrorKind::WouldBlock` error if a write operation would be about to block.
41///
42/// # Examples
43///
44/// Defines your own writing pattern:
45///
46/// ```
47/// # extern crate futures;
48/// # extern crate handy_async;
49/// use std::io::Write;
50/// use futures::{Future, BoxFuture};
51/// use handy_async::io::{WriteInto, PatternWriter, AsyncIoError};
52/// use handy_async::pattern::Pattern;
53/// use handy_async::matcher::AsyncMatch;
54///
55/// // Defines pattern.
56/// struct HelloWorld;
57/// impl Pattern for HelloWorld {
58///    type Value = ();
59/// }
60///
61/// // Implements pattern maching between `PatternWriter<W>` and `HelloWorld`.
62/// impl<W: Write + Send + 'static> AsyncMatch<PatternWriter<W>> for HelloWorld {
63///     type Future = BoxFuture<(PatternWriter<W>, ()), AsyncIoError<PatternWriter<W>>>;
64///     fn async_match(self, matcher: PatternWriter<W>) -> Self::Future {
65///         Vec::from(&b"Hello World!"[..]).map(|_| ()).async_match(matcher).boxed()
66///     }
67/// }
68///
69/// # fn main() {
70/// // Executes pattern matching.
71/// let pattern = ("Hey! ".to_string(), HelloWorld);
72/// let (output, _) = pattern.write_into(Vec::new()).wait().unwrap();
73/// assert_eq!(output, b"Hey! Hello World!");
74/// # }
75/// ```
76pub trait WriteInto<W: Write>: AsyncMatch<PatternWriter<W>> {
77    /// Creates a future instance to write a value of the pattern to `writer`.
78    ///
79    /// # Examples
80    ///
81    /// ```
82    /// # extern crate futures;
83    /// # extern crate handy_async;
84    /// use futures::Future;
85    /// use handy_async::io::WriteInto;
86    /// use handy_async::pattern::Endian;
87    ///
88    /// # fn main() {
89    /// let pattern = (1u8, 2u16.be());
90    /// let (output, _) = pattern.write_into(Vec::new()).wait().unwrap();
91    /// assert_eq!(output, [1, 0, 2]);
92    /// # }
93    /// ```
94    fn write_into(self, writer: W) -> WritePattern<Self, W> {
95        WritePattern(self.async_match(PatternWriter(writer)))
96    }
97
98    /// Synchronous version of the `WriteInto::write_into` method.
99    fn sync_write_into(self, writer: W) -> Result<Self::Value> {
100        self.write_into(writer).wait().map(|(_, v)| v).map_err(
101            |e| {
102                e.into_error()
103            },
104        )
105    }
106}
107impl<W: Write, T> WriteInto<W> for T
108where
109    T: AsyncMatch<PatternWriter<W>>,
110{
111}
112
113/// Future to write a pattern `P` into `W`.
114///
115/// This is created by calling `WriteInto::write_into` method.
116pub struct WritePattern<P, W>(P::Future)
117where
118    P: AsyncMatch<PatternWriter<W>>;
119impl<P, W> Future for WritePattern<P, W>
120where
121    P: AsyncMatch<PatternWriter<W>>,
122{
123    type Item = (W, P::Value);
124    type Error = AsyncIoError<W>;
125    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
126        Ok(self.0.poll().map_err(|e| e.map_state(|w| w.0))?.map(
127            |(m, v)| {
128                (m.0, v)
129            },
130        ))
131    }
132}
133
134/// A future which will flush the internal buffer of `W`.
135///
136/// This is created by calling `WriteInto::write_into` method for
137/// `Flush` pattern.
138pub struct WriteFlush<W>(super::futures::Flush<PatternWriter<W>>);
139impl<W: Write> Future for WriteFlush<W> {
140    type Item = (PatternWriter<W>, ());
141    type Error = AsyncIoError<PatternWriter<W>>;
142    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
143        Ok(self.0.poll()?.map(|m| (m, ())))
144    }
145}
146impl<W: Write> AsyncMatch<PatternWriter<W>> for write::Flush {
147    type Future = WriteFlush<W>;
148    fn async_match(self, matcher: PatternWriter<W>) -> Self::Future {
149        WriteFlush(matcher.async_flush())
150    }
151}
152
153/// A future which will write bytes contained in the buffer `B` to `W`.
154///
155/// This future is generally created by invoking
156/// `WriteInto::write_into` method for buffer like patterns
157/// such as the following.
158///
159/// ```
160/// use handy_async::io::WriteInto;
161/// use handy_async::pattern::{Buf, Window};
162///
163/// vec![0; 32].write_into(std::io::sink());
164/// Buf([0; 32]).write_into(std::io::sink());
165/// Window::new([0; 32]).skip(4).write_into(std::io::sink());
166/// ```
167pub struct WriteBuf<W, B>(super::futures::WriteAll<PatternWriter<W>, B>);
168impl<W: Write, B: AsRef<[u8]>> Future for WriteBuf<W, B> {
169    type Item = (PatternWriter<W>, B);
170    type Error = AsyncIoError<PatternWriter<W>>;
171    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
172        self.0.poll().map_err(|e| e.map_state(|(w, _)| w))
173    }
174}
175impl<W: Write, B: AsRef<[u8]>> AsyncMatch<PatternWriter<W>> for Buf<B> {
176    type Future = WriteBuf<W, B>;
177    fn async_match(self, matcher: PatternWriter<W>) -> Self::Future {
178        WriteBuf(matcher.async_write_all(self.0))
179    }
180}
181impl<W: Write> AsyncMatch<PatternWriter<W>> for Vec<u8> {
182    type Future = WriteBuf<W, Self>;
183    fn async_match(self, matcher: PatternWriter<W>) -> Self::Future {
184        WriteBuf(matcher.async_write_all(self))
185    }
186}
187impl<W: Write> AsyncMatch<PatternWriter<W>> for String {
188    type Future = WriteBuf<W, Self>;
189    fn async_match(self, matcher: PatternWriter<W>) -> Self::Future {
190        WriteBuf(matcher.async_write_all(self))
191    }
192}
193impl<W: Write, B: AsRef<[u8]>> AsyncMatch<PatternWriter<W>> for Window<B> {
194    type Future = WriteBuf<W, Self>;
195    fn async_match(self, matcher: PatternWriter<W>) -> Self::Future {
196        WriteBuf(matcher.async_write_all(self))
197    }
198}
199
200/// A future which will write bytes contained in the buffer `B` to `W`
201/// to the extent possible.
202///
203/// This future is generally created by invoking
204/// `WriteInto::write_into` method for `PartialBuf` pattern
205/// such as the following.
206///
207/// ```
208/// # extern crate futures;
209/// # extern crate handy_async;
210/// use handy_async::io::WriteInto;
211/// use handy_async::pattern::AllowPartial;
212/// use futures::Future;
213///
214/// # fn main() {
215/// // `PartialBuf` pattern is created via `allow_partial` method.
216/// let pattern = vec![0; 32].allow_partial();
217/// let (_, (_, written_size)) = pattern.write_into(&mut &mut [0; 4][..]).wait().unwrap();
218/// assert_eq!(written_size, 4);
219/// # }
220/// ```
221pub struct WritePartialBuf<W, B>(super::futures::WriteBytes<PatternWriter<W>, B>);
222impl<W: Write, B: AsRef<[u8]>> Future for WritePartialBuf<W, B> {
223    type Item = (PatternWriter<W>, (B, usize));
224    type Error = AsyncIoError<PatternWriter<W>>;
225    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
226        self.0
227            .poll()
228            .map(|a| a.map(|(w, b, s)| (w, (b, s))))
229            .map_err(|e| e.map_state(|(w, _)| w))
230    }
231}
232impl<W: Write, B: AsRef<[u8]>> AsyncMatch<PatternWriter<W>> for PartialBuf<B> {
233    type Future = WritePartialBuf<W, B>;
234    fn async_match(self, matcher: PatternWriter<W>) -> Self::Future {
235        WritePartialBuf(matcher.async_write(self.0))
236    }
237}
238
239/// A future which will write a fixnum associated with `P` into `W`.
240pub struct WriteFixnum<W, P>
241where
242    P: AsyncMatch<PatternWriter<W>>,
243{
244    future: P::Future,
245}
246impl<W: Write, P> Future for WriteFixnum<W, P>
247where
248    P: AsyncMatch<PatternWriter<W>>,
249{
250    type Item = (PatternWriter<W>, ());
251    type Error = AsyncIoError<PatternWriter<W>>;
252    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
253        Ok(self.future.poll()?.map(|(w, _)| (w, ())))
254    }
255}
256
257macro_rules! impl_write_fixnum_pattern {
258    ($pat:ty, $size:expr, $conv:expr) => {
259        impl<W: Write> AsyncMatch<PatternWriter<W>> for $pat {
260            type Future = WriteFixnum<W, Buf<[u8; $size]>>;
261            fn async_match(self, matcher: PatternWriter<W>) -> Self::Future {
262                let mut buf = [0; $size];
263                $conv(&mut buf[..], self);
264                let future = Buf(buf).async_match(matcher);
265                WriteFixnum{future: future}
266            }
267        }
268    }
269}
270impl_write_fixnum_pattern!(u8, 1, |b: &mut [u8], n: Self| b[0] = n);
271impl_write_fixnum_pattern!(i8, 1, |b: &mut [u8], n: Self| b[0] = n as u8);
272
273impl_write_fixnum_pattern!(u16, 2, NativeEndian::write_u16);
274impl_write_fixnum_pattern!(BE<u16>, 2, |b: &mut [u8], n: Self| BigEndian::write_u16(b,n.0));
275impl_write_fixnum_pattern!(LE<u16>, 2, |b: &mut [u8], n: Self| LittleEndian::write_u16(b,n.0));
276impl_write_fixnum_pattern!(i16, 2, NativeEndian::write_i16);
277impl_write_fixnum_pattern!(BE<i16>, 2, |b: &mut [u8], n: Self| BigEndian::write_i16(b,n.0));
278impl_write_fixnum_pattern!(LE<i16>, 2, |b: &mut [u8], n: Self| LittleEndian::write_i16(b,n.0));
279
280impl_write_fixnum_pattern!(
281    U24, 3, |b: &mut [u8], n: Self| NativeEndian::write_uint(b, u64::from(n.0), 3));
282impl_write_fixnum_pattern!(
283    BE<U24>, 3, |b: &mut [u8], n: Self| BigEndian::write_uint(b,u64::from((n.0).0), 3));
284impl_write_fixnum_pattern!(
285    LE<U24>, 3, |b: &mut [u8], n: Self| LittleEndian::write_uint(b,u64::from((n.0).0), 3));
286impl_write_fixnum_pattern!(
287    I24, 3, |b: &mut [u8], n: Self| NativeEndian::write_int(b, i64::from(n.0), 3));
288impl_write_fixnum_pattern!(
289    BE<I24>, 3, |b: &mut [u8], n: Self| BigEndian::write_int(b,i64::from((n.0).0), 3));
290impl_write_fixnum_pattern!(
291    LE<I24>, 3, |b: &mut [u8], n: Self| LittleEndian::write_int(b,i64::from((n.0).0), 3));
292
293impl_write_fixnum_pattern!(u32, 4, NativeEndian::write_u32);
294impl_write_fixnum_pattern!(BE<u32>, 4, |b: &mut [u8], n: Self| BigEndian::write_u32(b,n.0));
295impl_write_fixnum_pattern!(LE<u32>, 4, |b: &mut [u8], n: Self| LittleEndian::write_u32(b,n.0));
296impl_write_fixnum_pattern!(i32, 4, NativeEndian::write_i32);
297impl_write_fixnum_pattern!(BE<i32>, 4, |b: &mut [u8], n: Self| BigEndian::write_i32(b,n.0));
298impl_write_fixnum_pattern!(LE<i32>, 4, |b: &mut [u8], n: Self| LittleEndian::write_i32(b,n.0));
299
300impl_write_fixnum_pattern!(U40, 5,
301                           |b: &mut [u8], n: Self| NativeEndian::write_uint(b, n.0 as u64, 5));
302impl_write_fixnum_pattern!(BE<U40>, 5,
303                           |b: &mut [u8], n: Self| BigEndian::write_uint(b,(n.0).0 as u64, 5));
304impl_write_fixnum_pattern!(LE<U40>, 5,
305                           |b: &mut [u8], n: Self| LittleEndian::write_uint(b,(n.0).0 as u64, 5));
306impl_write_fixnum_pattern!(I40, 5,
307                           |b: &mut [u8], n: Self| NativeEndian::write_int(b, n.0 as i64, 5));
308impl_write_fixnum_pattern!(BE<I40>, 5,
309                           |b: &mut [u8], n: Self| BigEndian::write_int(b,(n.0).0 as i64, 5));
310impl_write_fixnum_pattern!(LE<I40>, 5,
311                           |b: &mut [u8], n: Self| LittleEndian::write_int(b,(n.0).0 as i64, 5));
312
313impl_write_fixnum_pattern!(U48, 6,
314                           |b: &mut [u8], n: Self| NativeEndian::write_uint(b, n.0 as u64, 6));
315impl_write_fixnum_pattern!(BE<U48>, 6,
316                           |b: &mut [u8], n: Self| BigEndian::write_uint(b,(n.0).0 as u64, 6));
317impl_write_fixnum_pattern!(LE<U48>, 6,
318                           |b: &mut [u8], n: Self| LittleEndian::write_uint(b,(n.0).0 as u64, 6));
319impl_write_fixnum_pattern!(I48, 6,
320                           |b: &mut [u8], n: Self| NativeEndian::write_int(b, n.0 as i64, 6));
321impl_write_fixnum_pattern!(BE<I48>, 6,
322                           |b: &mut [u8], n: Self| BigEndian::write_int(b,(n.0).0 as i64, 6));
323impl_write_fixnum_pattern!(LE<I48>, 6,
324                           |b: &mut [u8], n: Self| LittleEndian::write_int(b,(n.0).0 as i64, 6));
325
326impl_write_fixnum_pattern!(U56, 7,
327                           |b: &mut [u8], n: Self| NativeEndian::write_uint(b, n.0 as u64, 7));
328impl_write_fixnum_pattern!(BE<U56>, 7,
329                           |b: &mut [u8], n: Self| BigEndian::write_uint(b,(n.0).0 as u64, 7));
330impl_write_fixnum_pattern!(LE<U56>, 7,
331                           |b: &mut [u8], n: Self| LittleEndian::write_uint(b,(n.0).0 as u64, 7));
332impl_write_fixnum_pattern!(I56, 7,
333                           |b: &mut [u8], n: Self| NativeEndian::write_int(b, n.0 as i64, 7));
334impl_write_fixnum_pattern!(BE<I56>, 7,
335                           |b: &mut [u8], n: Self| BigEndian::write_int(b,(n.0).0 as i64, 7));
336impl_write_fixnum_pattern!(LE<I56>, 7,
337                           |b: &mut [u8], n: Self| LittleEndian::write_int(b,(n.0).0 as i64, 7));
338
339impl_write_fixnum_pattern!(u64, 8, NativeEndian::write_u64);
340impl_write_fixnum_pattern!(BE<u64>, 8, |b: &mut [u8], n: Self| BigEndian::write_u64(b,n.0));
341impl_write_fixnum_pattern!(LE<u64>, 8, |b: &mut [u8], n: Self| LittleEndian::write_u64(b,n.0));
342impl_write_fixnum_pattern!(i64, 8, NativeEndian::write_i64);
343impl_write_fixnum_pattern!(BE<i64>, 8, |b: &mut [u8], n: Self| BigEndian::write_i64(b,n.0));
344impl_write_fixnum_pattern!(LE<i64>, 8, |b: &mut [u8], n: Self| LittleEndian::write_i64(b,n.0));