at_commands/
serde.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! This module contains the top level AT command library methods.  It contains a
6//! trait for serialization and deserialization, which is implemented by the high level
7//! generated Command and Response types by composing together the parsing and
8//! unparsing methods for the low level ASTs with the the generated methods
9//! for raising and lowering from and to the low level ASTs and high level generated tyoes.
10
11pub use crate::parser::common::ParseError;
12use crate::{highlevel, lowlevel};
13use std::error::Error as StdError;
14use std::{fmt, io};
15use thiserror::Error;
16
17/// Errors that can occur while deserializing AT commands into high level generated AT command
18/// and response types.
19#[derive(Clone, Debug, Error, PartialEq)]
20pub enum DeserializeErrorCause {
21    // IO errors aren't Clone, so just use a String.
22    #[error("IO error: {0:?}")]
23    IoError(String),
24    // Just store the parse errors as Strings so as to not require clients to know about the
25    // pest parser types.
26    #[error("Parse error: {0:?}")]
27    ParseError(String),
28    #[error("Bad UTF8: {0:?}")]
29    Utf8Error(std::str::Utf8Error),
30    #[error("Parsed unknown command: {0:?}")]
31    UnknownCommand(lowlevel::Command),
32    #[error("Parsed unknown response: {0:?}")]
33    UnknownResponse(lowlevel::Response),
34    #[error("Parsed arguments do not match argument definition: {0:?}")]
35    UnknownArguments(lowlevel::Arguments),
36}
37
38impl From<io::Error> for DeserializeErrorCause {
39    fn from(io_error: io::Error) -> DeserializeErrorCause {
40        let string = format!("{:?}", io_error);
41        DeserializeErrorCause::IoError(string)
42    }
43}
44
45impl<RT: pest::RuleType> From<Box<ParseError<RT>>> for DeserializeErrorCause {
46    fn from(parse_error: Box<ParseError<RT>>) -> DeserializeErrorCause {
47        let string = format!("{:?}", parse_error);
48        DeserializeErrorCause::ParseError(string)
49    }
50}
51
52impl From<std::str::Utf8Error> for DeserializeErrorCause {
53    fn from(utf8_error: std::str::Utf8Error) -> DeserializeErrorCause {
54        DeserializeErrorCause::Utf8Error(utf8_error)
55    }
56}
57
58/// Error struct containing the cause of a deserialization error and the bytes that caused the error.
59#[derive(Clone, Debug, PartialEq)]
60pub struct DeserializeError {
61    pub cause: DeserializeErrorCause,
62    pub bytes: Vec<u8>,
63}
64
65impl fmt::Display for DeserializeError {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        fmt::Debug::fmt(self, f)
68    }
69}
70
71impl StdError for DeserializeError {}
72
73#[derive(Debug, Error)]
74pub enum SerializeErrorCause {
75    #[error("IO error: {0:?}")]
76    IoError(io::Error),
77}
78
79impl From<io::Error> for SerializeErrorCause {
80    fn from(io_error: io::Error) -> SerializeErrorCause {
81        SerializeErrorCause::IoError(io_error)
82    }
83}
84
85/// An error and remaining item to serialize if a serialization failure occurs while
86/// serializing multiple items.
87#[derive(Debug)]
88pub struct SerializeError<T> {
89    #[cfg_attr(test, allow(unused))]
90    pub remaining: Vec<T>,
91    #[cfg_attr(test, allow(unused))]
92    pub failed: T,
93    #[cfg_attr(test, allow(unused))]
94    pub cause: SerializeErrorCause,
95}
96
97impl<T: fmt::Debug> fmt::Display for SerializeError<T> {
98    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99        fmt::Debug::fmt(self, f)
100    }
101}
102
103impl<T: fmt::Debug> StdError for SerializeError<T> {}
104
105// While public traits can't depend on private traits, they can depend on public traits
106// in private modules.  By wrapping traits library clients should not have access to in
107// a module, clients can be prevented from using them.  The module is pub(crate) to allow
108// tests access to the internal traits.
109pub(crate) mod internal {
110    use super::{DeserializeError, DeserializeErrorCause, ParseError, SerializeErrorCause};
111    use crate::lowlevel::write_to::WriteTo;
112    use crate::parser::{command_grammar, command_parser, response_grammar, response_parser};
113    use crate::{highlevel, lowlevel, translate};
114    use std::io;
115
116    /// Trait to specify the parse, raise and lower functions for AT commands or responses.
117    /// This is used by the blanket SerDe implementation below to glue together the pieces
118    /// in a generic way.
119    pub trait SerDeMethods: Sized {
120        type Lowlevel: WriteTo;
121        type Rule: pest::RuleType;
122
123        fn parse(string: &str) -> Result<Self::Lowlevel, Box<ParseError<Self::Rule>>>;
124        fn raise(lowlevel: &Self::Lowlevel) -> Result<Self, DeserializeErrorCause>;
125        fn lower(&self) -> Self::Lowlevel;
126
127        fn write_to<W: io::Write>(sink: &mut W, lowlevel: &Self::Lowlevel) -> io::Result<()> {
128            lowlevel.write_to(sink)
129        }
130    }
131
132    /// Define the functions used for command serde.
133    impl SerDeMethods for highlevel::Command {
134        type Lowlevel = lowlevel::Command;
135        type Rule = command_grammar::Rule;
136
137        fn parse(string: &str) -> Result<lowlevel::Command, Box<ParseError<Self::Rule>>> {
138            command_parser::parse(string)
139        }
140
141        fn raise(lowlevel: &Self::Lowlevel) -> Result<Self, DeserializeErrorCause> {
142            translate::raise_command(lowlevel)
143        }
144
145        fn lower(&self) -> Self::Lowlevel {
146            translate::lower_command(self)
147        }
148    }
149
150    /// Define the functions used for response serde.
151    impl SerDeMethods for highlevel::Response {
152        type Lowlevel = lowlevel::Response;
153        type Rule = response_grammar::Rule;
154
155        fn parse(string: &str) -> Result<lowlevel::Response, Box<ParseError<Self::Rule>>> {
156            response_parser::parse(string)
157        }
158
159        fn raise(lowlevel: &Self::Lowlevel) -> Result<Self, DeserializeErrorCause> {
160            translate::raise_response(lowlevel)
161        }
162
163        fn lower(&self) -> Self::Lowlevel {
164            translate::lower_response(self)
165        }
166    }
167
168    /// Trait implemented for the generated high level AT command and response types
169    /// to convert back and forth between individule objects of those types and byte
170    /// streams.  This is used by SerDe to parse streams of commands and responses.
171    pub trait SerDeOne: Sized {
172        fn deserialize_one<R: io::Read>(source: &mut R) -> Result<Self, Box<DeserializeError>>;
173        fn serialize_one<W: io::Write>(&self, sink: &mut W) -> Result<(), SerializeErrorCause>;
174    }
175
176    /// Blanket implementation of SerDeOne which uses SerDeMethods implemenations for commands
177    /// and responses to glue the various serde functions together.
178    impl<T: SerDeMethods> SerDeOne for T {
179        fn deserialize_one<R: io::Read>(source: &mut R) -> Result<Self, Box<DeserializeError>> {
180            //TODO(https://fxbug.dev/42144806) Remove the intermediate String and parse directly from the Read.
181            let mut bytes: Vec<u8> = Vec::new();
182
183            (|| {
184                let _byte_count = source.read_to_end(&mut bytes)?;
185                let string = std::str::from_utf8(&bytes)?;
186                let lowlevel = Self::parse(string)?;
187                Ok(Self::raise(&lowlevel)?)
188            })()
189            .map_err(|cause| Box::new(DeserializeError { cause, bytes }))
190        }
191
192        fn serialize_one<W: io::Write>(&self, sink: &mut W) -> Result<(), SerializeErrorCause> {
193            let lowlevel = Self::lower(self);
194            Self::write_to(sink, &lowlevel)?;
195
196            Ok(())
197        }
198    }
199} // mod internal
200
201/// An abstract representation of bytes remaining after a deserialization failure.
202#[derive(Debug, PartialEq)]
203pub struct DeserializeBytes {
204    // Public for testing; this allows the use of assert_eq on DeserializeBytes.
205    pub(crate) bytes: Vec<u8>,
206}
207
208impl DeserializeBytes {
209    /// Adds bytes to self from an io::Read source.  This should guarantee that *any* bytes read
210    /// from the source are added, even in the case of an IO error.
211    fn add_bytes<R: io::Read>(&mut self, source: &mut R) -> Result<(), Box<DeserializeError>> {
212        let mut more_bytes = Vec::new();
213        let byte_count_result = source.read_to_end(&mut more_bytes);
214        self.bytes.append(&mut more_bytes);
215
216        match byte_count_result {
217            Ok(_byte_count) => Ok(()),
218            Err(err) => Err(Box::new(DeserializeError { cause: err.into(), bytes: more_bytes })),
219        }
220    }
221
222    fn from(bytes: &[u8]) -> Self {
223        DeserializeBytes { bytes: bytes.into() }
224    }
225
226    /// Creates an empty `SerializeBytes`.  This is the only method clients should use--
227    /// the only other way to get an instance is to get one returned from `deserialize`.
228    pub fn new() -> Self {
229        DeserializeBytes { bytes: Vec::new() }
230    }
231}
232
233impl Default for DeserializeBytes {
234    fn default() -> Self {
235        Self::new()
236    }
237}
238
239/// Result from attempt to deserialize multiple items, including the successfully serialized
240/// items, an error if one occurred, and the remaining bytes that were not serialized.
241#[derive(Debug, PartialEq)]
242pub struct DeserializeResult<T> {
243    pub values: Vec<T>,
244    pub error: Option<Box<DeserializeError>>,
245    pub remaining_bytes: DeserializeBytes,
246}
247
248/// A trait for serializing or deserializing multiple items at once and defragmenting partially
249/// serialized items when new bytes become available.
250pub trait SerDe: Sized {
251    fn serialize<W: io::Write>(sink: &mut W, values: &[Self]) -> Result<(), SerializeError<Self>>;
252    fn deserialize<R: io::Read>(
253        source: &mut R,
254        existing_bytes: DeserializeBytes,
255    ) -> DeserializeResult<Self>;
256}
257
258/// Blanket implementation for types that implement SerDe and which break bytestreams on newlines
259/// when deserializing.  This is just used for AT commands and responses.
260// Clone is needed to return copies of items which failed to serialize.
261impl<T: internal::SerDeOne + Clone> SerDe for T {
262    fn serialize<W: io::Write>(sink: &mut W, values: &[Self]) -> Result<(), SerializeError<Self>> {
263        let mut iter = values.iter();
264        for value in &mut iter {
265            match value.serialize_one(sink) {
266                Ok(()) => (),
267                Err(cause) => {
268                    return Err(SerializeError {
269                        remaining: iter.cloned().collect(),
270                        failed: value.clone(),
271                        cause,
272                    })
273                }
274            }
275        }
276        Ok(())
277    }
278
279    fn deserialize<R: io::Read>(
280        source: &mut R,
281        mut existing_bytes: DeserializeBytes,
282    ) -> DeserializeResult<T> {
283        let mut values = Vec::new();
284        if let Err(error) = existing_bytes.add_bytes(source) {
285            return DeserializeResult {
286                values,
287                error: Some(error),
288                remaining_bytes: existing_bytes,
289            };
290        }
291        let mut beginning = 0;
292        let mut end = 0;
293        let bytes = &existing_bytes.bytes;
294        let len = bytes.len();
295        let should_split = |b| b == &b'\n' || b == &b'\r';
296        let is_not_whitespace = |b| !should_split(b);
297        loop {
298            end += 1;
299            if end >= len {
300                break;
301            };
302            if !(should_split(&bytes[end])) {
303                continue;
304            }
305            let mut slice = &bytes[beginning..end];
306            // If it's empty or all whitespace due to mulitple consecutive \n or \rs.
307            if slice.is_empty() || slice.iter().position(is_not_whitespace).is_none() {
308                beginning = end;
309                continue;
310            }
311
312            let value_result = T::deserialize_one(&mut slice);
313            match value_result {
314                Ok(value) => values.push(value),
315                Err(error) => {
316                    // If the received bytes are unparseable, don't put them in the remaining bytes.
317                    // Clients can retrieve these from the error struct itself if need be.
318                    return DeserializeResult {
319                        values,
320                        error: Some(error),
321                        remaining_bytes: DeserializeBytes::from(&bytes[end..]),
322                    };
323                }
324            };
325
326            beginning = end;
327        }
328        DeserializeResult {
329            values,
330            error: None,
331            remaining_bytes: DeserializeBytes::from(&bytes[beginning..]),
332        }
333    }
334}
335
336/// Wrap a Success case in a Response.
337pub fn success(success: highlevel::Success) -> highlevel::Response {
338    highlevel::Response::Success(success)
339}