Skip to content

Commit eb5113b

Browse files
committed
Bypass queue when possible in slice::make_*case
1 parent fffbb33 commit eb5113b

File tree

1 file changed

+49
-29
lines changed

1 file changed

+49
-29
lines changed

library/alloc/src/slice.rs

+49-29
Original file line numberDiff line numberDiff line change
@@ -679,27 +679,22 @@ impl [u8] {
679679
let mut read_offset = 0;
680680
let mut write_offset = 0;
681681

682-
let mut buffer = [0; 4];
683682
while let Some((codepoint, width)) =
684683
unsafe { core::str::next_code_point_with_width(&mut self[read_offset..].iter()) }
685684
{
686685
read_offset += width;
686+
dump_queue(&mut queue, &mut self[..read_offset], &mut write_offset);
687687
let lowercase_char = unsafe { char::from_u32_unchecked(codepoint) };
688688
for c in lowercase_char.to_uppercase() {
689-
let l = c.len_utf8();
690-
c.encode_utf8(&mut buffer);
691-
queue.extend(&buffer[..l]);
692-
}
693-
while write_offset < read_offset {
694-
match queue.pop_front() {
695-
Some(b) => {
696-
self[write_offset] = b;
697-
write_offset += 1;
698-
}
699-
None => break,
700-
}
689+
encode_to_slice_or_else_to_queue(
690+
c,
691+
&mut queue,
692+
&mut self[..read_offset],
693+
&mut write_offset,
694+
);
701695
}
702696
}
697+
dump_queue(&mut queue, &mut self[..read_offset], &mut write_offset);
703698
assert_eq!(read_offset, self.len());
704699
if write_offset < read_offset { Ok(write_offset) } else { Err(queue) }
705700
}
@@ -715,12 +710,12 @@ impl [u8] {
715710
let mut read_offset = 0;
716711
let mut write_offset = 0;
717712

718-
let mut buffer = [0; 4];
719713
let mut final_sigma_automata = FinalSigmaAutomata::new();
720714
while let Some((codepoint, width)) =
721715
unsafe { core::str::next_code_point_with_width(&mut self[read_offset..].iter()) }
722716
{
723717
read_offset += width;
718+
dump_queue(&mut queue, &mut self[..read_offset], &mut write_offset);
724719
let uppercase_char = unsafe { char::from_u32_unchecked(codepoint) };
725720
if uppercase_char == 'Σ' {
726721
// Σ maps to σ, except at the end of a word where it maps to ς.
@@ -729,27 +724,25 @@ impl [u8] {
729724
let is_word_final =
730725
final_sigma_automata.is_accepting() && !case_ignorable_then_cased(rest.chars());
731726
let sigma_lowercase = if is_word_final { 'ς' } else { 'σ' };
732-
let l = sigma_lowercase.len_utf8();
733-
sigma_lowercase.encode_utf8(&mut buffer);
734-
queue.extend(&buffer[..l]);
727+
encode_to_slice_or_else_to_queue(
728+
sigma_lowercase,
729+
&mut queue,
730+
&mut self[..read_offset],
731+
&mut write_offset,
732+
);
735733
} else {
736734
for c in uppercase_char.to_lowercase() {
737-
let l = c.len_utf8();
738-
c.encode_utf8(&mut buffer);
739-
queue.extend(&buffer[..l]);
735+
encode_to_slice_or_else_to_queue(
736+
c,
737+
&mut queue,
738+
&mut self[..read_offset],
739+
&mut write_offset,
740+
);
740741
}
741742
}
742743
final_sigma_automata.step(uppercase_char);
743-
while write_offset < read_offset {
744-
match queue.pop_front() {
745-
Some(b) => {
746-
self[write_offset] = b;
747-
write_offset += 1;
748-
}
749-
None => break,
750-
}
751-
}
752744
}
745+
dump_queue(&mut queue, &mut self[..read_offset], &mut write_offset);
753746
assert_eq!(read_offset, self.len());
754747
return if write_offset < read_offset { Ok(write_offset) } else { Err(queue) };
755748

@@ -764,6 +757,33 @@ impl [u8] {
764757
}
765758
}
766759

760+
fn encode_to_slice_or_else_to_queue(
761+
c: char,
762+
queue: &mut VecDeque<u8>,
763+
slice: &mut [u8],
764+
write_offset: &mut usize,
765+
) {
766+
let mut buffer = [0; 4];
767+
let len = c.encode_utf8(&mut buffer).len();
768+
let writable_slice = &mut slice[*write_offset..];
769+
let direct_copy_length = core::cmp::min(len, writable_slice.len());
770+
writable_slice[..direct_copy_length].copy_from_slice(&buffer[..direct_copy_length]);
771+
*write_offset += direct_copy_length;
772+
queue.extend(&buffer[direct_copy_length..len]);
773+
}
774+
775+
fn dump_queue(queue: &mut VecDeque<u8>, slice: &mut [u8], write_offset: &mut usize) {
776+
while *write_offset < slice.len() {
777+
match queue.pop_front() {
778+
Some(b) => {
779+
slice[*write_offset] = b;
780+
*write_offset += 1;
781+
}
782+
None => break,
783+
}
784+
}
785+
}
786+
767787
#[derive(Clone)]
768788
enum FinalSigmaAutomata {
769789
Init,

0 commit comments

Comments
 (0)