Skip to content

Commit 6f1f32e

Browse files
committed
Add needed no_global_oom_handling cfg to make_case methods
1 parent a00b4ef commit 6f1f32e

File tree

3 files changed

+169
-162
lines changed

3 files changed

+169
-162
lines changed

library/alloc/src/slice.rs

Lines changed: 5 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,13 @@ use crate::alloc::Global;
7979
#[cfg(not(no_global_oom_handling))]
8080
use crate::borrow::ToOwned;
8181
use crate::boxed::Box;
82-
use crate::collections::VecDeque;
8382
use crate::vec::Vec;
8483

84+
// Using a module here allows having the no_global_oom_handling
85+
// in only one place
86+
#[cfg(not(no_global_oom_handling))]
87+
mod byte_slice_make_case;
88+
8589
// HACK(japaric): With cfg(test) `impl [T]` is not available, these three
8690
// functions are actually methods that are in `impl [T]` but not in
8791
// `core::slice::SliceExt` - we need to supply these functions for the
@@ -666,167 +670,6 @@ impl<T> [T] {
666670
}
667671
}
668672

669-
#[cfg(not(test))]
670-
impl [u8] {
671-
#[rustc_allow_incoherent_impl]
672-
#[unstable(issue = "none", feature = "std_internals")]
673-
#[allow(dead_code)]
674-
/// Safety:
675-
/// - Must be valid UTF-8
676-
pub unsafe fn make_utf8_uppercase(&mut self) -> Result<usize, VecDeque<u8>> {
677-
let mut queue = VecDeque::new();
678-
679-
let mut read_offset = 0;
680-
let mut write_offset = 0;
681-
682-
while let Some((codepoint, width)) =
683-
unsafe { core::str::next_code_point_with_width(&mut self[read_offset..].iter()) }
684-
{
685-
read_offset += width;
686-
// Queue must be flushed before encode_to_slice_or_else_to_queue is
687-
// called to ensure proper order of bytes
688-
dump_queue(&mut queue, &mut self[..read_offset], &mut write_offset);
689-
let lowercase_char = unsafe { char::from_u32_unchecked(codepoint) };
690-
for c in lowercase_char.to_uppercase() {
691-
encode_to_slice_or_else_to_queue(
692-
c,
693-
&mut queue,
694-
&mut self[..read_offset],
695-
&mut write_offset,
696-
);
697-
}
698-
}
699-
assert_eq!(read_offset, self.len());
700-
if write_offset < read_offset { Ok(write_offset) } else { Err(queue) }
701-
}
702-
703-
#[rustc_allow_incoherent_impl]
704-
#[unstable(issue = "none", feature = "std_internals")]
705-
#[allow(dead_code)]
706-
/// Safety:
707-
/// - Must be valid UTF-8
708-
pub unsafe fn make_utf8_lowercase(&mut self) -> Result<usize, VecDeque<u8>> {
709-
let mut queue = VecDeque::new();
710-
711-
let mut read_offset = 0;
712-
let mut write_offset = 0;
713-
714-
let mut final_sigma_automata = FinalSigmaAutomata::new();
715-
while let Some((codepoint, width)) =
716-
unsafe { core::str::next_code_point_with_width(&mut self[read_offset..].iter()) }
717-
{
718-
read_offset += width;
719-
// Queue must be flushed before encode_to_slice_or_else_to_queue is
720-
// called to ensure proper order of bytes
721-
dump_queue(&mut queue, &mut self[..read_offset], &mut write_offset);
722-
let uppercase_char = unsafe { char::from_u32_unchecked(codepoint) };
723-
if uppercase_char == 'Σ' {
724-
// Σ maps to σ, except at the end of a word where it maps to ς.
725-
// See core::str::to_lowercase
726-
let rest = unsafe { core::str::from_utf8_unchecked(&self[read_offset..]) };
727-
let is_word_final =
728-
final_sigma_automata.is_accepting() && !case_ignorable_then_cased(rest.chars());
729-
let sigma_lowercase = if is_word_final { 'ς' } else { 'σ' };
730-
encode_to_slice_or_else_to_queue(
731-
sigma_lowercase,
732-
&mut queue,
733-
&mut self[..read_offset],
734-
&mut write_offset,
735-
);
736-
} else {
737-
for c in uppercase_char.to_lowercase() {
738-
encode_to_slice_or_else_to_queue(
739-
c,
740-
&mut queue,
741-
&mut self[..read_offset],
742-
&mut write_offset,
743-
);
744-
}
745-
}
746-
final_sigma_automata.step(uppercase_char);
747-
}
748-
assert_eq!(read_offset, self.len());
749-
return if write_offset < read_offset { Ok(write_offset) } else { Err(queue) };
750-
751-
// For now this is copy pasted from core::str, FIXME: DRY
752-
fn case_ignorable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
753-
use core::unicode::{Case_Ignorable, Cased};
754-
match iter.skip_while(|&c| Case_Ignorable(c)).next() {
755-
Some(c) => Cased(c),
756-
None => false,
757-
}
758-
}
759-
}
760-
}
761-
762-
fn encode_to_slice_or_else_to_queue(
763-
c: char,
764-
queue: &mut VecDeque<u8>,
765-
slice: &mut [u8],
766-
write_offset: &mut usize,
767-
) {
768-
let mut buffer = [0; 4];
769-
let len = c.encode_utf8(&mut buffer).len();
770-
let writable_slice = &mut slice[*write_offset..];
771-
let direct_copy_length = core::cmp::min(len, writable_slice.len());
772-
writable_slice[..direct_copy_length].copy_from_slice(&buffer[..direct_copy_length]);
773-
*write_offset += direct_copy_length;
774-
queue.extend(&buffer[direct_copy_length..len]);
775-
}
776-
777-
fn dump_queue(queue: &mut VecDeque<u8>, slice: &mut [u8], write_offset: &mut usize) {
778-
while *write_offset < slice.len() {
779-
match queue.pop_front() {
780-
Some(b) => {
781-
slice[*write_offset] = b;
782-
*write_offset += 1;
783-
}
784-
None => break,
785-
}
786-
}
787-
}
788-
789-
#[derive(Clone)]
790-
enum FinalSigmaAutomata {
791-
Init,
792-
Accepted,
793-
}
794-
795-
impl FinalSigmaAutomata {
796-
fn new() -> Self {
797-
Self::Init
798-
}
799-
800-
fn is_accepting(&self) -> bool {
801-
match self {
802-
FinalSigmaAutomata::Accepted => true,
803-
FinalSigmaAutomata::Init => false,
804-
}
805-
}
806-
807-
fn step(&mut self, c: char) {
808-
use core::unicode::{Case_Ignorable, Cased};
809-
810-
use FinalSigmaAutomata::*;
811-
*self = match self {
812-
Init => {
813-
if Cased(c) {
814-
Accepted
815-
} else {
816-
Init
817-
}
818-
}
819-
Accepted => {
820-
if Cased(c) || Case_Ignorable(c) {
821-
Accepted
822-
} else {
823-
Init
824-
}
825-
}
826-
}
827-
}
828-
}
829-
830673
#[cfg(not(test))]
831674
impl [u8] {
832675
/// Returns a vector containing a copy of this slice where each byte
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
use crate::collections::VecDeque;
2+
3+
#[cfg(not(test))]
4+
impl [u8] {
5+
#[rustc_allow_incoherent_impl]
6+
#[unstable(issue = "none", feature = "std_internals")]
7+
#[allow(dead_code)]
8+
/// Safety:
9+
/// - Must be valid UTF-8
10+
pub unsafe fn make_utf8_uppercase(&mut self) -> Result<usize, VecDeque<u8>> {
11+
let mut queue = VecDeque::new();
12+
13+
let mut read_offset = 0;
14+
let mut write_offset = 0;
15+
16+
while let Some((codepoint, width)) =
17+
unsafe { core::str::next_code_point_with_width(&mut self[read_offset..].iter()) }
18+
{
19+
read_offset += width;
20+
// Queue must be flushed before encode_to_slice_or_else_to_queue is
21+
// called to ensure proper order of bytes
22+
dump_queue(&mut queue, &mut self[..read_offset], &mut write_offset);
23+
let lowercase_char = unsafe { char::from_u32_unchecked(codepoint) };
24+
for c in lowercase_char.to_uppercase() {
25+
encode_to_slice_or_else_to_queue(
26+
c,
27+
&mut queue,
28+
&mut self[..read_offset],
29+
&mut write_offset,
30+
);
31+
}
32+
}
33+
assert_eq!(read_offset, self.len());
34+
if write_offset < read_offset { Ok(write_offset) } else { Err(queue) }
35+
}
36+
37+
#[rustc_allow_incoherent_impl]
38+
#[unstable(issue = "none", feature = "std_internals")]
39+
#[allow(dead_code)]
40+
/// Safety:
41+
/// - Must be valid UTF-8
42+
pub unsafe fn make_utf8_lowercase(&mut self) -> Result<usize, VecDeque<u8>> {
43+
let mut queue = VecDeque::new();
44+
45+
let mut read_offset = 0;
46+
let mut write_offset = 0;
47+
48+
let mut final_sigma_automata = FinalSigmaAutomata::new();
49+
while let Some((codepoint, width)) =
50+
unsafe { core::str::next_code_point_with_width(&mut self[read_offset..].iter()) }
51+
{
52+
read_offset += width;
53+
// Queue must be flushed before encode_to_slice_or_else_to_queue is
54+
// called to ensure proper order of bytes
55+
dump_queue(&mut queue, &mut self[..read_offset], &mut write_offset);
56+
let uppercase_char = unsafe { char::from_u32_unchecked(codepoint) };
57+
if uppercase_char == 'Σ' {
58+
// Σ maps to σ, except at the end of a word where it maps to ς.
59+
// See core::str::to_lowercase
60+
let rest = unsafe { core::str::from_utf8_unchecked(&self[read_offset..]) };
61+
let is_word_final =
62+
final_sigma_automata.is_accepting() && !case_ignorable_then_cased(rest.chars());
63+
let sigma_lowercase = if is_word_final { 'ς' } else { 'σ' };
64+
encode_to_slice_or_else_to_queue(
65+
sigma_lowercase,
66+
&mut queue,
67+
&mut self[..read_offset],
68+
&mut write_offset,
69+
);
70+
} else {
71+
for c in uppercase_char.to_lowercase() {
72+
encode_to_slice_or_else_to_queue(
73+
c,
74+
&mut queue,
75+
&mut self[..read_offset],
76+
&mut write_offset,
77+
);
78+
}
79+
}
80+
final_sigma_automata.step(uppercase_char);
81+
}
82+
assert_eq!(read_offset, self.len());
83+
return if write_offset < read_offset { Ok(write_offset) } else { Err(queue) };
84+
85+
// For now this is copy pasted from core::str, FIXME: DRY
86+
fn case_ignorable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
87+
use core::unicode::{Case_Ignorable, Cased};
88+
match iter.skip_while(|&c| Case_Ignorable(c)).next() {
89+
Some(c) => Cased(c),
90+
None => false,
91+
}
92+
}
93+
}
94+
}
95+
96+
fn encode_to_slice_or_else_to_queue(
97+
c: char,
98+
queue: &mut VecDeque<u8>,
99+
slice: &mut [u8],
100+
write_offset: &mut usize,
101+
) {
102+
let mut buffer = [0; 4];
103+
let len = c.encode_utf8(&mut buffer).len();
104+
let writable_slice = &mut slice[*write_offset..];
105+
let direct_copy_length = core::cmp::min(len, writable_slice.len());
106+
writable_slice[..direct_copy_length].copy_from_slice(&buffer[..direct_copy_length]);
107+
*write_offset += direct_copy_length;
108+
queue.extend(&buffer[direct_copy_length..len]);
109+
}
110+
111+
fn dump_queue(queue: &mut VecDeque<u8>, slice: &mut [u8], write_offset: &mut usize) {
112+
while *write_offset < slice.len() {
113+
match queue.pop_front() {
114+
Some(b) => {
115+
slice[*write_offset] = b;
116+
*write_offset += 1;
117+
}
118+
None => break,
119+
}
120+
}
121+
}
122+
123+
#[derive(Clone)]
124+
enum FinalSigmaAutomata {
125+
Init,
126+
Accepted,
127+
}
128+
129+
impl FinalSigmaAutomata {
130+
fn new() -> Self {
131+
Self::Init
132+
}
133+
134+
fn is_accepting(&self) -> bool {
135+
match self {
136+
FinalSigmaAutomata::Accepted => true,
137+
FinalSigmaAutomata::Init => false,
138+
}
139+
}
140+
141+
fn step(&mut self, c: char) {
142+
use core::unicode::{Case_Ignorable, Cased};
143+
144+
use FinalSigmaAutomata::*;
145+
*self = match self {
146+
Init => {
147+
if Cased(c) {
148+
Accepted
149+
} else {
150+
Init
151+
}
152+
}
153+
Accepted => {
154+
if Cased(c) || Case_Ignorable(c) {
155+
Accepted
156+
} else {
157+
Init
158+
}
159+
}
160+
}
161+
}
162+
}

library/alloc/src/string.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,7 @@ impl String {
11271127
self.vec.extend_from_slice(string.as_bytes())
11281128
}
11291129

1130+
#[cfg(not(no_global_oom_handling))]
11301131
#[unstable(feature = "string_make_uplowercase", issue = "135885")]
11311132
#[allow(missing_docs)]
11321133
pub fn make_uppercase(&mut self) {
@@ -1139,6 +1140,7 @@ impl String {
11391140
*self = unsafe { Self::from_utf8_unchecked(v) }
11401141
}
11411142

1143+
#[cfg(not(no_global_oom_handling))]
11421144
#[unstable(feature = "string_make_uplowercase", issue = "135885")]
11431145
#[allow(missing_docs)]
11441146
pub fn make_lowercase(&mut self) {

0 commit comments

Comments
 (0)