use jt_util::codec_trait::{CodecEof, CodecError};
use tokio_util::codec::Decoder;
use bytes::{Buf, Bytes, BytesMut};
use std::{fmt, io, ops::Index, usize};
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Jt1078Codec {
sim_len: usize,
find_head: bool,
now_package_size: Option<usize>,
pub eof: bool,
}
const HEAD1078: [u8; 4] = [0x30, 0x31, 0x63, 0x64];
impl Jt1078Codec {
pub fn new() -> Self {
Jt1078Codec {
sim_len: 0,
find_head: false,
now_package_size: None,
eof: false,
}
}
fn decode_xxxx(buf: &mut BytesMut, ver: usize) -> Result<Option<Bytes>, Jt1078CodecError> {
let xxxx_index = match ver {
0 => 15, _ => 19,
};
let xxxx = buf.index(xxxx_index) & 0xF0 >> 4;
let dlen_index = match xxxx {
0 => xxxx_index + 13, 1 => xxxx_index + 13,
2 => xxxx_index + 13,
3 => xxxx_index + 9, _ => xxxx_index + 1, };
let dlen = match buf.chunk().get(dlen_index..dlen_index + 2) {
Some(src) => unsafe {
u16::from_be_bytes(*(src as *const _ as *const [_; 2])) as usize
},
None => {
return Ok(None);
}
};
let next_start = dlen_index + 2 + dlen;
if buf.len() < next_start + 4 {
return Ok(None);
}
if buf[next_start..next_start + 4].eq(&HEAD1078) {
return Ok(Some(buf.split_to(next_start).freeze()));
} else {
return Err(Jt1078CodecError::No1078);
}
}
}
impl Default for Jt1078Codec {
fn default() -> Self {
Self::new()
}
}
impl CodecEof for Jt1078Codec {
fn is_eof(&self) -> bool {
self.eof
}
}
impl Decoder for Jt1078Codec {
type Item = Bytes;
type Error = Jt1078CodecError;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Jt1078CodecError> {
if buf.len() < self.sim_len + 12 {
return Ok(None);
}
if !buf[..4].eq(&HEAD1078) {
return Err(Jt1078CodecError::No1078);
}
if self.sim_len == 0 {
let r13 = Self::decode_xxxx(buf, 0);
if let Ok(Some(ret)) = r13 {
self.sim_len = 6;
return Ok(Some(ret));
}
let r19 = Self::decode_xxxx(buf, 0);
if let Ok(Some(ret)) = r19 {
self.sim_len = 10;
return Ok(Some(ret));
}
if r13.is_err() && r19.is_err() {
return Err(Jt1078CodecError::No1078);
}
} else if self.sim_len == 6 {
return Self::decode_xxxx(buf, 0);
} else if self.sim_len == 10 {
return Self::decode_xxxx(buf, 1);
}
Ok(None)
}
fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Jt1078CodecError> {
self.eof = true;
Ok(match self.decode(buf)? {
Some(frame) => Some(frame),
None => {
if buf.is_empty() {
None
} else {
None
}
}
})
}
}
#[derive(Debug)]
pub enum Jt1078CodecError {
Io(io::Error),
No1078,
}
impl fmt::Display for Jt1078CodecError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Jt1078CodecError::Io(e) => write!(f, "{}", e),
&Jt1078CodecError::No1078 => write!(f, "no 1078"),
}
}
}
impl From<io::Error> for Jt1078CodecError {
fn from(e: io::Error) -> Jt1078CodecError {
Jt1078CodecError::Io(e)
}
}
impl CodecError for Jt1078CodecError {
fn is_io_err(&self) -> bool {
if let Self::Io(_) = self {
return true;
}
return false;
}
}