mod convert;
mod de;
mod ser;
use std::collections::HashMap;
use std::io;
use base64::{Engine, prelude::BASE64_STANDARD};
use bytes::BytesMut;
use serde::{Deserialize, Serialize};
use serde_json::{Value, ser::Formatter};
pub use serde_json::ser::CompactFormatter;
use crate::{HandleParseError, Sbp, messages::invalid::Invalid};
#[cfg(feature = "async")]
pub use de::stream_messages;
pub use de::{iter_json2json_messages, iter_messages, iter_messages_from_fields};
pub use ser::{Json2JsonEncoder, JsonEncoder, to_vec, to_writer};
use crate::SbpMessage;
pub use convert::JsonMap;
use ser::get_common_fields;
#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum JsonInput {
Input(CommonJsonInput),
Nested { data: CommonJsonInput },
}
impl JsonInput {
fn into_inner(self) -> Result<MaybeValidJsonInput, JsonError> {
let CommonJsonInput {
msg_type,
msg_name,
payload,
sender,
} = match self {
JsonInput::Input(data) | JsonInput::Nested { data } => data,
};
match (msg_type, sender) {
(Some(msg_type), Some(sender)) if !msg_name.eq_ignore_ascii_case("INVALID") => {
Ok(MaybeValidJsonInput {
msg_type,
payload,
sender,
})
}
_ => Err(JsonError::InvalidMsg(InvalidMsgInput { payload })),
}
}
}
#[derive(Debug, Deserialize)]
struct CommonJsonInput {
#[serde(default)]
msg_name: String,
#[serde(default)]
msg_type: Option<u16>,
payload: String,
#[serde(default)]
sender: Option<u16>,
}
#[derive(Debug, Deserialize)]
pub struct MaybeValidJsonInput {
msg_type: u16,
payload: String,
sender: u16,
}
#[derive(Debug, Deserialize)]
pub struct InvalidMsgInput {
payload: String,
}
#[derive(Debug, Deserialize)]
pub struct Json2JsonInput {
data: OwnedCommonJson,
#[serde(flatten)]
other: HashMap<String, Value>,
}
#[derive(Debug, Serialize, Deserialize)]
struct OwnedCommonJson {
crc: u16,
length: u8,
msg_type: u16,
payload: String,
preamble: u8,
sender: u16,
}
#[derive(Debug, Serialize)]
struct Json2JsonOutput<'a, M> {
data: JsonOutput<'a, M>,
#[serde(flatten)]
other: HashMap<String, Value>,
}
#[derive(Debug, Serialize, Deserialize)]
struct CommonJson<'a> {
#[serde(default, skip_serializing_if = "Option::is_none")]
crc: Option<u16>,
#[serde(default, skip_serializing_if = "Option::is_none")]
length: Option<u8>,
#[serde(default, skip_serializing_if = "Option::is_none")]
msg_type: Option<u16>,
msg_name: &'a str,
payload: &'a str,
#[serde(default, skip_serializing_if = "Option::is_none")]
preamble: Option<u8>,
#[serde(default, skip_serializing_if = "Option::is_none")]
sender: Option<u16>,
}
#[derive(Debug, Serialize)]
struct JsonOutput<'a, M> {
#[serde(flatten)]
common: Option<CommonJson<'a>>,
#[serde(flatten)]
msg: &'a M,
}
impl<'a, M: SbpMessage + Serialize> JsonOutput<'a, M> {
fn new_from_sbp(
payload_buf: &'a mut String,
frame_buf: &'a mut BytesMut,
msg: &'a M,
) -> Result<Self, JsonError> {
Ok(JsonOutput {
common: get_common_fields(payload_buf, frame_buf, msg)?,
msg,
})
}
}
#[derive(Debug, Clone)]
pub struct HaskellishFloatFormatter;
macro_rules! show_float {
($writer:expr, $value:expr) => {
if $value == 0.0 || $value.abs() >= 0.1 && $value.abs() <= 9_999_999.0 {
write!($writer, "{}", $value)
} else {
write!($writer, "{:e}", $value)
}
};
}
impl Formatter for HaskellishFloatFormatter {
#[inline]
fn write_f32<W>(&mut self, writer: &mut W, value: f32) -> io::Result<()>
where
W: io::Write + ?Sized,
{
show_float!(writer, value)
}
#[inline]
fn write_f64<W>(&mut self, writer: &mut W, value: f64) -> io::Result<()>
where
W: io::Write + ?Sized,
{
show_float!(writer, value)
}
}
#[derive(Debug)]
pub enum JsonError {
SbpMsgParseError(crate::messages::SbpMsgParseError),
CrcError(crate::de::CrcError),
WriteFrameError(crate::ser::WriteFrameError),
IoError(io::Error),
Base64Error(base64::DecodeError),
InvalidMsg(InvalidMsgInput),
SerdeJsonError(serde_json::Error),
}
impl HandleParseError<Sbp> for JsonError {
fn handle_parse_error(self) -> Sbp {
match self {
Self::SbpMsgParseError(e) => Invalid::from(e).into(),
Self::CrcError(e) => Invalid::from(e).into(),
Self::InvalidMsg(InvalidMsgInput { payload }) => {
let mut invalid_frame = Vec::<u8>::new();
BASE64_STANDARD
.decode_vec(&payload, &mut invalid_frame)
.expect("unable to recover from base64 error");
Invalid {
msg_id: None,
sender_id: None,
crc: None,
invalid_frame,
}
.into()
}
Self::WriteFrameError(e) => {
panic!("Unable to recover from WriteFrameError {}", e)
}
Self::IoError(e) => {
panic!("Unable to recover from IoError {}", e)
}
Self::Base64Error(e) => {
panic!("Unable to recover from Base64 decoding error {}", e)
}
Self::SerdeJsonError(e) => {
panic!("Unable to recover from SerdeJsonError {}", e)
}
}
}
}
impl HandleParseError<Json2JsonInput> for JsonError {
fn handle_parse_error(self) -> Json2JsonInput {
unimplemented!("We do not yet support falling back to invalid messages for Json2Json");
}
}
impl std::fmt::Display for JsonError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
JsonError::SbpMsgParseError(e) => e.fmt(f),
JsonError::CrcError(e) => e.fmt(f),
JsonError::WriteFrameError(e) => e.fmt(f),
JsonError::IoError(e) => e.fmt(f),
JsonError::Base64Error(e) => e.fmt(f),
JsonError::SerdeJsonError(e) => e.fmt(f),
JsonError::InvalidMsg(_e) => write!(f, "Received an json value with type INVALID",),
}
}
}
impl std::error::Error for JsonError {}
impl From<crate::messages::SbpMsgParseError> for JsonError {
fn from(e: crate::messages::SbpMsgParseError) -> Self {
JsonError::SbpMsgParseError(e)
}
}
impl From<crate::de::CrcError> for JsonError {
fn from(e: crate::de::CrcError) -> Self {
JsonError::CrcError(e)
}
}
impl From<crate::ser::WriteFrameError> for JsonError {
fn from(e: crate::ser::WriteFrameError) -> Self {
JsonError::WriteFrameError(e)
}
}
impl From<io::Error> for JsonError {
fn from(e: io::Error) -> Self {
JsonError::IoError(e)
}
}
impl From<base64::DecodeError> for JsonError {
fn from(e: base64::DecodeError) -> Self {
JsonError::Base64Error(e)
}
}
impl From<serde_json::Error> for JsonError {
fn from(e: serde_json::Error) -> Self {
JsonError::SerdeJsonError(e)
}
}