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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use core::iter::FusedIterator;

use crate::internal::{InternalCharIndices, InternalChars};

use super::JavaStr;

/// An iterator over the [`char`]s of a Java CESU-8 string slice.
///
/// This struct is created by the `chars` method on the `JavaStr`. See its
/// documentation for more detail.
///
/// [`chars`]: JavaStr::chars
#[derive(Debug, Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct JavaChars<'a> {
    pub(crate) iter: InternalChars<'a>,
}

impl<'a> JavaChars<'a> {
    /// Views the underlying string as a subslice of the original string.
    #[inline]
    #[must_use]
    pub fn as_str(&self) -> &JavaStr {
        // SAFETY: The bytes come from a JavaStr, so they must be in a valid format.
        unsafe { JavaStr::from_java_cesu8_unchecked(self.iter.as_bytes()) }
    }
}

impl Iterator for JavaChars<'_> {
    type Item = char;

    #[inline]
    #[must_use]
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }

    #[inline]
    fn last(self) -> Option<char> {
        self.iter.last()
    }
}

impl DoubleEndedIterator for JavaChars<'_> {
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back()
    }
}

impl FusedIterator for JavaChars<'_> {}

/// An iterator over the [`char`]s of a Java CESU-8 string slice, and their
/// positions.
///
/// This struct is created by the `char_indices` method on a `JavaStr`. See its
/// documentation for more detail.
#[derive(Debug, Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct JavaCharIndices<'a> {
    pub(crate) iter: InternalCharIndices<'a>,
}

impl<'a> JavaCharIndices<'a> {
    /// Returns the byte position of the next character, or
    /// the length of the underlying string if there are no
    /// more characters.
    #[inline]
    #[must_use]
    pub fn offset(&self) -> usize {
        self.iter.offset()
    }

    /// Views the underlying string as a subslice of the original string.
    #[inline]
    #[must_use]
    pub fn as_str(&self) -> &JavaStr {
        // SAFETY: The bytes come from a JavaStr, so they must be in a valid format.
        unsafe { JavaStr::from_java_cesu8_unchecked(self.iter.as_bytes()) }
    }
}

impl Iterator for JavaCharIndices<'_> {
    type Item = (usize, char);

    #[inline]
    fn next(&mut self) -> Option<(usize, char)> {
        self.iter.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }

    #[inline]
    fn last(self) -> Option<Self::Item> {
        self.iter.last()
    }
}

impl DoubleEndedIterator for JavaCharIndices<'_> {
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back()
    }
}

impl FusedIterator for JavaCharIndices<'_> {}