use alloc::string::String;
use core::fmt;
#[cfg(feature = "std")]
use thiserror::Error;
use crate::parser::SectionType;
#[cfg_attr(feature = "std", derive(Error))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseError {
ExpectedSectionHeader { line: usize },
UnclosedSectionHeader { line: usize },
UnknownSection { section: String, line: usize },
InvalidFieldFormat { line: usize },
MissingRequiredField { field: String, section: String },
InvalidFormatLine { line: usize, reason: String },
FieldCountMismatch {
line: usize,
expected: usize,
found: usize,
},
InvalidTimeFormat {
time: String,
line: usize,
reason: String,
},
InvalidColorFormat {
color: String,
line: usize,
reason: String,
},
InvalidNumericValue {
value: String,
line: usize,
reason: String,
},
InvalidStyleOverride { line: usize, reason: String },
InvalidDrawingCommand { line: usize, reason: String },
UuDecodeError { line: usize, reason: String },
Utf8Error { position: usize, reason: String },
UnsupportedVersion { version: String },
CircularStyleReference { chain: String },
MaxNestingDepth { line: usize, limit: usize },
InputTooLarge { size: usize, limit: usize },
IoError { message: String },
OutOfMemory { message: String },
InternalError { line: usize, message: String },
InvalidEventType { line: usize },
InsufficientFields {
expected: usize,
found: usize,
line: usize,
},
MissingFormat,
SectionNotFound,
IndexOutOfBounds,
UnsupportedSection(SectionType),
}
impl ParseError {
fn fmt_structural(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ExpectedSectionHeader { line } => {
write!(
f,
"Expected section header like [Script Info] at line {line}"
)
}
Self::UnclosedSectionHeader { line } => {
write!(f, "Unclosed section header at line {line}: missing ']'")
}
Self::UnknownSection { section, line } => {
write!(f, "Unknown section '{section}' at line {line}")
}
Self::InvalidFieldFormat { line } => {
write!(
f,
"Invalid field format at line {line}: expected 'key: value'"
)
}
Self::MissingRequiredField { field, section } => {
write!(f, "Missing required field '{field}' in {section} section")
}
Self::InvalidFormatLine { line, reason } => {
write!(f, "Invalid format line at line {line}: {reason}")
}
Self::FieldCountMismatch {
line,
expected,
found,
} => {
write!(
f,
"Field count mismatch at line {line}: expected {expected}, found {found}"
)
}
_ => Err(fmt::Error),
}
}
fn fmt_content(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidTimeFormat { time, line, reason } => {
write!(f, "Invalid time format '{time}' at line {line}: {reason}")
}
Self::InvalidColorFormat {
color,
line,
reason,
} => {
write!(f, "Invalid color format '{color}' at line {line}: {reason}")
}
Self::InvalidNumericValue {
value,
line,
reason,
} => {
write!(
f,
"Invalid numeric value '{value}' at line {line}: {reason}"
)
}
Self::InvalidStyleOverride { line, reason } => {
write!(f, "Invalid style override at line {line}: {reason}")
}
Self::InvalidDrawingCommand { line, reason } => {
write!(f, "Invalid drawing command at line {line}: {reason}")
}
Self::UuDecodeError { line, reason } => {
write!(f, "UU-decode error at line {line}: {reason}")
}
_ => Err(fmt::Error),
}
}
fn fmt_system(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Utf8Error { position, reason } => {
write!(f, "UTF-8 encoding error at byte {position}: {reason}")
}
Self::UnsupportedVersion { version } => {
write!(
f,
"Unsupported script version '{version}': expected v4.00+ or compatible"
)
}
Self::CircularStyleReference { chain } => {
write!(f, "Circular style reference detected: {chain}")
}
Self::MaxNestingDepth { line, limit } => {
write!(
f,
"Maximum nesting depth exceeded at line {line}: limit is {limit}"
)
}
Self::InputTooLarge { size, limit } => {
write!(f, "Input size {size} bytes exceeds limit {limit} bytes")
}
Self::IoError { message } => {
write!(f, "I/O error during parsing: {message}")
}
Self::OutOfMemory { message } => {
write!(f, "Memory allocation failed: {message}")
}
Self::InternalError { line, message } => {
write!(f, "Internal parser error at line {line}: {message}")
}
Self::InvalidEventType { line } => {
write!(f, "Invalid event type at line {line}: expected Dialogue, Comment, Picture, Sound, Movie, or Command")
}
Self::InsufficientFields {
expected,
found,
line,
} => {
write!(
f,
"Insufficient fields at line {line}: expected {expected}, found {found}"
)
}
Self::MissingFormat => {
write!(f, "Missing format specification for section")
}
Self::SectionNotFound => {
write!(f, "Section not found")
}
Self::IndexOutOfBounds => {
write!(f, "Index out of bounds")
}
Self::UnsupportedSection(section_type) => {
write!(
f,
"Unsupported section type for operation: {section_type:?}"
)
}
_ => Err(fmt::Error),
}
}
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.fmt_structural(f)
.or_else(|_| self.fmt_content(f))
.or_else(|_| self.fmt_system(f))
}
}