You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rewot/src/mudlet_replay.rs

87 lines
1.8 KiB

use std::io;
use std::io::Read;
use std::thread::sleep;
use std::time::Duration;
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
#[derive(Debug)]
struct Chunk {
pub delta: i32,
pub text: String,
}
impl Chunk {
fn chunk32(chunk: &[u8; 8]) -> Result<(i32, i32)> {
let (dc, sc) = {
let (mut dc, mut sc): ([u8; 4], [u8; 4]) = ([0; 4], [0; 4]);
for i in 0..4 {
dc[i] = chunk[i];
sc[i] = chunk[i + 4];
}
(dc, sc)
};
let delta = i32::from_be_bytes(dc);
let size = i32::from_be_bytes(sc);
if delta < 0 || size < 1 || size > 100000 {
return Err("delta source is not int32_t".into());
}
Ok((delta, size))
}
fn chunk64(dc: [u8; 8], sc: [u8; 4]) -> Result<(i32, i32)> {
let delta = i64::from_be_bytes(dc);
let size = i32::from_be_bytes(sc);
if delta < 0 || delta > i32::MAX.into() || size < 1 || size > 100000 {
return Err("delta source is not int64_t".into());
}
let delta: i32 = delta.try_into()?;
Ok((delta, size))
}
pub fn read_chunk() -> Result<Self> {
let mut stdin = io::stdin();
let mut chunk: [u8; 8] = [0; 8];
stdin.read_exact(&mut chunk)?;
let (delta, size) = {
if let Ok((delta, size)) = Self::chunk32(&chunk) {
(delta, size)
} else {
let mut next_chunk: [u8; 4] = [0; 4];
stdin.read_exact(&mut next_chunk)?;
if let Ok((delta, size)) = Self::chunk64(chunk, next_chunk) {
(delta, size)
} else {
return Err("broken".into());
}
}
};
let mut text_chunk: Vec<u8> = vec![0; size as usize];
stdin.read_exact(&mut text_chunk)?;
let text = String::from_utf8(text_chunk)?;
Ok(Self { delta, text })
}
}
fn main() -> Result<()> {
while let Ok(chunk) = Chunk::read_chunk() {
sleep(Duration::from_millis(chunk.delta.try_into()?));
print!("{}", chunk.text);
}
println!();
Ok(())
}