summaryrefslogtreecommitdiffstats
path: root/vendor/icu_locid/src/parser/mod.rs
blob: fef10b0abc3fdf0b74bcc5277bc5a4c3622fb524 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

pub mod errors;
mod langid;
mod locale;

pub use errors::ParserError;
pub use langid::{
    parse_language_identifier, parse_language_identifier_from_iter,
    parse_language_identifier_with_single_variant,
    parse_locale_with_single_variant_single_keyword_unicode_extension_from_iter, ParserMode,
};

pub use locale::{
    parse_locale, parse_locale_with_single_variant_single_keyword_unicode_keyword_extension,
};

pub const fn get_subtag_iterator(slice: &[u8]) -> SubtagIterator {
    let mut current_start = 0;
    #[allow(clippy::indexing_slicing)]
    while current_start < slice.len()
        && (slice[current_start] == b'-' || slice[current_start] == b'_')
    {
        current_start += 1;
    }
    let mut current_end = current_start;
    #[allow(clippy::indexing_slicing)]
    while current_end < slice.len() && slice[current_end] != b'-' && slice[current_end] != b'_' {
        current_end += 1;
    }
    SubtagIterator {
        slice,
        current_start,
        current_end,
    }
}

#[derive(Copy, Clone, Debug)]
pub struct SubtagIterator<'a> {
    slice: &'a [u8],
    current_start: usize,
    current_end: usize,
}

pub type ManualSlice<'a> = (&'a [u8], usize, usize);

impl<'a> SubtagIterator<'a> {
    pub const fn next_manual(mut self) -> (Self, Option<ManualSlice<'a>>) {
        if self.current_start == self.current_end {
            (self, None)
        } else {
            let r = (self.slice, self.current_start, self.current_end);
            self.current_start = self.current_end;
            #[allow(clippy::indexing_slicing)]
            while self.current_start < self.slice.len()
                && (self.slice[self.current_start] == b'-'
                    || self.slice[self.current_start] == b'_')
            {
                self.current_start += 1;
            }
            self.current_end = self.current_start;
            #[allow(clippy::indexing_slicing)]
            while self.current_end < self.slice.len()
                && self.slice[self.current_end] != b'-'
                && self.slice[self.current_end] != b'_'
            {
                self.current_end += 1;
            }
            (self, Some(r))
        }
    }

    pub const fn peek_manual(&self) -> Option<ManualSlice<'a>> {
        if self.current_start == self.current_end {
            None
        } else {
            Some((self.slice, self.current_start, self.current_end))
        }
    }

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

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

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