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
115
116
117
118
119
120
121
122
123
124
125
126
#![feature(pattern)]
#![cfg_attr(not(test), no_std)]
extern crate alloc;
use core::str::pattern::{Pattern, Searcher, ReverseSearcher};
use core::mem;
use core::str::from_utf8_unchecked_mut;
use core::slice;
use core::iter::FusedIterator;
use alloc::string::String;
pub trait SplitMutStr<'a, T: Pattern<'a> + Copy, I: Iterator<Item = &'a mut str>> {
fn split_mut(&'a mut self, pattern: T) -> I;
}
impl<'a, T: Pattern<'a> + Copy> SplitMutStr<'a, T, SplitMut<'a, T>> for str {
fn split_mut(&'a mut self, pattern: T) -> SplitMut<'a, T> {
SplitMut { v: self, pattern, finished: false }
}
}
impl<'a, T: Pattern<'a> + Copy> SplitMutStr<'a, T, SplitMut<'a, T>> for String {
fn split_mut(&'a mut self, pattern: T) -> SplitMut<'a, T> {
SplitMut { v: self, pattern, finished: false }
}
}
pub struct SplitMut<'a, T: Pattern<'a> + Copy> {
v: &'a mut str,
pattern: T,
finished: bool
}
impl<'a, T: Pattern<'a> + Copy> SplitMut<'a, T> {
fn v(&mut self) -> &'a mut str {
mem::replace(&mut self.v, unsafe { from_utf8_unchecked_mut(slice::from_raw_parts_mut(1 as *mut u8, 0)) })
}
}
impl<'a, T: Pattern<'a> + Copy> Iterator for SplitMut<'a, T> {
type Item = &'a mut str;
#[inline]
fn next(&mut self) -> Option<&'a mut str> {
if self.finished {
return None;
}
let tmp1 = self.v();
let tmp = unsafe { &*(tmp1 as *mut str) };
match self.pattern.into_searcher(tmp).next_match() {
None => {
self.finished = true;
Some(tmp1)
},
Some((idx1, idx2)) => {
let len = idx2 - idx1;
let (head, tail) = tmp1.split_at_mut(idx1);
self.v = &mut tail[len..];
Some(head)
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.finished {
(0, Some(0))
} else {
(1, Some(self.v.len() + 1))
}
}
}
impl<'a, U: ReverseSearcher<'a>, T: Pattern<'a, Searcher = U> + Copy> DoubleEndedIterator for SplitMut<'a, T>
{
#[inline]
fn next_back(&mut self) -> Option<&'a mut str> {
if self.finished {
return None;
}
let tmp1 = self.v();
let tmp = unsafe { &*(tmp1 as *mut str) };
match self.pattern.into_searcher(tmp).next_match_back() {
None => {
self.finished = true;
Some(tmp1)
},
Some((idx1, idx2)) => {
let len = idx2 - idx1;
let (head, tail) = tmp1.split_at_mut(idx1);
self.v = head;
Some(&mut tail[len..])
}
}
}
}
impl<'a, T: Pattern<'a> + Copy> FusedIterator for SplitMut<'a, T> {}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn a() {
assert_eq!(format!("sdasdasd").split_mut("a").collect::<Vec<&mut str>>(), ["sd", "sd", "sd"]);
assert_eq!(format!("sdasdasd").split_mut(|c: char| c == 'a').collect::<Vec<&mut str>>(), ["sd", "sd", "sd"]);
assert_eq!(format!("sdasdasd").split_mut('a').collect::<Vec<&mut str>>(), ["sd", "sd", "sd"]);
assert_eq!(format!("sdasdasd").split_mut(&['a', 'b'][..]).collect::<Vec<&mut str>>(), ["sd", "sd", "sd"]);
assert_eq!(format!("sdasdasdads").split_mut("a").rev().collect::<Vec<&mut str>>(), ["ds", "sd", "sd", "sd"]);
}
}