#![feature(ascii_char)]
#![feature(ascii_char_variants)]
#![allow(clippy::unusual_byte_groupings)]
#![allow(clippy::collapsible_match)]
#![allow(clippy::type_complexity)]
pub mod format;
pub mod items;
pub mod messages;
pub mod units;
use std::ascii::Char;
use encoding::{all::ISO_2022_JP, Encoding};
#[derive(Clone, Debug)]
pub struct Message {
pub stream: u8,
pub function: u8,
pub w: bool,
pub text: Option<Item>,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
EmptyText,
InvalidText,
WrongStream,
WrongFunction,
WrongReply,
WrongFormat,
}
#[repr(u8)]
#[derive(Clone, Debug)]
pub enum Item {
List(Vec<Item>) = format::LIST,
Ascii(Vec<Char>) = format::ASCII,
Jis8(String) = format::JIS8,
Local(LocalizedStringHeader, Vec<u8>) = format::LOCAL,
Bin(Vec<u8>) = format::BIN,
Bool(Vec<bool>) = format::BOOL,
I1(Vec<i8>) = format::I1,
I2(Vec<i16>) = format::I2,
I4(Vec<i32>) = format::I4,
I8(Vec<i64>) = format::I8,
U1(Vec<u8>) = format::U1,
U2(Vec<u16>) = format::U2,
U4(Vec<u32>) = format::U4,
U8(Vec<u64>) = format::U8,
F4(Vec<f32>) = format::F4,
F8(Vec<f64>) = format::F8,
}
impl Item {
pub fn bin(value: u8) -> Self {
Self::Bin(vec![value])
}
pub fn bool(value: bool) -> Self {
Self::Bool(vec![value])
}
pub fn i1(value: i8) -> Self {
Self::I1(vec![value])
}
pub fn i2(value: i16) -> Self {
Self::I2(vec![value])
}
pub fn i4(value: i32) -> Self {
Self::I4(vec![value])
}
pub fn i8(value: i64) -> Self {
Self::I8(vec![value])
}
pub fn u1(value: u8) -> Self {
Self::U1(vec![value])
}
pub fn u2(value: u16) -> Self {
Self::U2(vec![value])
}
pub fn u4(value: u32) -> Self {
Self::U4(vec![value])
}
pub fn u8(value: u64) -> Self {
Self::U8(vec![value])
}
pub fn f4(value: f32) -> Self {
Self::F4(vec![value])
}
pub fn f8(value: f64) -> Self {
Self::F8(vec![value])
}
}
impl From<Item> for Vec<u8> {
fn from(item: Item) -> Self {
let mut vec = vec![];
match item {
Item::List(item_vec) => {
let len = item_vec.len();
if len < 256 {
vec.push(format::LIST | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::LIST | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::LIST | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for item in item_vec {
vec.append(&mut item.into());
}
},
Item::Ascii(ascii_vec) => {
let len = ascii_vec.len();
if len < 256 {
vec.push(format::ASCII | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::ASCII | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::ASCII | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for ascii in ascii_vec {
vec.push(ascii as u8);
}
},
Item::Jis8(jis8_string) => {
let encoded = ISO_2022_JP.encode(&jis8_string, encoding::EncoderTrap::Ignore).unwrap();
let len = encoded.len();
if len < 256 {
vec.push(format::JIS8 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::JIS8 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::JIS8 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
vec.extend_from_slice(&encoded);
},
Item::Local(_widechar_format, _widechar_vec) => {
todo!()
},
Item::Bin(bin_vec) => {
let len = bin_vec.len();
if len < 256 {
vec.push(format::BIN | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::BIN | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::BIN | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for bin in bin_vec {
vec.push(bin);
}
},
Item::Bool(bool_vec) => {
let len = bool_vec.len();
if len < 256 {
vec.push(format::BOOL | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::BOOL | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::BOOL | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for bool in bool_vec {
vec.push(bool as u8);
}
},
Item::I1(i1_vec) => {
let len = i1_vec.len();
if len < 256 {
vec.push(format::I1 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::I1 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::I1 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for i1 in i1_vec {
vec.extend_from_slice(&i1.to_be_bytes());
}
},
Item::I2(i2_vec) => {
let len = i2_vec.len() * 2;
if len < 256 {
vec.push(format::I2 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::I2 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::I2 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for i2 in i2_vec {
vec.extend_from_slice(&i2.to_be_bytes());
}
},
Item::I4(i4_vec) => {
let len = i4_vec.len() * 4;
if len < 256 {
vec.push(format::I4 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::I4 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::I4 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for i4 in i4_vec {
vec.extend_from_slice(&i4.to_be_bytes());
}
},
Item::I8(i8_vec) => {
let len = i8_vec.len() * 8;
if len < 256 {
vec.push(format::I8 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::I8 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::I8 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for i8 in i8_vec {
vec.extend_from_slice(&i8.to_be_bytes());
}
},
Item::U1(u1_vec) => {
let len = u1_vec.len();
if len < 256 {
vec.push(format::U1 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::U1 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::U1 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for u1 in u1_vec {
vec.push(u1);
}
},
Item::U2(u2_vec) => {
let len = u2_vec.len() * 2;
if len < 256 {
vec.push(format::U2 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::U2 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::U2 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for u2 in u2_vec {
vec.extend_from_slice(&u2.to_be_bytes());
}
},
Item::U4(u4_vec) => {
let len = u4_vec.len() * 4;
if len < 256 {
vec.push(format::U4 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::U4 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::U4 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for u4 in u4_vec {
vec.extend_from_slice(&u4.to_be_bytes());
}
},
Item::U8(u8_vec) => {
let len = u8_vec.len() * 8;
if len < 256 {
vec.push(format::U8 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::U8 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::U8 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for u8 in u8_vec {
vec.extend_from_slice(&u8.to_be_bytes());
}
},
Item::F4(f4_vec) => {
let len = f4_vec.len() * 4;
if len < 256 {
vec.push(format::F4 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::F4 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::F4 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for f4 in f4_vec {
vec.extend_from_slice(&f4.to_be_bytes());
}
},
Item::F8(f8_vec) => {
let len = f8_vec.len() * 8;
if len < 256 {
vec.push(format::F8 | 1);
vec.push(len as u8);
} else if len < 65536 {
vec.push(format::F8 | 2);
vec.extend_from_slice(&(len as u16).to_be_bytes());
} else {
vec.push(format::F8 | 3);
vec.extend_from_slice(&(len as u32).to_be_bytes()[0..3]);
};
for f8 in f8_vec {
vec.extend_from_slice(&f8.to_be_bytes());
}
},
}
vec
}
}
impl TryFrom<Vec<u8>> for Item {
type Error = Error;
fn try_from(text: Vec<u8>) -> Result<Self, Self::Error> {
fn convert(data: &mut std::slice::Iter<u8>) -> Option<Item> {
let format_byte = *data.next()?;
let item = format_byte & 0b111111_00;
let length_length = format_byte & 0b000000_11;
if length_length == 0 {return None}
let length: u32 = {
let mut bytes = [0u8;4];
for i in (4-length_length)..4 {
bytes[i as usize] = *data.next()?;
}
u32::from_be_bytes(bytes)
};
match item {
format::LIST => {
let mut vec: Vec<Item> = vec![];
for _ in 0..length {vec.push(convert(data)?);}
Some(Item::List(vec))
},
format::ASCII => {
let mut vec: Vec<Char> = vec![];
for _ in 0..length {vec.push(Char::from_u8(*data.next()?)?);}
Some(Item::Ascii(vec))
},
format::JIS8 => {
let mut vec: Vec<u8> = vec![];
for _ in 0..length {vec.push(*data.next()?);}
Some(Item::Jis8(ISO_2022_JP.decode(&vec, encoding::types::DecoderTrap::Strict).ok()?))
},
format::LOCAL => None,
format::BIN => {
let mut vec: Vec<u8> = vec![];
for _ in 0..length {vec.push(*data.next()?);}
Some(Item::Bin(vec))
},
format::BOOL => {
let mut vec: Vec<bool> = vec![];
for _ in 0..length {vec.push(*data.next()? > 0);}
Some(Item::Bool(vec))
},
format::I1 => {
let mut vec: Vec<i8> = vec![];
for _ in 0..length {vec.push(*data.next()? as i8);}
Some(Item::I1(vec))
},
format::I2 => {
if length % 2 != 0 {return None}
let mut vec: Vec<i16> = vec![];
for _ in 0..length/2 {
let mut bytes = [0u8;2];
for byte in &mut bytes {*byte = *data.next()?}
vec.push(i16::from_be_bytes(bytes));
}
Some(Item::I2(vec))
},
format::I4 => {
if length % 4 != 0 {return None}
let mut vec: Vec<i32> = vec![];
for _ in 0..length/4 {
let mut bytes = [0u8;4];
for byte in &mut bytes {*byte = *data.next()?}
vec.push(i32::from_be_bytes(bytes));
}
Some(Item::I4(vec))
},
format::I8 => {
if length % 8 != 0 {return None}
let mut vec: Vec<i64> = vec![];
for _ in 0..length/8 {
let mut bytes = [0u8;8];
for byte in &mut bytes {*byte = *data.next()?}
vec.push(i64::from_be_bytes(bytes));
}
Some(Item::I8(vec))
},
format::U1 => {
let mut vec: Vec<u8> = vec![];
for _ in 0..length {vec.push(*data.next()?);}
Some(Item::U1(vec))
},
format::U2 => {
if length % 2 != 0 {return None}
let mut vec: Vec<u16> = vec![];
for _ in 0..length/2 {
let mut bytes = [0u8;2];
for byte in &mut bytes {*byte = *data.next()?}
vec.push(u16::from_be_bytes(bytes));
}
Some(Item::U2(vec))
},
format::U4 => {
if length % 4 != 0 {return None}
let mut vec: Vec<u32> = vec![];
for _ in 0..length/4 {
let mut bytes = [0u8;4];
for byte in &mut bytes {*byte = *data.next()?}
vec.push(u32::from_be_bytes(bytes));
}
Some(Item::U4(vec))
},
format::U8 => {
if length % 8 != 0 {return None}
let mut vec: Vec<u64> = vec![];
for _ in 0..length/8 {
let mut bytes = [0u8;8];
for byte in &mut bytes {*byte = *data.next()?}
vec.push(u64::from_be_bytes(bytes));
}
Some(Item::U8(vec))
},
format::F4 => {
if length % 4 != 0 {return None}
let mut vec: Vec<f32> = vec![];
for _ in 0..length/4 {
let mut bytes = [0u8;4];
for byte in &mut bytes {*byte = *data.next()?}
vec.push(f32::from_be_bytes(bytes));
}
Some(Item::F4(vec))
},
format::F8 => {
if length % 8 != 0 {return None}
let mut vec: Vec<f64> = vec![];
for _ in 0..length/8 {
let mut bytes = [0u8;8];
for byte in &mut bytes {*byte = *data.next()?}
vec.push(f64::from_be_bytes(bytes));
}
Some(Item::F8(vec))
},
_ => None
}
}
if text.is_empty() {return Err(Error::EmptyText)};
let mut data: std::slice::Iter<u8> = text.iter();
let result = convert(&mut data).ok_or(Error::InvalidText)?;
if data.next().is_some() {return Err(Error::InvalidText)}
Ok(result)
}
}
#[repr(u16)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LocalizedStringHeader {
Ucs2 = 1,
Utf8 = 2,
Iso646_1991 = 3, Iso8859_1 = 4, Iso8859_11 = 5,
Tis620 = 6,
Is13194_1991 = 7, ShiftJis = 8,
EucJp = 9,
EucKr = 10,
Gb = 11,
EucCn = 12,
Big5 = 13,
EucTw = 14,
}