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.
45//! 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.
1011pub use crate::parser::common::ParseError;
12use crate::{highlevel, lowlevel};
13use std::io;
14use thiserror::Error;
1516/// 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:?}")]
22IoError(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:?}")]
26ParseError(String),
27#[error("Bad UTF8: {0:?}")]
28Utf8Error(std::str::Utf8Error),
29#[error("Parsed unknown command: {0:?}")]
30UnknownCommand(lowlevel::Command),
31#[error("Parsed unknown response: {0:?}")]
32UnknownResponse(lowlevel::Response),
33#[error("Parsed arguments do not match argument definition: {0:?}")]
34UnknownArguments(lowlevel::Arguments),
35}
3637impl From<io::Error> for DeserializeErrorCause {
38fn from(io_error: io::Error) -> DeserializeErrorCause {
39let string = format!("{:?}", io_error);
40 DeserializeErrorCause::IoError(string)
41 }
42}
4344impl<RT: pest::RuleType> From<Box<ParseError<RT>>> for DeserializeErrorCause {
45fn from(parse_error: Box<ParseError<RT>>) -> DeserializeErrorCause {
46let string = format!("{:?}", parse_error);
47 DeserializeErrorCause::ParseError(string)
48 }
49}
5051impl From<std::str::Utf8Error> for DeserializeErrorCause {
52fn from(utf8_error: std::str::Utf8Error) -> DeserializeErrorCause {
53 DeserializeErrorCause::Utf8Error(utf8_error)
54 }
55}
5657/// Error struct containing the cause of a deserialization error and the bytes that caused the error.
58#[derive(Clone, Debug, PartialEq)]
59pub struct DeserializeError {
60pub cause: DeserializeErrorCause,
61pub bytes: Vec<u8>,
62}
6364#[derive(Debug, Error)]
65pub enum SerializeErrorCause {
66#[error("IO error: {0:?}")]
67IoError(io::Error),
68}
6970impl From<io::Error> for SerializeErrorCause {
71fn from(io_error: io::Error) -> SerializeErrorCause {
72 SerializeErrorCause::IoError(io_error)
73 }
74}
7576// 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 {
81use super::{DeserializeError, DeserializeErrorCause, ParseError, SerializeErrorCause};
82use crate::lowlevel::write_to::WriteTo;
83use crate::parser::{command_grammar, command_parser, response_grammar, response_parser};
84use crate::{highlevel, lowlevel, translate};
85use std::io;
8687/// 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.
90pub trait SerDeMethods: Sized {
91type Lowlevel: WriteTo;
92type Rule: pest::RuleType;
9394fn parse(string: &str) -> Result<Self::Lowlevel, Box<ParseError<Self::Rule>>>;
95fn raise(lowlevel: &Self::Lowlevel) -> Result<Self, DeserializeErrorCause>;
96fn lower(&self) -> Self::Lowlevel;
9798fn write_to<W: io::Write>(sink: &mut W, lowlevel: &Self::Lowlevel) -> io::Result<()> {
99 lowlevel.write_to(sink)
100 }
101 }
102103/// Define the functions used for command serde.
104impl SerDeMethods for highlevel::Command {
105type Lowlevel = lowlevel::Command;
106type Rule = command_grammar::Rule;
107108fn parse(string: &str) -> Result<lowlevel::Command, Box<ParseError<Self::Rule>>> {
109 command_parser::parse(string)
110 }
111112fn raise(lowlevel: &Self::Lowlevel) -> Result<Self, DeserializeErrorCause> {
113 translate::raise_command(lowlevel)
114 }
115116fn lower(&self) -> Self::Lowlevel {
117 translate::lower_command(self)
118 }
119 }
120121/// Define the functions used for response serde.
122impl SerDeMethods for highlevel::Response {
123type Lowlevel = lowlevel::Response;
124type Rule = response_grammar::Rule;
125126fn parse(string: &str) -> Result<lowlevel::Response, Box<ParseError<Self::Rule>>> {
127 response_parser::parse(string)
128 }
129130fn raise(lowlevel: &Self::Lowlevel) -> Result<Self, DeserializeErrorCause> {
131 translate::raise_response(lowlevel)
132 }
133134fn lower(&self) -> Self::Lowlevel {
135 translate::lower_response(self)
136 }
137 }
138139/// 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.
142pub trait SerDeOne: Sized {
143fn deserialize_one<R: io::Read>(source: &mut R) -> Result<Self, Box<DeserializeError>>;
144fn serialize_one<W: io::Write>(&self, sink: &mut W) -> Result<(), SerializeErrorCause>;
145 }
146147/// Blanket implementation of SerDeOne which uses SerDeMethods implemenations for commands
148 /// and responses to glue the various serde functions together.
149impl<T: SerDeMethods> SerDeOne for T {
150fn 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.
152let mut bytes: Vec<u8> = Vec::new();
153154 (|| {
155let _byte_count = source.read_to_end(&mut bytes)?;
156let string = std::str::from_utf8(&bytes)?;
157let lowlevel = Self::parse(string)?;
158Ok(Self::raise(&lowlevel)?)
159 })()
160 .map_err(|cause| Box::new(DeserializeError { cause, bytes }))
161 }
162163fn serialize_one<W: io::Write>(&self, sink: &mut W) -> Result<(), SerializeErrorCause> {
164let lowlevel = Self::lower(self);
165Self::write_to(sink, &lowlevel)?;
166167Ok(())
168 }
169 }
170} // mod internal
171172/// An error and remaining item to serialize if a serialization failure occurs while
173/// serializing multiple items.
174#[derive(Debug)]
175pub struct SerializeError<T> {
176pub remaining: Vec<T>,
177pub failed: T,
178pub cause: SerializeErrorCause,
179}
180181/// An abstract representaiton of bytes remaining after a deserialization failure.
182#[derive(Debug, PartialEq)]
183pub struct DeserializeBytes {
184// Public for testing; this allows the use of assert_eq on DeserializeBytes.
185pub(crate) bytes: Vec<u8>,
186}
187188impl DeserializeBytes {
189/// Adds bytes to self from an io::Read source. This should guarantee that *any* bytes read
190 /// from the source are added, even in the case of an IO error.
191fn add_bytes<R: io::Read>(&mut self, source: &mut R) -> Result<(), Box<DeserializeError>> {
192let mut more_bytes = Vec::new();
193let byte_count_result = source.read_to_end(&mut more_bytes);
194self.bytes.append(&mut more_bytes);
195196match byte_count_result {
197Ok(_byte_count) => Ok(()),
198Err(err) => Err(Box::new(DeserializeError { cause: err.into(), bytes: more_bytes })),
199 }
200 }
201202fn from(bytes: &[u8]) -> Self {
203 DeserializeBytes { bytes: bytes.into() }
204 }
205206/// Creates an empty `SerializeBytes`. This is the only method clients should use--
207 /// the only other way to get an instance is to get one returned from `deserialize`.
208pub fn new() -> Self {
209 DeserializeBytes { bytes: Vec::new() }
210 }
211}
212213impl Default for DeserializeBytes {
214fn default() -> Self {
215Self::new()
216 }
217}
218219/// Result from attempt to deserialize multiple items, including the successfully serialized
220/// items, an error if one occurred, and the remaining bytes that were not serialized.
221#[derive(Debug, PartialEq)]
222pub struct DeserializeResult<T> {
223pub values: Vec<T>,
224pub error: Option<Box<DeserializeError>>,
225pub remaining_bytes: DeserializeBytes,
226}
227228/// A trait for serializing or deserializing multiple items at once and defragmenting partially
229/// serialized items when new bytes become available.
230pub trait SerDe: Sized {
231fn serialize<W: io::Write>(sink: &mut W, values: &[Self]) -> Result<(), SerializeError<Self>>;
232fn deserialize<R: io::Read>(
233 source: &mut R,
234 existing_bytes: DeserializeBytes,
235 ) -> DeserializeResult<Self>;
236}
237238/// Blanket implementation for types that implement SerDe and which break bytestreams on newlines
239/// when deserializing. This is just used for AT commands and responses.
240// Clone is needed to return copies of items which failed to serialize.
241impl<T: internal::SerDeOne + Clone> SerDe for T {
242fn serialize<W: io::Write>(sink: &mut W, values: &[Self]) -> Result<(), SerializeError<Self>> {
243let mut iter = values.iter();
244for value in &mut iter {
245match value.serialize_one(sink) {
246Ok(()) => (),
247Err(cause) => {
248return Err(SerializeError {
249 remaining: iter.cloned().collect(),
250 failed: value.clone(),
251 cause,
252 })
253 }
254 }
255 }
256Ok(())
257 }
258259fn deserialize<R: io::Read>(
260 source: &mut R,
261mut existing_bytes: DeserializeBytes,
262 ) -> DeserializeResult<T> {
263let mut values = Vec::new();
264if let Err(error) = existing_bytes.add_bytes(source) {
265return DeserializeResult {
266 values,
267 error: Some(error),
268 remaining_bytes: existing_bytes,
269 };
270 }
271let mut beginning = 0;
272let mut end = 0;
273let bytes = &existing_bytes.bytes;
274let len = bytes.len();
275let should_split = |b| b == &b'\n' || b == &b'\r';
276let is_not_whitespace = |b| !should_split(b);
277loop {
278 end += 1;
279if end >= len {
280break;
281 };
282if !(should_split(&bytes[end])) {
283continue;
284 }
285let mut slice = &bytes[beginning..end];
286// If it's empty or all whitespace due to mulitple consecutive \n or \rs.
287if slice.is_empty() || slice.iter().position(is_not_whitespace).is_none() {
288 beginning = end;
289continue;
290 }
291292let value_result = T::deserialize_one(&mut slice);
293match value_result {
294Ok(value) => values.push(value),
295Err(error) => {
296// If the received bytes are unparseable, don't put them in the remaining bytes.
297 // Clients can retrieve these from the error struct itself if need be.
298return DeserializeResult {
299 values,
300 error: Some(error),
301 remaining_bytes: DeserializeBytes::from(&bytes[end..]),
302 };
303 }
304 };
305306 beginning = end;
307 }
308 DeserializeResult {
309 values,
310 error: None,
311 remaining_bytes: DeserializeBytes::from(&bytes[beginning..]),
312 }
313 }
314}
315316/// Wrap a Success case in a Response.
317pub fn success(success: highlevel::Success) -> highlevel::Response {
318 highlevel::Response::Success(success)
319}