use std::string::FromUtf8Error;
use std::sync::Arc;
use std::{fmt::Display, error::Error};
use serde::{ser, de};
use crate::format_specs::{FortField, IntBase, PError, RealFmt};
use crate::fort_error::FError;
use crate::ser::{serialize_characters, serialize_integer, serialize_logical, serialize_real_exp, serialize_real_f};
pub type SResult<T> = Result<T, SError>;
#[derive(Debug)]
pub enum SError {
FormatSpecTooShort,
FormatTypeMismatch{spec_type: FortField, serde_type: &'static str, field_name: Option<String>},
ParsingError(FError),
FormatError(PError),
WriteError(std::io::Error),
InvalidOutputFmt(FortField, String),
KeyToFieldError(Arc<Self>),
FieldMissingError(String),
SerializationFailure(String),
UnicodeError(FromUtf8Error),
}
impl Display for SError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::FormatSpecTooShort => write!(f, "Format specifier ended before all fields of the structure to deserialize into were filled."),
Self::FormatTypeMismatch { spec_type, serde_type, field_name } => {
if let Some(field) = field_name {
write!(f, "The next value in the format specifier for the field '{field}' was {spec_type}, but the structure to deserialize into expected a {serde_type}")
} else {
write!(f, "The next value in the format specifier was {spec_type}, but the structure to deserialize into expected a {serde_type}")
}
},
Self::ParsingError(e) => write!(f, "Error parsing value: {e}"),
Self::FormatError(e) => write!(f, "Error parsing format: {e}"),
Self::WriteError(e) => write!(f, "Error writing data: {e}"),
Self::InvalidOutputFmt(field, msg) => write!(f, "'{field} is not valid for an output format: {msg}"),
Self::KeyToFieldError(e) => write!(f, "Unable to convert one of the map keys to a string to compare with field names, error was: {e}"),
Self::FieldMissingError(field) => write!(f, "Unable to find the field '{field}' in the list of field names"),
Self::SerializationFailure(msg) => write!(f, "Error serializing data: {msg}"),
Self::UnicodeError(e) => write!(f, "Serialized data includes invalid unicode: {e}")
}
}
}
impl Error for SError {}
impl ser::Error for SError {
fn custom<T>(msg:T) -> Self where T:Display {
Self::SerializationFailure(msg.to_string())
}
}
impl From<std::io::Error> for SError {
fn from(value: std::io::Error) -> Self {
Self::WriteError(value)
}
}
impl From<FromUtf8Error> for SError {
fn from(value: FromUtf8Error) -> Self {
Self::UnicodeError(value)
}
}
pub type DResult<T> = Result<T, DError>;
#[derive(Debug)]
pub enum DError {
FormatSpecTooShort,
FormatTypeMismatch{spec_type: FortField, serde_type: &'static str, field_name: Option<String>},
FieldListTooShort,
InputEndedEarly,
ClosingQuoteMissing{quote: char, start_byte: usize},
ParsingError(FError),
FormatError(PError),
DeserializationFailure(String),
TableReadError(std::io::Error, usize),
TableLineEndedEarly{line_num: usize, ncol: usize},
}
impl DError {
pub(crate) fn with_serde_type(self, serde_type: &'static str) -> Self {
match self {
Self::FormatTypeMismatch { spec_type, serde_type: _ , field_name} => Self::FormatTypeMismatch { spec_type, serde_type, field_name },
_ => self
}
}
}
impl Display for DError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::FormatSpecTooShort => write!(f, "Format specifier ended before all fields of the structure to deserialize into were filled."),
Self::FormatTypeMismatch { spec_type, serde_type, field_name } => {
if let Some(field) = field_name {
write!(f, "The next value in the format specifier for the field '{field}' was {spec_type}, but the structure to deserialize into expected a {serde_type}")
} else {
write!(f, "The next value in the format specifier was {spec_type}, but the structure to deserialize into expected a {serde_type}")
}
},
Self::FieldListTooShort => write!(f, "Field list ended before all fields of the structure to deserialize into were filled"),
Self::InputEndedEarly => write!(f, "The input ended before deserialization was complete"),
Self::ClosingQuoteMissing{quote, start_byte} => write!(f, "The input ended before a closing quote matching {quote} at byte {start_byte} was found"),
Self::ParsingError(e) => write!(f, "Error parsing value: {e}"),
Self::FormatError(e) => write!(f, "Error parsing format: {e}"),
Self::DeserializationFailure(msg) => write!(f, "Serde deserialization error: {msg}"),
Self::TableReadError(e, line_num) => write!(f, "Error reading line {line_num} of table data: {e}"),
Self::TableLineEndedEarly{line_num, ncol} => write!(f, "Line {line_num} of table data ended before all {ncol} columns were read")
}
}
}
impl de::Error for DError {
fn custom<T>(msg:T) -> Self where T:Display {
Self::DeserializationFailure(format!("{msg}"))
}
}
impl Error for DError {}
impl From<FError> for DError {
fn from(value: FError) -> Self {
Self::ParsingError(value)
}
}
impl From<PError> for DError {
fn from(value: PError) -> Self {
Self::FormatError(value)
}
}
#[derive(Debug, Clone)]
pub enum NoneFill {
RepChar(u8),
String(Vec<u8>),
PartialTyped{int: i64, real: f64, fill_byte: u8},
Typed{logical: bool, int: i64, real: f64, string: Vec<u8>},
}
impl Default for NoneFill {
fn default() -> Self {
Self::default_inner()
}
}
impl NoneFill {
pub(crate) const fn default_inner() -> Self {
Self::RepChar(b'*')
}
pub fn new_rep_char(c: char) -> Result<Self, std::char::TryFromCharError> {
let byte: u8 = c.try_into()?;
Ok(Self::RepChar(byte))
}
pub fn new_string(s: &str) -> Self {
let bytes = s.as_bytes().to_vec();
Self::String(bytes)
}
pub fn new_partial_typed(int: i64, real: f64) -> Self {
let fill_byte = '*'.try_into().expect("Should be able to convert a * into a single byte");
Self::PartialTyped { int, real, fill_byte }
}
pub fn new_typed(logical: bool, int: i64, real: f64, string: &str) -> Self {
let string = string.as_bytes().to_vec();
Self::Typed { logical, int, real, string }
}
pub(crate) fn make_fill_bytes(&self, fmt: &FortField, left_align_str: bool) -> SResult<Vec<u8>> {
match self {
NoneFill::RepChar(byte) => Ok(Self::_fill_bytes_rep_char(*byte, fmt.width().unwrap_or(0))),
NoneFill::String(bytes) => Self::_file_bytes_string(bytes, Some(fmt.width().unwrap_or(0)), left_align_str),
NoneFill::PartialTyped { int, real, fill_byte } => {
match fmt {
FortField::Char { width } => Ok(Self::_fill_bytes_rep_char(*fill_byte, width.unwrap_or(1))),
FortField::Logical { width } => Ok(Self::_fill_bytes_rep_char(*fill_byte, *width)),
FortField::Integer { width, zeros, base } => Self::_fill_bytes_int(*int, *width, *zeros, *base),
FortField::Real { width, precision, fmt, scale } => {
let precision = precision.expect("Format strings for real values must include a precision when writing");
Self::_fill_bytes_real(*real, *fmt, *width, precision, *scale)
},
FortField::Any => unimplemented!("make_fill_bytes called on an Any format field"),
FortField::Skip => panic!("make_fill_bytes called on a positional format field"),
}
},
NoneFill::Typed { logical, int, real, string } => {
match fmt {
FortField::Char { width } => Self::_file_bytes_string(&string, *width, left_align_str),
FortField::Logical { width } => Self::_fill_bytes_logical(*logical, *width),
FortField::Integer { width, zeros, base } => Self::_fill_bytes_int(*int, *width, *zeros, *base),
FortField::Real { width, precision, fmt, scale } => {
let precision = precision.expect("Format strings for real values must include a precision when writing");
Self::_fill_bytes_real(*real, *fmt, *width, precision, *scale)
},
FortField::Any => unimplemented!("make_fill_bytes called on an Any format field"),
FortField::Skip => panic!("make_fill_bytes called on a positional format field"),
}
},
}
}
fn _fill_bytes_rep_char(byte: u8, width: u32) -> Vec<u8> {
std::iter::repeat(byte).take(width as usize).collect()
}
fn _file_bytes_string(bytes: &[u8], width: Option<u32>, left_aligned: bool) -> SResult<Vec<u8>> {
let mut buf = vec![];
serialize_characters(bytes, width, &mut buf, left_aligned)?;
Ok(buf)
}
fn _fill_bytes_logical(fill_bool: bool, width: u32) -> SResult<Vec<u8>> {
let mut buf = vec![];
serialize_logical(fill_bool, width, &mut buf)?;
Ok(buf)
}
fn _fill_bytes_int(fill_int: i64, width: u32, zeros: Option<u32>, base: IntBase) -> SResult<Vec<u8>> {
let mut buf: Vec<u8> = vec![];
let abs_value = fill_int.abs();
let is_neg = fill_int < 0;
serialize_integer(width, zeros, base, &mut buf, abs_value, is_neg)?;
Ok(buf)
}
fn _fill_bytes_real(fill_real: f64, real_kind: RealFmt, width: u32, precision: u32, scale: i32) -> SResult<Vec<u8>> {
let mut buf: Vec<u8> = vec![];
match real_kind {
RealFmt::D => serialize_real_exp(&mut buf, fill_real, width, precision, scale, "D", None)?,
RealFmt::E => serialize_real_exp(&mut buf, fill_real, width, precision, scale, "E", None)?,
RealFmt::F => serialize_real_f(&mut buf, fill_real, width, precision, scale)?,
RealFmt::G => todo!(),
}
Ok(buf)
}
}