Skip to content

Commit

Permalink
iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
robertbastian committed Jul 26, 2024
1 parent ae2be02 commit 886919e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 35 deletions.
45 changes: 22 additions & 23 deletions components/locale_core/src/parser/langid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
let mut variant = None;
let mut keyword = None;

if let (i, Some((start, end))) = iter.next_manual() {
if let (i, Some(subtag)) = iter.next_const() {
iter = i;
match subtags::Language::try_from_utf8_manual_slice(iter.slice, start, end) {
match subtags::Language::try_from_utf8_manual_slice(iter.slice, 0, subtag.len()) {
Ok(l) => language = l,
Err(e) => return Err(e),
}
Expand All @@ -139,22 +139,22 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f

let mut position = ParserPosition::Script;

while let Some((start, end)) = iter.peek_manual() {
if !matches!(mode, ParserMode::LanguageIdentifier) && end - start == 1 {
while let Some(subtag) = iter.peek() {
if !matches!(mode, ParserMode::LanguageIdentifier) && subtag.len() == 1 {
break;
}

if matches!(position, ParserPosition::Script) {
if let Ok(s) = subtags::Script::try_from_utf8_manual_slice(iter.slice, start, end) {
if let Ok(s) = subtags::Script::try_from_utf8_manual_slice(subtag, 0, subtag.len()) {
script = Some(s);
position = ParserPosition::Region;
} else if let Ok(r) =
subtags::Region::try_from_utf8_manual_slice(iter.slice, start, end)
subtags::Region::try_from_utf8_manual_slice(subtag, 0, subtag.len())
{
region = Some(r);
position = ParserPosition::Variant;
} else if let Ok(v) =
subtags::Variant::try_from_utf8_manual_slice(iter.slice, start, end)
subtags::Variant::try_from_utf8_manual_slice(subtag, 0, subtag.len())
{
// We cannot handle multiple variants in a const context
debug_assert!(variant.is_none());
Expand All @@ -166,11 +166,11 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
return Err(ParseError::InvalidSubtag);
}
} else if matches!(position, ParserPosition::Region) {
if let Ok(s) = subtags::Region::try_from_utf8_manual_slice(iter.slice, start, end) {
if let Ok(s) = subtags::Region::try_from_utf8_manual_slice(subtag, 0, subtag.len()) {
region = Some(s);
position = ParserPosition::Variant;
} else if let Ok(v) =
subtags::Variant::try_from_utf8_manual_slice(iter.slice, start, end)
subtags::Variant::try_from_utf8_manual_slice(subtag, 0, subtag.len())
{
// We cannot handle multiple variants in a const context
debug_assert!(variant.is_none());
Expand All @@ -181,7 +181,8 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
} else {
return Err(ParseError::InvalidSubtag);
}
} else if let Ok(v) = subtags::Variant::try_from_utf8_manual_slice(iter.slice, start, end) {
} else if let Ok(v) = subtags::Variant::try_from_utf8_manual_slice(subtag, 0, subtag.len())
{
debug_assert!(matches!(position, ParserPosition::Variant));
if variant.is_some() {
// We cannot handle multiple variants in a const context
Expand All @@ -194,16 +195,16 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
return Err(ParseError::InvalidSubtag);
}

iter = iter.next_manual().0;
iter = iter.next_const().0;
}

if matches!(mode, ParserMode::Locale) {
if let Some((start, end)) = iter.peek_manual() {
match ExtensionType::try_from_utf8_manual_slice(iter.slice, start, end) {
if let Some(subtag) = iter.peek() {
match ExtensionType::try_from_utf8_manual_slice(subtag, 0, subtag.len()) {
Ok(ExtensionType::Unicode) => {
iter = iter.next_manual().0;
if let Some((start, end)) = iter.peek_manual() {
if Attribute::try_from_utf8_manual_slice(iter.slice, start, end).is_ok() {
iter = iter.next_const().0;
if let Some(peek) = iter.peek() {
if Attribute::try_from_utf8_manual_slice(peek, 0, peek.len()).is_ok() {
// We cannot handle Attributes in a const context
return Err(ParseError::InvalidSubtag);
}
Expand All @@ -212,20 +213,18 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
let mut key = None;
let mut current_type = None;

while let Some((start, end)) = iter.peek_manual() {
let slen = end - start;
if slen == 2 {
while let Some(peek) = iter.peek() {
if peek.len() == 2 {
if key.is_some() {
// We cannot handle more than one Key in a const context
return Err(ParseError::InvalidSubtag);
}
match Key::try_from_utf8_manual_slice(iter.slice, start, end) {
match Key::try_from_utf8_manual_slice(peek, 0, peek.len()) {
Ok(k) => key = Some(k),
Err(e) => return Err(e),
};
} else if key.is_some() {
match Value::parse_subtag_from_utf8_manual_slice(iter.slice, start, end)
{
match Value::parse_subtag_from_utf8_manual_slice(peek, 0, peek.len()) {
Ok(Some(t)) => {
if current_type.is_some() {
// We cannot handle more than one type in a const context
Expand All @@ -239,7 +238,7 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
} else {
break;
}
iter = iter.next_manual().0
iter = iter.next_const().0
}
if let Some(k) = key {
keyword = Some((k, current_type));
Expand Down
27 changes: 15 additions & 12 deletions components/locale_core/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl<'a> SubtagIterator<'a> {
}
}

pub const fn next_manual(mut self) -> (Self, Option<(usize, usize)>) {
pub const fn next_const(mut self) -> (Self, Option<&'a [u8]>) {
if self.done {
return (self, None);
}
Expand All @@ -91,30 +91,33 @@ impl<'a> SubtagIterator<'a> {
} else {
self.done = true;
}
(self, Some(result))
(
self,
Some(self.slice.split_at(result.1).0.split_at(result.0).1),
)
}

pub const fn peek_manual(&self) -> Option<(usize, usize)> {
pub const fn peek(&self) -> Option<&'a [u8]> {
if self.done {
return None;
}
Some(self.subtag)
}

pub fn peek(&self) -> Option<&'a [u8]> {
#[allow(clippy::indexing_slicing)] // peek_manual returns valid indices
self.peek_manual().map(|(s, e)| &self.slice[s..e])
Some(
self.slice
.split_at(self.subtag.1)
.0
.split_at(self.subtag.0)
.1,
)
}
}

impl<'a> Iterator for SubtagIterator<'a> {
type Item = &'a [u8];

fn next(&mut self) -> Option<Self::Item> {
let (s, res) = self.next_manual();
let (s, res) = self.next_const();
*self = s;
#[allow(clippy::indexing_slicing)] // next_manual returns valid indices
res.map(|(s, e)| &self.slice[s..e])
res
}
}

Expand Down

0 comments on commit 886919e

Please sign in to comment.