use std::fmt::Debug;
use std::path::Path;
use qubit_io::{ReadSeek, ReadSeekExt};
use qubit_local_files::{FileReadOptions, LocalFiles};
use crate::{MimeDetectorCore, MimeError, MimeResult};
pub trait StreamBasedMimeDetector: Debug + Send + Sync {
fn core(&self) -> &MimeDetectorCore;
fn max_test_bytes(&self) -> usize;
fn guess_from_filename(&self, filename: &str) -> Vec<String>;
fn guess_from_content_bytes(&self, content: &[u8]) -> MimeResult<Vec<String>>;
fn guess_from_reader_stream(
&self,
reader: &mut dyn ReadSeek,
) -> MimeResult<(Vec<String>, Vec<u8>)> {
let content = read_prefix(reader, self.max_test_bytes(), self.core().max_buffer_size())?;
let candidates = self.guess_from_content_bytes(&content)?;
Ok((candidates, content))
}
fn guess_from_file_stream(&self, file: &Path) -> MimeResult<(Vec<String>, Vec<u8>)> {
let mut reader = LocalFiles::open_reader(file, FileReadOptions::buffered())?;
self.guess_from_reader_stream(&mut reader)
}
}
pub(crate) fn read_prefix(
reader: &mut dyn ReadSeek,
max_bytes: usize,
max_buffer_size: usize,
) -> MimeResult<Vec<u8>> {
if max_bytes > max_buffer_size {
return Err(MimeError::BufferLimitExceeded {
requested: max_bytes,
limit: max_buffer_size,
});
}
let mut buffer = vec![0; max_bytes];
let bytes_read = reader.peek_exact_or_eof(&mut buffer)?;
buffer.truncate(bytes_read);
Ok(buffer)
}