use crate::ascii::ascii_prefix_len_capped;
use crate::result::{DecoderResult, EncoderResult};
use crate::sink::{ByteSink, DECODER_HEADROOM, ENCODER_HEADROOM};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct Identity {
limit: u16,
}
impl Identity {
pub(crate) const fn latin1() -> Self {
Identity { limit: 0x100 }
}
pub(crate) const fn ascii() -> Self {
Identity { limit: 0x80 }
}
pub(crate) fn decode(&mut self, src: &[u8], sink: &mut ByteSink) -> (DecoderResult, usize) {
let mut read = 0usize;
loop {
if !sink.has_room(DECODER_HEADROOM) {
return (DecoderResult::OutputFull, read);
}
let rest = &src[read..];
let run = ascii_prefix_len_capped(rest, sink.room());
if run > 0 {
sink.write_slice(&rest[..run]);
read += run;
continue;
}
let Some(byte) = rest.first().copied() else {
return (DecoderResult::InputEmpty, read);
};
if u16::from(byte) >= self.limit {
read += 1;
return (DecoderResult::Malformed(1), read);
}
read += 1;
sink.write_code_point(u32::from(byte));
}
}
pub(crate) fn encode(&mut self, src: &str, sink: &mut ByteSink) -> (EncoderResult, usize) {
let mut read = 0usize;
loop {
if !sink.has_room(ENCODER_HEADROOM) {
return (EncoderResult::OutputFull, read);
}
let rest = &src[read..];
let run = ascii_prefix_len_capped(rest.as_bytes(), sink.room());
if run > 0 {
sink.write_slice(&rest.as_bytes()[..run]);
read += run;
continue;
}
let Some(c) = rest.chars().next() else {
return (EncoderResult::InputEmpty, read);
};
read += c.len_utf8();
let scalar = u32::from(c);
if scalar >= u32::from(self.limit) {
return (EncoderResult::Unmappable(c), read);
}
sink.write_byte(scalar as u8);
}
}
}