Reduce allocation more

String::strip_formatting will do most of operations in place.
This commit is contained in:
Eunchong Yu 2018-08-19 11:28:45 +09:00
parent 4feafc681a
commit b108c833bb

View file

@ -39,82 +39,79 @@ impl<'a> FormattedStringExt<'a> for &'a str {
if !self.is_formatted() { if !self.is_formatted() {
return Cow::Borrowed(self); return Cow::Borrowed(self);
} }
Cow::Owned(internal::strip_formatting(self)) let mut s = String::from(self);
strip_formatting(&mut s);
Cow::Owned(s)
} }
} }
mod internal { // to reduce commit diff fn strip_formatting(buf: &mut String) {
use super::*; let mut parser = Parser {
pub(super) fn strip_formatting(input: &str) -> String { state: ParserState::Text,
let mut parser = Parser { };
state: ParserState::Text, let mut prev: char = '\x00';
buf.retain(|cur| {
let result = match parser.state {
ParserState::Text | ParserState::Foreground1 | ParserState::Foreground2 if cur == '\x03' => {
parser.state = ParserState::ColorCode;
false
},
ParserState::Text => !['\x02', '\x1F', '\x16', '\x0F'].contains(&cur),
ParserState::ColorCode if cur.is_digit(10) => {
parser.state = ParserState::Foreground1;
false
},
ParserState::Foreground1 if cur.is_digit(6) => {
// can only consume another digit if previous char was 1.
if prev == '1' {
parser.state = ParserState::Foreground2;
false
} else {
parser.state = ParserState::Text;
true
}
},
ParserState::Foreground1 if cur == ',' => {
parser.state = ParserState::Comma;
false
},
ParserState::Foreground2 if cur == ',' => {
parser.state = ParserState::Comma;
false
},
ParserState::Comma if (cur.is_digit(10)) => {
parser.state = ParserState::Background1;
false
},
ParserState::Background1 if cur.is_digit(6) => {
// can only consume another digit if previous char was 1.
parser.state = ParserState::Text;
if prev == '1' {
false
} else {
true
}
}
_ => {
parser.state = ParserState::Text;
true
}
}; };
let mut prev: char = '\x00'; prev = cur;
input return result
.chars() });
.filter(move |cur| {
let result = match parser.state {
ParserState::Text | ParserState::Foreground1 | ParserState::Foreground2 if *cur == '\x03' => {
parser.state = ParserState::ColorCode;
false
},
ParserState::Text => !['\x02', '\x1F', '\x16', '\x0F'].contains(cur),
ParserState::ColorCode if (*cur).is_digit(10) => {
parser.state = ParserState::Foreground1;
false
},
ParserState::Foreground1 if (*cur).is_digit(6) => {
// can only consume another digit if previous char was 1.
if (prev) == '1' {
parser.state = ParserState::Foreground2;
false
} else {
parser.state = ParserState::Text;
true
}
},
ParserState::Foreground1 if *cur == ',' => {
parser.state = ParserState::Comma;
false
},
ParserState::Foreground2 if *cur == ',' => {
parser.state = ParserState::Comma;
false
},
ParserState::Comma if ((*cur).is_digit(10)) => {
parser.state = ParserState::Background1;
false
},
ParserState::Background1 if (*cur).is_digit(6) => {
// can only consume another digit if previous char was 1.
parser.state = ParserState::Text;
if (prev) == '1' {
false
} else {
true
}
}
_ => {
parser.state = ParserState::Text;
true
}
};
prev = *cur;
return result
})
.collect()
}
} }
impl FormattedStringExt<'static> for String { impl FormattedStringExt<'static> for String {
fn is_formatted(&self) -> bool { fn is_formatted(&self) -> bool {
self.as_str().is_formatted() self.as_str().is_formatted()
} }
fn strip_formatting(self) -> Cow<'static, str> { fn strip_formatting(mut self) -> Cow<'static, str> {
if !self.is_formatted() { if !self.is_formatted() {
return Cow::Owned(self); return Cow::Owned(self);
} }
Cow::Owned(internal::strip_formatting(&self)) strip_formatting(&mut self);
Cow::Owned(self)
} }
} }