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