fn fill_pdt_from_tokens(
    pdt: &mut ParsedDateTime,
    actual: &mut VecDeque<TimeStrToken>,
    expected: &mut VecDeque<TimeStrToken>,
    leading_field: DateTimeField,
    sign: i64,
) -> Result<(), String> {
    use TimeStrToken::*;
    let mut current_field = leading_field;

    let mut i = 0u8;

    let mut unit_buf: Option<DateTimeFieldValue> = None;

    while let (Some(atok), Some(etok)) = (actual.front(), expected.front()) {
        match (atok, etok) {
            // The following forms of punctuation signal the end of a field and can
            // trigger a write.
            (Dash, Dash) | (Colon, Colon) => {
                pdt.write_field_iff_none(current_field, unit_buf)?;
                unit_buf = None;
                current_field = current_field.next_smallest();
            }
            (Delim, Delim) => {
                pdt.write_field_iff_none(current_field, unit_buf)?;
                unit_buf = None;
                current_field = current_field.next_smallest();

                // Spaces require special processing to allow users to enter an
                // arbitrary number of delimiters wherever they're allowed. Note
                // that this does not include colons.
                actual.pop_front();
                expected.pop_front();
                i += 1;

                while let Some(Delim) = actual.front() {
                    actual.pop_front();
                }

                continue;
            }
            (TimeUnit(f), TimeUnit(_)) => {
                if unit_buf.is_some() && *f != current_field {
                    return Err(format!(
                            "Invalid syntax at offset {}: provided TimeUnit({}) but expected TimeUnit({})",
                            i,
                            f,
                            current_field
                        ));
                }
            }
            // If we got a DateTimeUnits, attempt to convert it to a TimeUnit.
            (DateTimeUnit(u), TimeUnit(_)) => {
                let f = match u {
                    DateTimeUnits::Milliseconds => {
                        unit_buf.as_mut().map(|b| b.div(1_000));
                        DateTimeField::Second
                    }
                    DateTimeUnits::Hour => DateTimeField::Hour,
                    DateTimeUnits::Minute => DateTimeField::Minute,
                    DateTimeUnits::Second => DateTimeField::Second,
                    _ => return Err(format!("unsupported unit {}", u)),
                };
                if unit_buf.is_some() && f != current_field {
                    return Err(format!(
                            "Invalid syntax at offset {}: provided DateTimeUnit({}) but expected TimeUnit({})",
                            u,
                            f,
                            current_field
                        ));
                }
            }
            (Dot, Dot) => {}
            (Num(val, _), Num(_, _)) => match unit_buf {
                Some(_) => {
                    return Err(
                        "Invalid syntax; parts must be separated by '-', ':', or ' '".to_string(),
                    )
                }
                None => {
                    unit_buf = Some(DateTimeFieldValue {
                        unit: *val * sign,
                        fraction: 0,
                    });
                }
            },
            (Nanos(val), Nanos(_)) => match unit_buf {
                Some(ref mut u) => {
                    u.fraction = *val * sign;
                }
                None => {
                    unit_buf = Some(DateTimeFieldValue {
                        unit: 0,
                        fraction: *val * sign,
                    });
                }
            },
            (Num(n, _), Nanos(_)) => {
                // Create disposable copy of n.
                let mut nc = *n;

                let mut width = 0;
                // Destructively count the number of digits in n.
                while nc != 0 {
                    nc /= 10;
                    width += 1;
                }

                let mut n = *n;

                // Nanoseconds have 9 digits of precision.
                let precision = 9;

                if width > precision {
                    // Trim n to its 9 most significant digits.
                    n /= 10_i64.pow(width - precision);
                } else {
                    // Right-pad n with 0s.
                    n *= 10_i64.pow(precision - width);
                }

                match unit_buf {
                    Some(ref mut u) => {
                        u.fraction = n * sign;
                    }
                    None => {
                        unit_buf = Some(DateTimeFieldValue {
                            unit: 0,
                            fraction: n * sign,
                        });
                    }
                }
            }
            // Allow skipping expected spaces (Delim), numbers, dots, and nanoseconds.
            (_, Num(_, _)) | (_, Dot) | (_, Nanos(_)) | (_, Delim) => {
                expected.pop_front();
                continue;
            }
            (provided, expected) => {
                return Err(format!(
                    "Invalid syntax at offset {}: provided {:?} but expected {:?}",
                    i, provided, expected
                ))
            }
        }
        i += 1;
        actual.pop_front();
        expected.pop_front();
    }

    ltrim_delim_or_colon(actual);

    pdt.write_field_iff_none(current_field, unit_buf)?;

    Ok(())
}
/// Fills a ParsedDateTime's fields using the `actual` tokens, starting at `leading_field`
/// and descending to less significant DateTimeFields.
///
/// # Errors
/// - If `actual` doesn't match `expected`, modulo skippable TimeStrTokens.
/// - Setting a field in ParsedDateTime that has already been set.
///
/// # Panics
/// - Trying to advance to the next smallest DateTimeField if you're currently
///     at DateTimeField::Second.
Fills a ParsedDateTime's fields using the `actual` tokens, starting at `leading_field`
and descending to less significant DateTimeFields.
Fills a ParsedDateTime ' s fields using the ` actual ` tokens starting at ` leading_field ` and descending to less significant DateTimeFields .
fn fill_pdt_from_tokens(
    pdt: &mut ParsedDateTime,
    actual: &mut VecDeque<TimeStrToken>,
    expected: &mut VecDeque<TimeStrToken>,
    leading_field: DateTimeField,
    sign: i64,
) -> Result<(), String> {
    use TimeStrToken::*;
    let mut current_field = leading_field;
    let mut i = 0u8;
    let mut unit_buf: Option<DateTimeFieldValue> = None;
    while let (Some(atok), Some(etok)) = (actual.front(), expected.front()) {
        match (atok, etok) {
            // The following forms of punctuation signal the end of a field and can
            // trigger a write.
            (Dash, Dash) | (Colon, Colon) => {
                pdt.write_field_iff_none(current_field, unit_buf)?;
                unit_buf = None;
                current_field = current_field.next_smallest();
            }
            (Delim, Delim) => {
                pdt.write_field_iff_none(current_field, unit_buf)?;
                unit_buf = None;
                current_field = current_field.next_smallest();
                // Spaces require special processing to allow users to enter an
                // arbitrary number of delimiters wherever they're allowed. Note
                // that this does not include colons.
                actual.pop_front();
                expected.pop_front();
                i += 1;
                while let Some(Delim) = actual.front() {
                    actual.pop_front();
                }
                continue;
            }
            (TimeUnit(f), TimeUnit(_)) => {
                if unit_buf.is_some() && *f != current_field {
                    return Err(format!(
                            "Invalid syntax at offset {}: provided TimeUnit({}) but expected TimeUnit({})",
                            i,
                            f,
                            current_field
                        ));
                }
            }
            // If we got a DateTimeUnits, attempt to convert it to a TimeUnit.
            (DateTimeUnit(u), TimeUnit(_)) => {
                let f = match u {
                    DateTimeUnits::Milliseconds => {
                        unit_buf.as_mut().map(|b| b.div(1_000));
                        DateTimeField::Second
                    }
                    DateTimeUnits::Hour => DateTimeField::Hour,
                    DateTimeUnits::Minute => DateTimeField::Minute,
                    DateTimeUnits::Second => DateTimeField::Second,
                    _ => return Err(format!("unsupported unit {}", u)),
                };
                if unit_buf.is_some() && f != current_field {
                    return Err(format!(
                            "Invalid syntax at offset {}: provided DateTimeUnit({}) but expected TimeUnit({})",
                            u,
                            f,
                            current_field
                        ));
                }
            }
            (Dot, Dot) => {}
            (Num(val, _), Num(_, _)) => match unit_buf {
                Some(_) => {
                    return Err(
                        "Invalid syntax; parts must be separated by '-', ':', or ' '".to_string(),
                    )
                }
                None => {
                    unit_buf = Some(DateTimeFieldValue {
                        unit: *val * sign,
                        fraction: 0,
                    });
                }
            },
            (Nanos(val), Nanos(_)) => match unit_buf {
                Some(ref mut u) => {
                    u.fraction = *val * sign;
                }
                None => {
                    unit_buf = Some(DateTimeFieldValue {
                        unit: 0,
                        fraction: *val * sign,
                    });
                }
            },
            (Num(n, _), Nanos(_)) => {
                // Create disposable copy of n.
                let mut nc = *n;
                let mut width = 0;
                // Destructively count the number of digits in n.
                while nc != 0 {
                    nc /= 10;
                    width += 1;
                }
                let mut n = *n;
                // Nanoseconds have 9 digits of precision.
                let precision = 9;
                if width > precision {
                    // Trim n to its 9 most significant digits.
                    n /= 10_i64.pow(width - precision);
                } else {
                    // Right-pad n with 0s.
                    n *= 10_i64.pow(precision - width);
                }
                match unit_buf {
                    Some(ref mut u) => {
                        u.fraction = n * sign;
                    }
                    None => {
                        unit_buf = Some(DateTimeFieldValue {
                            unit: 0,
                            fraction: n * sign,
                        });
                    }
                }
            }
            // Allow skipping expected spaces (Delim), numbers, dots, and nanoseconds.
            (_, Num(_, _)) | (_, Dot) | (_, Nanos(_)) | (_, Delim) => {
                expected.pop_front();
                continue;
            }
            (provided, expected) => {
                return Err(format!(
                    "Invalid syntax at offset {}: provided {:?} but expected {:?}",
                    i, provided, expected
                ))
            }
        }
        i += 1;
        actual.pop_front();
        expected.pop_front();
    }
    ltrim_delim_or_colon(actual);
    pdt.write_field_iff_none(current_field, unit_buf)?;
    Ok(())
}
fn fill_pdt_from_tokens ( pdt : & mut ParsedDateTime , actual : & mut VecDeque < TimeStrToken > , expected : & mut VecDeque < TimeStrToken > , leading_field : DateTimeField , sign : i64 , ) -> Result < ( ) , String > { use TimeStrToken :: * ; let mut current_field = leading_field ; let mut i = 0u8 ; let mut unit_buf : Option < DateTimeFieldValue > = None ; while let ( Some ( atok ) , Some ( etok ) ) = ( actual . front ( ) , expected . front ( ) ) { match ( atok , etok ) { // The following forms of punctuation signal the end of a field and can // trigger a write. ( Dash , Dash ) | ( Colon , Colon ) => { pdt . write_field_iff_none ( current_field , unit_buf ) ? ; unit_buf = None ; current_field = current_field . next_smallest ( ) ; } ( Delim , Delim ) => { pdt . write_field_iff_none ( current_field , unit_buf ) ? ; unit_buf = None ; current_field = current_field . next_smallest ( ) ; // Spaces require special processing to allow users to enter an // arbitrary number of delimiters wherever they're allowed. Note // that this does not include colons. actual . pop_front ( ) ; expected . pop_front ( ) ; i += 1 ; while let Some ( Delim ) = actual . front ( ) { actual . pop_front ( ) ; } continue ; } ( TimeUnit ( f ) , TimeUnit ( _ ) ) => { if unit_buf . is_some ( ) && * f != current_field { return Err ( format ! ( " " i f current_field ) ) ; } } // If we got a DateTimeUnits, attempt to convert it to a TimeUnit. ( DateTimeUnit ( u ) , TimeUnit ( _ ) ) => { let f = match u { DateTimeUnits :: Milliseconds => { unit_buf . as_mut ( ) . map ( | b | b . div ( 1_000 ) ) ; DateTimeField :: Second } DateTimeUnits :: Hour => DateTimeField :: Hour , DateTimeUnits :: Minute => DateTimeField :: Minute , DateTimeUnits :: Second => DateTimeField :: Second , _ => return Err ( format ! ( " " u ) ) , } ; if unit_buf . is_some ( ) && f != current_field { return Err ( format ! ( " " u f current_field ) ) ; } } ( Dot , Dot ) => { } ( Num ( val , _ ) , Num ( _ , _ ) ) => match unit_buf { Some ( _ ) => { return Err ( " " . to_string ( ) , ) } None => { unit_buf = Some ( DateTimeFieldValue { unit : * val * sign , fraction : 0 , } ) ; } } , ( Nanos ( val ) , Nanos ( _ ) ) => match unit_buf { Some ( ref mut u ) => { u . fraction = * val * sign ; } None => { unit_buf = Some ( DateTimeFieldValue { unit : 0 , fraction : * val * sign , } ) ; } } , ( Num ( n , _ ) , Nanos ( _ ) ) => { // Create disposable copy of n. let mut nc = * n ; let mut width = 0 ; // Destructively count the number of digits in n. while nc != 0 { nc /= 10 ; width += 1 ; } let mut n = * n ; // Nanoseconds have 9 digits of precision. let precision = 9 ; if width > precision { // Trim n to its 9 most significant digits. n /= 10_i64 . pow ( width - precision ) ; } else { // Right-pad n with 0s. n *= 10_i64 . pow ( precision - width ) ; } match unit_buf { Some ( ref mut u ) => { u . fraction = n * sign ; } None => { unit_buf = Some ( DateTimeFieldValue { unit : 0 , fraction : n * sign , } ) ; } } } // Allow skipping expected spaces (Delim), numbers, dots, and nanoseconds. ( _ , Num ( _ , _ ) ) | ( _ , Dot ) | ( _ , Nanos ( _ ) ) | ( _ , Delim ) => { expected . pop_front ( ) ; continue ; } ( provided , expected ) => { return Err ( format ! ( " " i provided expected ) ) } } i += 1 ; actual . pop_front ( ) ; expected . pop_front ( ) ; } ltrim_delim_or_colon ( actual ) ; pdt . write_field_iff_none ( current_field , unit_buf ) ? ; Ok ( ( ) ) }
Fills a ParsedDateTime's fields using the `actual` tokens, starting at `leading_field`
and descending to less significant DateTimeFields.
Fills a ParsedDateTime ' s fields using the ` actual ` tokens starting at ` leading_field ` and descending to less significant DateTimeFields .
pdt
&mut ParsedDateTime
actual
&mut VecDeque<TimeStrToken>
expected
&mut VecDeque<TimeStrToken>
leading_field
DateTimeField
sign
i64
pdt
&mut ParsedDateTime
actual
&mut VecDeque<TimeStrToken>
expected
&mut VecDeque<TimeStrToken>
leading_field
DateTimeField
sign
i64
errors
If `actual` doesn't match `expected`, modulo skippable TimeStrTokens.
Setting a field in ParsedDateTime that has already been set.
If ` actual ` doesn ' t match ` expected ` modulo skippable TimeStrTokens . Setting a field in ParsedDateTime that has already been set .
panics
Trying to advance to the next smallest DateTimeField if you're currently
at DateTimeField::Second.
Trying to advance to the next smallest DateTimeField if you ' re currently at DateTimeField :: Second .