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