use super::{DataEncodingError, EncodingContext};
fn randomize_255_state(ch: u8, pos: usize) -> u8 {
let pseudo_random = ((149 * pos) % 255) + 1;
let tmp = ch as u16 + pseudo_random as u16;
if tmp <= 255 {
tmp as u8
} else {
(tmp - 256) as u8
}
}
fn write_length<T: EncodingContext>(ctx: &mut T, start: usize) -> Result<(), DataEncodingError> {
let space_left = ctx
.symbol_size_left(0)
.ok_or(DataEncodingError::TooMuchOrIllegalData)?;
let mut data_written = ctx.codewords().len() - start;
if ctx.has_more_characters() || space_left > 0 {
let data_count = data_written - 1;
if data_count <= 249 {
ctx.replace(start, data_count as u8);
} else if data_count <= 1555 {
ctx.replace(start, ((data_count / 250) + 249) as u8);
ctx.insert(start + 1, (data_count % 250) as u8);
data_written += 1;
} else {
panic!("base256 data too long, this is an encoding bug");
}
}
for i in 0..data_written {
let ch = ctx.codewords()[start + i];
ctx.replace(start + i, randomize_255_state(ch, start + i + 1));
}
Ok(())
}
pub(super) fn encode<T: EncodingContext>(ctx: &mut T) -> Result<(), DataEncodingError> {
let start = ctx.codewords().len();
ctx.push(0);
loop {
if let Some(ch) = ctx.eat() {
ctx.push(ch);
}
if !ctx.has_more_characters() || ctx.maybe_switch_mode()? {
write_length(ctx, start)?;
if !ctx.has_more_characters() {
ctx.set_ascii_until_end();
}
return Ok(());
}
}
}