use crate::{
ByteOrder,
Charset,
};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum UnicodeBom {
Utf8,
Utf16BigEndian,
Utf16LittleEndian,
Utf32BigEndian,
Utf32LittleEndian,
}
impl UnicodeBom {
#[inline]
pub fn detect(bytes: &[u8]) -> Option<Self> {
if bytes.starts_with(&[0x00, 0x00, 0xfe, 0xff]) {
Some(Self::Utf32BigEndian)
} else if bytes.starts_with(&[0xff, 0xfe, 0x00, 0x00]) {
Some(Self::Utf32LittleEndian)
} else if bytes.starts_with(&[0xef, 0xbb, 0xbf]) {
Some(Self::Utf8)
} else if bytes.starts_with(&[0xfe, 0xff]) {
Some(Self::Utf16BigEndian)
} else if bytes.starts_with(&[0xff, 0xfe]) {
Some(Self::Utf16LittleEndian)
} else {
None
}
}
#[inline]
pub const fn bytes(self) -> &'static [u8] {
match self {
Self::Utf8 => &[0xef, 0xbb, 0xbf],
Self::Utf16BigEndian => &[0xfe, 0xff],
Self::Utf16LittleEndian => &[0xff, 0xfe],
Self::Utf32BigEndian => &[0x00, 0x00, 0xfe, 0xff],
Self::Utf32LittleEndian => &[0xff, 0xfe, 0x00, 0x00],
}
}
#[inline]
pub const fn byte_len(self) -> usize {
match self {
Self::Utf8 => 3,
Self::Utf16BigEndian | Self::Utf16LittleEndian => 2,
Self::Utf32BigEndian | Self::Utf32LittleEndian => 4,
}
}
#[inline]
pub const fn charset(self) -> Charset {
match self {
Self::Utf8 => Charset::UTF_8,
Self::Utf16BigEndian => Charset::UTF_16BE,
Self::Utf16LittleEndian => Charset::UTF_16LE,
Self::Utf32BigEndian => Charset::UTF_32BE,
Self::Utf32LittleEndian => Charset::UTF_32LE,
}
}
#[inline]
pub const fn byte_order(self) -> Option<ByteOrder> {
match self {
Self::Utf8 => None,
Self::Utf16BigEndian | Self::Utf32BigEndian => Some(ByteOrder::BigEndian),
Self::Utf16LittleEndian | Self::Utf32LittleEndian => Some(ByteOrder::LittleEndian),
}
}
}