asai 0.1.2

Library for .ass file parsing.
Documentation
use crate::structure::{FromLine, FromLines, InvalidValue};
use std::marker::PhantomData;
use std::ops::Index;
use std::str::FromStr;

pub struct FormattedSection<'a, K: FromStr, L: FromLine<'a>>
where
    Self: Sized,
{
    pd: PhantomData<&'a str>,
    lines: Vec<(K, L)>,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum FormattedSectionParseError<'a> {
    FormatNotFound,
    InvalidLine(&'a str, &'a str),
}

impl<'a, K: FromStr, L: FromLine<'a>> FromLines<'a> for FormattedSection<'a, K, L> {
    type Err = FormattedSectionParseError<'a>;

    fn from_lines(lines: &[(&'a str, &'a str)]) -> Result<Self, Self::Err> {
        let format = lines
            .iter()
            .find(|x| x.0 == "Format")
            .ok_or(FormattedSectionParseError::FormatNotFound)?
            .1;
        let mut lines_ = Vec::with_capacity(lines.len());
        for &line in lines {
            if line.0 == "Format" {
                continue;
            }
            lines_.push((
                line.0
                    .parse::<K>()
                    .map_err(|_| FormattedSectionParseError::InvalidLine(line.0, line.1))?,
                L::from_line(line.1, format)
                    .map_err(|_| FormattedSectionParseError::InvalidLine(line.0, line.1))?,
            ));
        }
        Ok(Self {
            pd: PhantomData::default(),
            lines: lines_,
        })
    }
}

impl<'a, K: FromStr, L: FromLine<'a>> FormattedSection<'a, K, L> {
    pub fn len(&self) -> usize {
        self.lines.len()
    }
}

impl<'a, K: FromStr, L: FromLine<'a>> Index<usize> for FormattedSection<'a, K, L> {
    type Output = (K, L);

    fn index(&self, index: usize) -> &Self::Output {
        &self.lines[index]
    }
}