let bitmask = ((WEEKDAYS[0] == byte) as u32) << 1
| ((WEEKDAYS[1] == byte) as u32) << 2
| ((WEEKDAYS[2] == byte) as u32) << 3
| ((WEEKDAYS[3] == byte) as u32) << 4
| ((WEEKDAYS[4] == byte) as u32) << 5
| ((WEEKDAYS[5] == byte) as u32) << 6
| ((WEEKDAYS[6] == byte) as u32) << 7
| ((WEEKDAYS[7] == byte) as u32) << 8
| ((WEEKDAYS[8] == byte) as u32) << 9
| ((WEEKDAYS[9] == byte) as u32) << 10
| ((WEEKDAYS[10] == byte) as u32) << 11
| ((WEEKDAYS[11] == byte) as u32) << 12; if bitmask == 0 { return None;
} let index = if cfg!(target_endian = "little") {
bitmask.trailing_zeros() as u8
} else { 31 - bitmask.leading_zeros() as u8
};
// Safety: `index` cannot be greater than 12 because there are only 12 elements in the // array that is converted to a bitmask. We know at least one element matched because // the bitmask is non-zero. let month = unsafe { Month::from_number(NonZero::new(index)?).unwrap_unchecked() };
// For the "short" repr, we've already validated the full text expected. For the "long" // repr, we need to validate the remaining characters. if modifiers.repr == modifier::MonthRepr::Short { return Some(ParsedItem(rest, month));
}
let expected_remaining = match month {
January => b"uary".as_slice(),
February => b"ruary".as_slice(),
March => b"ch".as_slice(),
April => b"il".as_slice(),
May => b"".as_slice(),
June => b"e".as_slice(),
July => b"y".as_slice(),
August => b"ust".as_slice(),
September => b"tember".as_slice(),
October => b"ober".as_slice(),
November | December => b"ember".as_slice(),
};
let bitmask = ((WEEKDAYS[0] == byte) as u32)
| ((WEEKDAYS[1] == byte) as u32) << 1
| ((WEEKDAYS[2] == byte) as u32) << 2
| ((WEEKDAYS[3] == byte) as u32) << 3
| ((WEEKDAYS[4] == byte) as u32) << 4
| ((WEEKDAYS[5] == byte) as u32) << 5
| ((WEEKDAYS[6] == byte) as u32) << 6; if bitmask == 0 { return None;
} let index = if cfg!(target_endian = "little") {
bitmask.trailing_zeros()
} else { 31 - bitmask.leading_zeros()
};
if index > 6 { return None;
} // Safety: Values zero thru six are valid variants, while values greater than six have // already been excluded above. We know at least one element matched because the bitmask // is non-zero. let weekday = unsafe { core::mem::transmute::<u8, Weekday>(index.truncate()) };
// For the "short" repr, we've already validated the full text expected. For the "long" // repr, we need to validate the remaining characters. if modifiers.repr == modifier::WeekdayRepr::Short { return Some(ParsedItem(rest, weekday));
}
if modifiers.repr == modifier::WeekdayRepr::Sunday { // Remap so that Sunday comes after Saturday, not before Monday.
digit = (digit + 6) % 7;
} // Safety: Values zero thru six are valid variants. let weekday = unsafe { core::mem::transmute::<u8, Weekday>(digit) };
Some(ParsedItem(rest, weekday))
}
}
}
/// Parse the "ordinal" component of a `Date`. #[inline] pub(crate) fn parse_ordinal(
input: &[u8],
modifiers: modifier::Ordinal,
) -> Option<ParsedItem<'_, NonZero<u16>>> {
exactly_n_digits_padded::<3, _>(modifiers.padding)(input)
.and_then(|parsed| parsed.flat_map(NonZero::new))
}
/// Parse the "day" component of a `Date`. #[inline] pub(crate) fn parse_day(
input: &[u8],
modifiers: modifier::Day,
) -> Option<ParsedItem<'_, NonZero<u8>>> {
exactly_n_digits_padded::<2, _>(modifiers.padding)(input)
.and_then(|parsed| parsed.flat_map(NonZero::new))
}
/// Parse the "hour" component of a `Time`. #[inline] pub(crate) fn parse_hour(input: &[u8], modifiers: modifier::Hour) -> Option<ParsedItem<'_, u8>> {
exactly_n_digits_padded::<2, _>(modifiers.padding)(input)
}
/// Parse the "minute" component of a `Time`. #[inline] pub(crate) fn parse_minute(
input: &[u8],
modifiers: modifier::Minute,
) -> Option<ParsedItem<'_, u8>> {
exactly_n_digits_padded::<2, _>(modifiers.padding)(input)
}
/// Parse the "second" component of a `Time`. #[inline] pub(crate) fn parse_second(
input: &[u8],
modifiers: modifier::Second,
) -> Option<ParsedItem<'_, u8>> {
exactly_n_digits_padded::<2, _>(modifiers.padding)(input)
}
/// Parse the "period" component of a `Time`. Required if the hour is on a 12-hour clock. #[inline] pub(crate) fn parse_period(
input: &[u8],
modifiers: modifier::Period,
) -> Option<ParsedItem<'_, Period>> { let [first, second, rest @ ..] = input else { return None;
}; letmut first = *first; letmut second = *second;
if modifiers.is_uppercase && modifiers.case_sensitive { match [first, second].as_slice() {
b"AM" => Some(ParsedItem(rest, Period::Am)),
b"PM" => Some(ParsedItem(rest, Period::Pm)),
_ => None,
}
} else {
first = first.to_ascii_lowercase();
second = second.to_ascii_lowercase();
/// Parse the "hour" component of a `UtcOffset`. /// /// Returns the value and whether the value is negative. This is used for when "-0" is parsed. #[inline] pub(crate) fn parse_offset_hour(
input: &[u8],
modifiers: modifier::OffsetHour,
) -> Option<ParsedItem<'_, (i8, bool)>> { let ParsedItem(input, sign) = opt(sign)(input); let ParsedItem(input, hour) = exactly_n_digits_padded::<2, u8>(modifiers.padding)(input)?; match sign {
Some(Sign::Negative) => Some(ParsedItem(input, (-hour.cast_signed(), true))),
None if modifiers.sign_is_mandatory => None,
_ => Some(ParsedItem(input, (hour.cast_signed(), false))),
}
}
/// Parse the "minute" component of a `UtcOffset`. #[inline] pub(crate) fn parse_offset_minute(
input: &[u8],
modifiers: modifier::OffsetMinute,
) -> Option<ParsedItem<'_, i8>> {
Some(
exactly_n_digits_padded::<2, u8>(modifiers.padding)(input)?
.map(|offset_minute| offset_minute.cast_signed()),
)
}
/// Parse the "second" component of a `UtcOffset`. #[inline] pub(crate) fn parse_offset_second(
input: &[u8],
modifiers: modifier::OffsetSecond,
) -> Option<ParsedItem<'_, i8>> {
Some(
exactly_n_digits_padded::<2, u8>(modifiers.padding)(input)?
.map(|offset_second| offset_second.cast_signed()),
)
}
/// Ignore the given number of bytes. #[inline] pub(crate) fn parse_ignore(
input: &[u8],
modifiers: modifier::Ignore,
) -> Option<ParsedItem<'_, ()>> { let modifier::Ignore { count } = modifiers; let input = input.get((count.get().extend())..)?;
Some(ParsedItem(input, ()))
}
/// Parse the Unix timestamp component. pub(crate) fn parse_unix_timestamp(
input: &[u8],
modifiers: modifier::UnixTimestamp,
) -> Option<ParsedItem<'_, i128>> { let ParsedItem(input, sign) = opt(sign)(input); let ParsedItem(input, nano_timestamp) = match modifiers.precision {
modifier::UnixTimestampPrecision::Second => {
n_to_m_digits::<1, 14, u128>(input)?.map(|val| val * Nanosecond::per_t::<u128>(Second))
}
modifier::UnixTimestampPrecision::Millisecond => n_to_m_digits::<1, 17, u128>(input)?
.map(|val| val * Nanosecond::per_t::<u128>(Millisecond)),
modifier::UnixTimestampPrecision::Microsecond => n_to_m_digits::<1, 20, u128>(input)?
.map(|val| val * Nanosecond::per_t::<u128>(Microsecond)),
modifier::UnixTimestampPrecision::Nanosecond => n_to_m_digits::<1, 23, _>(input)?,
};
match sign {
Some(Sign::Negative) => Some(ParsedItem(input, -nano_timestamp.cast_signed())),
None if modifiers.sign_is_mandatory => None,
_ => Some(ParsedItem(input, nano_timestamp.cast_signed())),
}
}
/// Parse the `end` component, which represents the end of input. If any input is remaining _and_ /// trailing input is prohibited, `None` is returned. If trailing input is permitted, it is /// discarded. #[inline] pub(crate) fn parse_end(input: &[u8], end: modifier::End) -> Option<ParsedItem<'_, ()>> { let modifier::End { trailing_input } = end;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.