huawei_modem/
codec.rs

1//! Contains the Tokio codec used to decode the AT protocol.
2use tokio_codec::{Encoder, Decoder};
3use bytes::BytesMut;
4use crate::at::{AtCommand, AtResponse};
5use failure;
6use crate::parse;
7
8/// Encodes AT commands into text to be sent to a modem, and decodes its responses into AT
9/// responses.
10pub struct AtCodec;
11
12impl Decoder for AtCodec {
13    type Item = Vec<AtResponse>;
14    type Error = failure::Error;
15
16    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
17        use nom::IResult;
18        trace!("decoding data: {:?}", src);
19        let (point, data) = match parse::responses(src) {
20            IResult::Done(rest, data) => {
21                if data.len() == 0 {
22                    return Ok(None);
23                }
24                (rest.len(), data)
25            },
26            IResult::Error(e) => return Err(e.into()),
27            IResult::Incomplete(_) => return Ok(None)
28        };
29        let len = src.len().saturating_sub(point);
30        src.split_to(len);
31        Ok(Some(data))
32    }
33}
34impl Encoder for AtCodec {
35    type Item = AtCommand;
36    type Error = failure::Error;
37
38    fn encode(&mut self, item: AtCommand, dst: &mut BytesMut) -> Result<(), Self::Error> {
39        use std::fmt::Write;
40        use bytes::BufMut;
41
42        trace!("sending data: {}", item);
43        let data = format!("\r\n{}\r\n", item);
44        let data_len = data.as_bytes().len();
45        let rem = dst.remaining_mut();
46        let delta = data_len.saturating_sub(rem);
47        if data_len > rem {
48            dst.reserve(data_len * 2);
49        }
50        dst.write_str(&data)
51            .map_err(|e| {
52                error!("writing to AtCodec buffer failed: rem {} len {} delta {}", rem, data_len, delta);
53                e
54            })?;
55        Ok(())
56    }
57}