bin_file 0.1.4

Mangling of various file formats that conveys binary information (Motorola S-Record, Intel HEX, TI-TXT and binary files).
Documentation
use std::{error::Error as StdError, fmt, num::ParseIntError, str::Utf8Error};

#[derive(PartialEq, Clone, Debug)]
/// Error of bin_copy
pub enum Error {
    /// The record provided does not begin with a ':'.
    MissingStartCode,
    /// The record provided is shorter than the smallest valid.
    RecordTooShort,
    /// The record provided exceeds the maximum size (255b payload).
    RecordTooLong,
    /// The record is not an even number of bytes.
    RecordNotEvenLength,
    /// The record is not all hexadecimal characters.
    ContainsInvalidCharacters,
    /// The checksum did not match.
    ChecksumMismatch(u8, u8),
    /// The record is not the length it claims.
    PayloadLengthMismatch,
    /// The record type is not supported.
    UnsupportedRecordType {
        /// Provided record string
        record: String,
        /// Provided record type
        record_type: u8,
    },
    /// The payload length does not match the record type.
    InvalidLengthForType,
    /// A record contains data too large to represent.
    DataExceedsMaximumLength(usize),
    /// Object does not end in an EoF record.
    MissingEndOfFileRecord,
    /// Object contains multiple EoF records.
    MultipleEndOfFileRecords(usize),
    /// Unable to synthesize record string.
    SynthesisFailed,
    /// Wrong byte count for export
    WrongByteCount(u32),
    /// Invalid start address
    InvalidStartAddress,
    /// Empty Hex File
    EmptyIntelHexError,
    /// Start, End and size is speziefied for export
    OverSpecifiedStartEnd,
    /// Specified size for export is invalid
    InvalideSize,
    /// Duplicated Start Address Record
    DuplicateStartAddressRecordError,
    /// Address overlap error
    AddressOverlapError(u32),
    /// Writer Error
    WriterError,
    /// No data to read continues bytes
    NotEnoughData(u32),
    /// Size is not a multiple of alignment
    AlignmentToSizeError {
        /// size
        size: usize,
        /// alignment
        alignment: usize,
    },
    /// Datas are not suitable to add
    AddDataError,
    /// File format error
    UnsupportedFileFormat,
    /// Address too big for selected format
    AddressTooBig,
    /// IO Error
    IoError,
    /// Given address range is not valid
    InvalidAddressRange,
    /// Error in UTF8 conversion
    Utf8Error(std::str::Utf8Error),
    /// Regular Expression Error
    RegExError(regex::Error),
}

unsafe impl Sync for Error {}

unsafe impl Send for Error {}

impl StdError for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::MissingStartCode => {
                write!(f, "missing start code ':' on intel hex or 'S' on Srec")
            }
            Error::RecordTooShort => write!(f, "too short"),
            Error::RecordTooLong => write!(f, "too long"),
            Error::RecordNotEvenLength => {
                write!(f, "record does not contain a whole number of bytes")
            }
            Error::ContainsInvalidCharacters => {
                write!(f, "invalid characters encountered in record")
            }
            Error::ChecksumMismatch(found, expecting) => write!(
                f,
                "invalid checksum '{:02X}', expecting '{:02X}'",
                found, expecting,
            ),
            Error::PayloadLengthMismatch => {
                write!(f, "payload length does not match record header")
            }
            Error::UnsupportedRecordType {
                record,
                record_type,
            } => {
                write!(
                    f,
                    "unsupported record type in {}, provided record type is {}",
                    record, record_type
                )
            }
            Error::InvalidLengthForType => {
                write!(f, "payload length invalid for record type")
            }
            Error::DataExceedsMaximumLength(bytes) => {
                write!(f, "record has {} bytes (max 255)", bytes)
            }
            Error::MissingEndOfFileRecord => {
                write!(f, "object is missing end of file record")
            }
            Error::MultipleEndOfFileRecords(eofs) => {
                write!(f, "object contains {} end of file records", eofs)
            }
            Error::SynthesisFailed => {
                write!(f, "unable to write string representation of record")
            }
            Error::WrongByteCount(byte_count) => {
                write!(f, "byte count for hex file export is wrong. Value is {} and should be in between 1..255", byte_count)
            }
            Error::InvalidStartAddress => {
                write!(f, "start address should be exported but is not available")
            }
            Error::EmptyIntelHexError => {
                write!(
                    f,
                    "requested operation cannot be executed with empty object"
                )
            }
            Error::OverSpecifiedStartEnd => {
                write!(f, "start, End and size is speziefied for export")
            }
            Error::InvalideSize => {
                write!(f, "specified size for export is invalid")
            }
            Error::DuplicateStartAddressRecordError => {
                write!(f, "duplicated start address record")
            }
            Error::AddressOverlapError(address) => {
                write!(f, "hex file has data overlap at address: {:0X}", address)
            }
            Error::WriterError => {
                write!(f, "writer error")
            }
            Error::NotEnoughData(address) => {
                write!(
                    f,
                    "Bad access at {:0X}. No data to read continues bytes",
                    address
                )
            }
            Error::AlignmentToSizeError { size, alignment } => {
                write!(
                    f,
                    "Size {} is not a multiple of aligment {}",
                    size, alignment
                )
            }
            Error::AddDataError => {
                write!(
                                    f,
                                    "data added to a segment must be adjacent to or overlapping with the original segment data"
                                )
            }
            Error::UnsupportedFileFormat => {
                write!(f, "Unsupported file format")
            }
            Error::AddressTooBig => {
                write!(f, "Address too big for selected format")
            }
            Error::IoError => {
                write!(f, "General IO Error")
            }
            Error::InvalidAddressRange => {
                write!(f, "Invalid Address Range")
            }
            Error::Utf8Error(utf8_error) => write!(f, "Error converting UTF8: {}", utf8_error),
            Error::RegExError(error) => write!(f, "Regular Expression Error: {}", error),
        }
    }
}

impl From<regex::Error> for Error {
    fn from(value: regex::Error) -> Self {
        Self::RegExError(value)
    }
}

impl From<Utf8Error> for Error {
    fn from(value: Utf8Error) -> Self {
        Self::Utf8Error(value)
    }
}

impl From<ParseIntError> for Error {
    fn from(_value: ParseIntError) -> Self {
        Self::ContainsInvalidCharacters
    }
}