blob: db5ce2de484365a802a374a13e556fa6935b9bde [file] [log] [blame]
macro_rules! decode_impl {
($l:expr; $(#[$attr: meta])* $parse_macro:ident; $(#[$decode_attr: meta])* $decode_name: ident; $(#[$decode_to_string_attr: meta])* $decode_to_string_name: ident; $(#[$decode_to_vec_attr: meta])* $decode_to_vec_name: ident; $(#[$decode_to_writer_attr: meta])* $decode_to_writer_name: ident $(;)*) => {
$(#[$decode_attr])*
///
$(#[$attr])*
#[inline]
pub fn $decode_name<S: ?Sized + AsRef<str>>(text: &S) -> Cow<str> {
let text = text.as_ref();
let text_bytes = text.as_bytes();
let text_length = text_bytes.len();
let mut p = 0;
let mut e;
let mut step = 0;
let (mut v, mut start) = loop {
if p == text_length {
return Cow::from(text);
}
e = text_bytes[p];
$parse_macro!(e, step,
{
let mut v = Vec::with_capacity(text_length);
v.extend_from_slice(&text_bytes[..(p - ($l + 1))]);
break (v, p - $l);
},
{
let mut v = Vec::with_capacity(text_length);
v.extend_from_slice(&text_bytes[..(p - 1)]);
break (v, p);
},
{
let mut v = Vec::with_capacity(text_length);
v.extend_from_slice(&text_bytes[..(p - 3)]);
break (v, p - 2);
}
);
p += 1;
};
p += 1;
for e in text_bytes[p..].iter().copied() {
$parse_macro!(e, step,
{
v.extend_from_slice(&text_bytes[start..(p - ($l + 1))]);
start = p - $l;
},
{
v.extend_from_slice(&text_bytes[start..(p - 1)]);
start = p;
},
{
v.extend_from_slice(&text_bytes[start..(p - 3)]);
start = p - 2;
}
);
p += 1;
}
v.extend_from_slice(&text_bytes[start..p]);
Cow::from(unsafe { String::from_utf8_unchecked(v) })
}
$(#[$decode_to_string_attr])*
///
$(#[$attr])*
#[inline]
pub fn $decode_to_string_name<S: AsRef<str>>(text: S, output: &mut String) -> &str {
unsafe { from_utf8_unchecked($decode_to_vec_name(text, output.as_mut_vec())) }
}
$(#[$decode_to_vec_attr])*
///
$(#[$attr])*
#[inline]
pub fn $decode_to_vec_name<S: AsRef<str>>(text: S, output: &mut Vec<u8>) -> &[u8] {
let text = text.as_ref();
let text_bytes = text.as_bytes();
let text_length = text_bytes.len();
output.reserve(text_length);
let current_length = output.len();
let mut start = 0;
let mut end = 0;
let mut step = 0;
for e in text_bytes.iter().copied() {
$parse_macro!(e, step,
{
output.extend_from_slice(&text_bytes[start..(end - ($l + 1))]);
start = end - $l;
},
{
output.extend_from_slice(&text_bytes[start..(end - 1)]);
start = end;
},
{
output.extend_from_slice(&text_bytes[start..(end - 3)]);
start = end - 2;
}
);
end += 1;
}
output.extend_from_slice(&text_bytes[start..end]);
&output[current_length..]
}
#[cfg(feature = "std")]
$(#[$decode_to_writer_attr])*
///
$(#[$attr])*
#[inline]
pub fn $decode_to_writer_name<S: AsRef<str>, W: Write>(text: S, output: &mut W) -> Result<(), io::Error> {
let text = text.as_ref();
let text_bytes = text.as_bytes();
let mut start = 0;
let mut end = 0;
let mut step = 0;
for e in text_bytes.iter().copied() {
$parse_macro!(e, step,
{
output.write_all(&text_bytes[start..(end - ($l + 1))])?;
start = end - $l;
},
{
output.write_all(&text_bytes[start..(end - 1)])?;
start = end;
},
{
output.write_all(&text_bytes[start..(end - 3)])?;
start = end - 2;
}
);
end += 1;
}
output.write_all(&text_bytes[start..end])
}
};
}