#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Codepage {
Iso6937,
Iso8859_1,
Iso8859_2,
Iso8859_3,
Iso8859_4,
Iso8859_5,
Iso8859_6,
Iso8859_7,
Iso8859_8,
Iso8859_9,
Iso8859_10,
Iso8859_11,
Iso8859_13,
Iso8859_14,
Iso8859_15,
Iso8859_16,
Utf8,
Utf16,
Gb2312,
}
pub struct TextcodeRef<'a>(Codepage, &'a [u8]);
impl<'a> TextcodeRef<'a> {
pub fn codepage(&self) -> Codepage {
self.0
}
}
impl<'a> std::fmt::Display for TextcodeRef<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.1.is_empty() {
f.write_str("")
} else if self.1[0] == 0x1E {
textcode::decode::<textcode::Geo>(&self.1[1 ..]).fmt(f)
} else {
textcode::dvb::decode(self.1).fmt(f)
}
}
}
#[derive(Debug)]
pub enum TextcodeError {
InvalidLength,
InvalidCodepage,
}
impl core::error::Error for TextcodeError {}
impl std::fmt::Display for TextcodeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TextcodeError::InvalidLength => write!(f, "Invalid length of input data"),
TextcodeError::InvalidCodepage => write!(f, "Invalid or unsupported codepage"),
}
}
}
impl<'a> TryFrom<&'a [u8]> for TextcodeRef<'a> {
type Error = TextcodeError;
fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
if data.is_empty() {
return Ok(TextcodeRef(Codepage::Utf8, &[]));
}
let codepage = match data[0] {
0x00 => Codepage::Iso6937,
0x20 ..= 0xFF => Codepage::Iso6937,
0x01 => Codepage::Iso8859_5,
0x02 => Codepage::Iso8859_6,
0x03 => Codepage::Iso8859_7,
0x04 => Codepage::Iso8859_8,
0x05 => Codepage::Iso8859_9,
0x06 => Codepage::Iso8859_10,
0x07 => Codepage::Iso8859_11,
0x09 => Codepage::Iso8859_13,
0x0A => Codepage::Iso8859_14,
0x0B => Codepage::Iso8859_15,
0x10 => {
if data.len() < 3 {
return Err(TextcodeError::InvalidLength);
}
let part = u16::from_be_bytes([data[1], data[2]]);
match part {
0x01 => Codepage::Iso8859_1,
0x02 => Codepage::Iso8859_2,
0x03 => Codepage::Iso8859_3,
0x04 => Codepage::Iso8859_4,
0x05 => Codepage::Iso8859_5,
0x06 => Codepage::Iso8859_6,
0x07 => Codepage::Iso8859_7,
0x08 => Codepage::Iso8859_8,
0x09 => Codepage::Iso8859_9,
0x0A => Codepage::Iso8859_10,
0x0B => Codepage::Iso8859_11,
0x0D => Codepage::Iso8859_13,
0x0E => Codepage::Iso8859_14,
0x0F => Codepage::Iso8859_15,
0x10 => Codepage::Iso8859_16,
_ => return Err(TextcodeError::InvalidCodepage),
}
}
0x11 => Codepage::Utf16,
0x13 => Codepage::Gb2312,
0x15 => Codepage::Utf8,
_ => return Err(TextcodeError::InvalidCodepage),
};
Ok(TextcodeRef(codepage, data))
}
}