use std::fmt;
use byteorder::{BigEndian, ByteOrder};
use serde::de::{Deserialize, Deserializer, Error as SerdeError, Unexpected, Visitor};
use serde::ser::{Serialize, Serializer};
use crate::errors::{SignalingError, SignalingResult};
use super::csn::CombinedSequenceSnapshot;
use super::Address;
const SEND_ERROR_ID_BYTES: usize = 8;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct SendErrorId {
pub(crate) source: Address,
pub(crate) destination: Address,
pub(crate) csn: CombinedSequenceSnapshot,
}
impl SendErrorId {
pub(crate) fn as_bytes(&self) -> [u8; SEND_ERROR_ID_BYTES] {
let mut bytes = [0u8; 8];
bytes[0] = self.source.0;
bytes[1] = self.destination.0;
BigEndian::write_u16(&mut bytes[2..4], self.csn.overflow_number());
BigEndian::write_u32(&mut bytes[4..8], self.csn.sequence_number());
bytes
}
pub(crate) fn from_slice(bytes: &[u8]) -> SignalingResult<Self> {
if bytes.len() != SEND_ERROR_ID_BYTES {
return Err(SignalingError::Decode(format!(
"byte slice must be exactly {} bytes, not {}",
SEND_ERROR_ID_BYTES,
bytes.len()
)));
};
let source = Address(bytes[0]);
let destination = Address(bytes[1]);
let overflow = BigEndian::read_u16(&bytes[2..4]);
let sequence = BigEndian::read_u32(&bytes[4..8]);
let csn = CombinedSequenceSnapshot::new(overflow, sequence);
Ok(SendErrorId {
source,
destination,
csn,
})
}
}
impl Serialize for SendErrorId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(&self.as_bytes())
}
}
struct SendErrorIdVisitor;
impl<'de> Visitor<'de> for SendErrorIdVisitor {
type Value = SendErrorId;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("8 bytes of binary data")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: SerdeError,
{
if v.len() != 8 {
return Err(SerdeError::invalid_length(v.len(), &self));
}
SendErrorId::from_slice(v)
.map_err(|e| SerdeError::invalid_value(Unexpected::Other(&e.to_string()), &self))
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: SerdeError,
{
self.visit_bytes(&v)
}
}
impl<'de> Deserialize<'de> for SendErrorId {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_bytes(SendErrorIdVisitor)
}
}