use crate::{
base::{
octet,
BaseAtom,
},
utils::Utils,
Contexting,
CoreAtom,
Parse,
Parsed,
Streaming,
Success,
};
fn raw<Stream, Context>(stream: Stream) -> Parsed<u32, Stream, Context>
where
Stream: Streaming,
Context: Contexting<CoreAtom<Stream>>,
Context: Contexting<BaseAtom<u8>>,
Stream::Item: Into<u8>,
{
let Success { token: a, stream } = octet.parse(stream)?;
if a & 0x80 == 0 {
Parsed::Success {
token: a as u32,
stream,
}
} else if a & 0xE0 == 0xC0 {
let Success { token: b, stream } = octet.parse(stream)?;
Parsed::Success {
token: (a as u32 & 0x1F) << 6 | (b as u32 & 0x3F),
stream,
}
} else if a & 0xF0 == 0xE0 {
let Success { token: b, stream } = octet.parse(stream)?;
let Success { token: c, stream } = octet.parse(stream)?;
Parsed::Success {
token: (a as u32 & 0x0F) << 12 | (b as u32 & 0x3F) << 6 | (c as u32 & 0x3F),
stream,
}
} else if a & 0xF8 == 0xF0 {
let Success { token: b, stream } = octet.parse(stream)?;
let Success { token: c, stream } = octet.parse(stream)?;
let Success { token: d, stream } = octet.parse(stream)?;
Parsed::Success {
token: (a as u32 & 0x07) << 18
| (b as u32 & 0x3F) << 12
| (c as u32 & 0x3F) << 6
| (d as u32 & 0x3F),
stream,
}
} else {
Parsed::Failure(Contexting::new(BaseAtom::Utf8 {}))
}
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip_all, ret(Display))
)]
pub fn utf8<Stream, Context>(stream: Stream) -> Parsed<char, Stream, Context>
where
Stream: Streaming,
Context: Contexting<CoreAtom<Stream>>,
Context: Contexting<BaseAtom<u8>>,
Stream::Item: Into<u8>,
{
raw
.try_map(|raw| char::from_u32(raw).ok_or_else(|| Contexting::new(BaseAtom::Utf8 {})))
.parse(stream)
}
#[cfg(test)]
mod tests {
use crate::{
context::Ignore,
Parsed,
};
#[test]
fn utf8() {
println!("{}", "❤".len());
assert_eq!(
super::utf8::<_, Ignore>("❤".as_bytes()),
Parsed::Success {
token: '❤',
stream: "".as_bytes(),
}
);
}
}