#![feature(pattern)]
#![no_std]
extern crate alloc;
use alloc::string::String;
use core::str::pattern::{Pattern, Searcher, ReverseSearcher};
use core::mem;
use core::str::from_utf8_unchecked_mut;
use core::iter::FusedIterator;
use core::ptr;
pub trait SplitMutStr<'a, T: Pattern<'a>> {
fn split_mut(&'a mut self, pattern: T) -> SplitMut<'a, T>;
fn splitn_mut(&'a mut self, n: usize, pattern: T) -> SplitNMut<'a, T>;
}
impl<'a, T: Pattern<'a>> SplitMutStr<'a, T> for str {
fn split_mut(&'a mut self, pattern: T) -> SplitMut<'a, T> {
SplitMut { v: self, pattern, finished: false }
}
fn splitn_mut(&'a mut self, n: usize, pattern: T) -> SplitNMut<'a, T> {
SplitNMut { v: self, pattern, count: n }
}
}
impl<'a, T: Pattern<'a>> SplitMutStr<'a, T> for String {
fn split_mut(&'a mut self, pattern: T) -> SplitMut<'a, T> {
SplitMutStr::split_mut(&mut **self, pattern)
}
fn splitn_mut(&'a mut self, n: usize, pattern: T) -> SplitNMut<'a, T> {
SplitMutStr::splitn_mut(&mut **self, n, pattern)
}
}
pub struct SplitMut<'a, T: Pattern<'a>> {
v: &'a mut str,
pattern: T,
finished: bool
}
impl<'a, T: Pattern<'a>> SplitMut<'a, T> {
fn v(&mut self) -> &'a mut str {
mem::replace(&mut self.v, unsafe { from_utf8_unchecked_mut(&mut [][..]) })
}
#[inline]
pub fn finished(&self) -> bool {
self.finished
}
}
impl<'a, T: Pattern<'a>> AsRef<str> for SplitMut<'a, T> {
fn as_ref(&self) -> &str {
&*self.v
}
}
impl<'a, T: Pattern<'a>> AsMut<str> for SplitMut<'a, T> {
fn as_mut(&mut self) -> &mut str {
unsafe { ptr::read(&self.v) }
}
}
impl<'a, T: Pattern<'a>> 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 unsafe { ptr::read(&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>> 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 unsafe { ptr::read(&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> {}
pub struct SplitNMut<'a, T: Pattern<'a>> {
v: &'a mut str,
pattern: T,
count: usize
}
impl<'a, T: Pattern<'a>> AsRef<str> for SplitNMut<'a, T> {
fn as_ref(&self) -> &str {
&*self.v
}
}
impl<'a, T: Pattern<'a>> AsMut<str> for SplitNMut<'a, T> {
fn as_mut(&mut self) -> &mut str {
unsafe { ptr::read(&self.v) }
}
}
impl<'a, T: Pattern<'a>> SplitNMut<'a, T> {
fn v(&mut self) -> &'a mut str {
mem::replace(&mut self.v, unsafe { from_utf8_unchecked_mut(&mut [][..]) })
}
#[inline]
pub fn finished(&self) -> bool {
self.count == 0
}
}
impl<'a, T: Pattern<'a>> Iterator for SplitNMut<'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) };
if self.count == 1 {
self.count = 0;
return Some(tmp1);
}
match unsafe { ptr::read(&self.pattern) }.into_searcher(tmp).next_match() {
None => {
self.count = 0;
Some(tmp1)
},
Some((idx1, idx2)) => {
let len = idx2 - idx1;
let (head, tail) = tmp1.split_at_mut(idx1);
self.v = &mut tail[len..];
self.count = self.count.wrapping_sub(1);
Some(head)
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.finished() {
(0, Some(0))
} else {
(1, Some(self.count))
}
}
}
impl<'a, U: ReverseSearcher<'a>, T: Pattern<'a, Searcher = U>> DoubleEndedIterator for SplitNMut<'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) };
if self.count == 1 {
self.count = 0;
return Some(tmp1);
}
match unsafe { ptr::read(&self.pattern) }.into_searcher(tmp).next_match_back() {
None => {
self.count = 0;
Some(tmp1)
},
Some((idx1, idx2)) => {
let len = idx2 - idx1;
let (head, tail) = tmp1.split_at_mut(idx1);
self.v = head;
self.count = self.count.wrapping_sub(1);
Some(&mut tail[len..])
}
}
}
}
impl<'a, T: Pattern<'a>> FusedIterator for SplitNMut<'a, T> {}
#[cfg(test)]
mod test {
use super::*;
use alloc::{
format,
vec::Vec,
};
#[test]
fn a() {
let mut b = format!("sdasdasd");
assert_eq!(b.as_mut().split_mut("a").collect::<Vec<&mut str>>(), ["sd", "sd", "sd"]);
assert_eq!(format!("sdasdasd").split_mut(&format!("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"]);
assert_eq!(format!("sdasdasd").splitn_mut(2, "a").collect::<Vec<&mut str>>(), ["sd", "sdasd"]);
assert_eq!(format!("sdasdasd").splitn_mut(2, |c: char| c == 'a').collect::<Vec<&mut str>>(), ["sd", "sdasd"]);
assert_eq!(format!("sdasdasd").splitn_mut(2, 'a').collect::<Vec<&mut str>>(), ["sd", "sdasd"]);
assert_eq!(format!("sdasdasd").splitn_mut(2, &['a', 'b'][..]).collect::<Vec<&mut str>>(), ["sd", "sdasd"]);
assert_eq!(format!("sdasdasdads").splitn_mut(2, "a").rev().collect::<Vec<&mut str>>(), ["ds", "sdasdasd"]);
}
}