fn parse_title_demo_date_happy(input: &str) -> IResult<&str, Vec<TOSECToken>>
{
    fn parse_version_and_demo_or_date(input: &str) -> IResult<&str, Vec<TOSECToken>>
    {
        let mut parses = Vec::new();
        let (input, version) = opt(preceded(char(' '), parse_version_string))(input)?;
        if let Some(version) = version {
            parses.push(version);
        }
        let (input, demo) = opt(
            preceded(opt(char(' ')), parse_demo_tag)
        )(input)?;
        if let Some(demo) = demo {
            parses.push(demo);
        }
        let (input, (warning, mut date)) = pair(
            // TOSEC Warn:
            // (demo) may occur without following space
            // 2600 Digital Clock - Demo 1 (demo)(1997-10-03)(Cracknell, Chris 'Crackers')(NTSC)(PD)
            opt(char(' '))
                .map(|c| {
                    match c {
                        Some(_) => None,
                        None => Some(TOSECToken::Warning(TOSECWarn::MissingSpace))
                    }
                }),

                parse_date_tag
        )(input)?;

        // Warnings come before associated token.
        if let Some(warning) = warning {
            parses.push(warning)
        }
        parses.append(&mut date);
        Ok((input, parses))
    }

    // reuse the output vec as our collector
    let (input, (title, mut tokens))
        = take_up_to(parse_version_and_demo_or_date)(input)?;

    tokens.insert(0, TOSECToken::Title(title.trim()));

    Ok((input, tokens))
}
// Parse the happy path where a date is actually required..
// invariant:
// This function returns vec![Title, Date, Warning?]
Parse the happy path where a date is actually required
invariant:
This function returns vec![Title, Date, Warning?]
Parse the happy path where a date is actually required invariant : This function returns vec! [ Title Date Warning? ]
fn parse_title_demo_date_happy(input: &str) -> IResult<&str, Vec<TOSECToken>>
{
    fn parse_version_and_demo_or_date(input: &str) -> IResult<&str, Vec<TOSECToken>>
    {
        let mut parses = Vec::new();
        let (input, version) = opt(preceded(char(' '), parse_version_string))(input)?;
        if let Some(version) = version {
            parses.push(version);
        }
        let (input, demo) = opt(
            preceded(opt(char(' ')), parse_demo_tag)
        )(input)?;
        if let Some(demo) = demo {
            parses.push(demo);
        }
        let (input, (warning, mut date)) = pair(
            // TOSEC Warn:
            // (demo) may occur without following space
            // 2600 Digital Clock - Demo 1 (demo)(1997-10-03)(Cracknell, Chris 'Crackers')(NTSC)(PD)
            opt(char(' '))
                .map(|c| {
                    match c {
                        Some(_) => None,
                        None => Some(TOSECToken::Warning(TOSECWarn::MissingSpace))
                    }
                }),
                parse_date_tag
        )(input)?;
        // Warnings come before associated token.
        if let Some(warning) = warning {
            parses.push(warning)
        }
        parses.append(&mut date);
        Ok((input, parses))
    }
    // reuse the output vec as our collector
    let (input, (title, mut tokens))
        = take_up_to(parse_version_and_demo_or_date)(input)?;
    tokens.insert(0, TOSECToken::Title(title.trim()));
    Ok((input, tokens))
}
fn parse_title_demo_date_happy ( input : & str ) -> IResult < & str , Vec < TOSECToken > > { fn parse_version_and_demo_or_date ( input : & str ) -> IResult < & str , Vec < TOSECToken > > { let mut parses = Vec :: new ( ) ; let ( input , version ) = opt ( preceded ( char ( ' ' ) , parse_version_string ) ) ( input ) ? ; if let Some ( version ) = version { parses . push ( version ) ; } let ( input , demo ) = opt ( preceded ( opt ( char ( ' ' ) ) , parse_demo_tag ) ) ( input ) ? ; if let Some ( demo ) = demo { parses . push ( demo ) ; } let ( input , ( warning , mut date ) ) = pair ( // TOSEC Warn: // (demo) may occur without following space // 2600 Digital Clock - Demo 1 (demo)(1997-10-03)(Cracknell, Chris 'Crackers')(NTSC)(PD) opt ( char ( ' ' ) ) . map ( | c | { match c { Some ( _ ) => None , None => Some ( TOSECToken :: Warning ( TOSECWarn :: MissingSpace ) ) } } ) , parse_date_tag ) ( input ) ? ; // Warnings come before associated token. if let Some ( warning ) = warning { parses . push ( warning ) } parses . append ( & mut date ) ; Ok ( ( input , parses ) ) } // reuse the output vec as our collector let ( input , ( title , mut tokens ) ) = take_up_to ( parse_version_and_demo_or_date ) ( input ) ? ; tokens . insert ( 0 , TOSECToken :: Title ( title . trim ( ) ) ) ; Ok ( ( input , tokens ) ) }
Parse the happy path where a date is actually required..
invariant:
This function returns vec!
Parse the happy path where a date is actually required .. invariant : This function returns vec!
input
&str