use std::io::{Cursor, Read};
use super::{BomsBytesTest, BomType, BomBytesArray, BomBytesPushBuffer, Result};
#[derive(Debug, Clone)]
pub enum BomState {
Initial {
start_bytes: BomBytesPushBuffer,
},
PostInitBuffer {
bytes_after_bom: Cursor<BomBytesPushBuffer>,
bom_type: Option<BomType>,
},
Final(Option<BomType>),
}
impl Default for BomState {
fn default() -> Self {
Self::Initial { start_bytes: Default::default() }
}
}
impl BomState {
pub fn bom_found(&self) -> Option<Option<BomType>> {
match self {
BomState::Initial { .. } => None,
BomState::PostInitBuffer { bom_type, .. } => Some(bom_type.clone()),
BomState::Final(bom_type) => Some(bom_type.clone()),
}
}
pub fn try_read_bom<R: Read>(start_bytes: &BomBytesPushBuffer, reader: &mut R, bom_types: &[BomType]) -> Result<TryReadBomResult> {
let mut new_start_bytes_buffer = BomBytesArray::default();
let start_bytes_slice = start_bytes.bytes();
if !start_bytes_slice.is_empty() {
new_start_bytes_buffer[..start_bytes_slice.len()].copy_from_slice(start_bytes_slice);
}
let read_slice = &mut new_start_bytes_buffer[start_bytes_slice.len()..];
let current_bytes_read = reader.read(read_slice)?;
let total_bom_bytes_read = start_bytes_slice.len() + current_bytes_read;
match BomType::try_find_bytes_bom(&new_start_bytes_buffer[..total_bom_bytes_read], bom_types) {
BomsBytesTest::Complete { bom_type, additional_bytes } => {
let bytes_after_bom = BomBytesPushBuffer::from_slice(additional_bytes);
Ok(TryReadBomResult::Complete { bom_type, bytes_after_bom })
},
BomsBytesTest::Incomplete => {
let bytes_after_bom = BomBytesPushBuffer::from_array(new_start_bytes_buffer, total_bom_bytes_read);
Ok(TryReadBomResult::Incomplete(bytes_after_bom))
}
}
}
}
pub enum TryReadBomResult {
Incomplete(BomBytesPushBuffer),
Complete { bom_type: Option<BomType>, bytes_after_bom: BomBytesPushBuffer },
}