use std::error::Error as StdError;
use std::fmt;
use std::io;
mod file;
mod search;
mod within_line;
pub use file::{fingerprint_file, fingerprint_through_line, inspect_file};
pub use search::{ByteSearch, ByteSearchStep, LineSearch, LineSearchStep};
pub use within_line::{fingerprint_line_prefix, inspect_line, utf8_character_position};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct FileInfo {
pub byte_len: u64,
pub line_count: u64,
pub fingerprint: Fingerprint,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct LineInfo {
pub byte_len: u64,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Fingerprint([u8; 32]);
impl Fingerprint {
pub fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
}
#[derive(Debug)]
pub enum Error {
Io(io::Error),
NotRegularFile,
FileTooLarge,
EmptyFilesCannotDiffer,
EmptyLinesCannotDiffer,
InvalidLineNumber,
InvalidBytePosition,
SearchAlreadyComplete,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Io(error) => write!(f, "file I/O failed: {error}"),
Self::NotRegularFile => f.write_str("input is not a regular file"),
Self::FileTooLarge => f.write_str("file size or line count exceeds u64"),
Self::EmptyFilesCannotDiffer => f.write_str("two empty files cannot differ"),
Self::EmptyLinesCannotDiffer => f.write_str("two zero-length lines cannot differ"),
Self::InvalidLineNumber => f.write_str("line numbers must start at 1"),
Self::InvalidBytePosition => {
f.write_str("byte position must be within the line or immediately after it")
}
Self::SearchAlreadyComplete => f.write_str("search is already complete"),
}
}
}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
Self::Io(error) => Some(error),
Self::NotRegularFile
| Self::FileTooLarge
| Self::EmptyFilesCannotDiffer
| Self::EmptyLinesCannotDiffer
| Self::InvalidLineNumber
| Self::InvalidBytePosition
| Self::SearchAlreadyComplete => None,
}
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Self::Io(error)
}
}