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.
87 lines
1.8 KiB
87 lines
1.8 KiB
3 years ago
|
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(())
|
||
|
}
|