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
#[cfg(feature = "alloc")]
use alloc::vec::Vec;

/// Converts the given slice to its ASCII upper case equivalent in-place.
///
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', but non-ASCII letters are
/// unchanged.
///
/// This function can be used to implement [`String#upcase!`] for ASCII strings
/// in Ruby.
///
#[cfg_attr(
    feature = "alloc",
    doc = "To return a new uppercased value without modifying the existing one, use [`to_ascii_uppercase`]."
)]
/// This function is analogous to [`<[u8]>::make_ascii_uppercase`][slice-primitive].
///
/// # Examples
///
/// ```
/// # use roe::make_ascii_uppercase;
/// let mut buf = *b"ABCxyz";
/// make_ascii_uppercase(&mut buf);
/// assert_eq!(buf, *b"ABCXYZ");
///
/// let mut buf = *b"1234%&*";
/// make_ascii_uppercase(&mut buf);
/// assert_eq!(buf, *b"1234%&*");
/// ```
///
/// [`String#upcase!`]: https://ruby-doc.org/core-3.1.2/String.html#method-i-upcase-21
/// [slice-primitive]: https://doc.rust-lang.org/std/primitive.u8.html#method.make_ascii_uppercase
#[inline]
#[allow(clippy::module_name_repetitions)]
pub fn make_ascii_uppercase<T: AsMut<[u8]>>(slice: &mut T) {
    let slice = slice.as_mut();
    slice.make_ascii_uppercase();
}

/// Returns a vector containing a copy of the given slice where each byte is
/// mapped to its ASCII upper case equivalent.
///
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', but non-ASCII letters are
/// unchanged.
///
/// This function can be used to implement [`String#upcase`] and
/// [`Symbol#upcase`] for ASCII strings in Ruby.
///
/// To uppercase the value in-place, use [`make_ascii_uppercase`]. This function
/// is analogous to [`<[u8]>::to_ascii_uppercase`][slice-primitive].
///
/// # Examples
///
/// ```
/// # use roe::to_ascii_uppercase;
/// assert_eq!(to_ascii_uppercase("ABCxyz"), &b"ABCXYZ"[..]);
/// assert_eq!(to_ascii_uppercase("1234%&*"), &b"1234%&*"[..]);
/// ```
///
/// [`String#upcase`]: https://ruby-doc.org/core-3.1.2/String.html#method-i-upcase
/// [`Symbol#upcase`]: https://ruby-doc.org/core-3.1.2/Symbol.html#method-i-upcase
/// [slice-primitive]: https://doc.rust-lang.org/std/primitive.slice.html#method.to_ascii_uppercase
#[inline]
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
#[allow(clippy::module_name_repetitions)]
pub fn to_ascii_uppercase<T: AsRef<[u8]>>(slice: T) -> Vec<u8> {
    let slice = slice.as_ref();
    slice.to_ascii_uppercase()
}

#[cfg(test)]
mod tests {
    #[test]
    fn make_ascii_uppercase_empty() {
        let mut buf = *b"";
        super::make_ascii_uppercase(&mut buf);
        assert_eq!(buf, *b"");
    }

    #[test]
    #[cfg(feature = "alloc")]
    fn to_ascii_uppercase_empty() {
        assert_eq!(super::to_ascii_uppercase(""), b"");
    }
}