diff --git a/Makefile b/Makefile index 46fd88e..d8c0c59 100644 --- a/Makefile +++ b/Makefile @@ -101,6 +101,13 @@ strcmp: build/bin/strcmp build/bin/strcmp: src/strcmp.c build $(CC) $(CFLAGS) -o $@ src/strcmp.c +.PHONY: swab +swab: build/bin/swab +build/bin/swab: src/swab.rs build build/o/libsysexits.rlib + $(RUSTC) $(RUSTFLAGS) \ + --extern sysexits=build/o/libsysexits.rlib \ + -o $@ src/swab.rs + .PHONY: true true: build/bin/true build/bin/true: src/true.c build diff --git a/src/swab.rs b/src/swab.rs new file mode 100644 index 0000000..26104eb --- /dev/null +++ b/src/swab.rs @@ -0,0 +1,47 @@ +use std::{ + env::args, + io::{ stdin, stdout, Error, ErrorKind, Read, Write }, + process::ExitCode, + vec::Vec +}; + +extern crate sysexits; + +use sysexits::{ EX_OK, EX_OSERR }; + +fn oserr(s: &str, e: Error) -> ExitCode { + eprintln!("{}: {}", s, e); + ExitCode::from(EX_OSERR as u8) +} + +fn main() -> ExitCode { + let argv = args().collect::>(); + let mut buf: Vec = Vec::new(); + let mut input = stdin(); + let mut output = stdout().lock(); + + let wordsize: usize = 2; + let force = false; + + buf.resize(wordsize, 0); + + loop { + match input.read(&mut buf) { + Ok(0) => break ExitCode::from(EX_OK as u8), + Ok(v) if v == wordsize => { + let (left, right) = buf.split_at(v/2); + if let Err(e) = output.write(&right) + .and_then(|_| output.write(&left)) { + break oserr(&argv[0], e) + } + }, + Ok(v) => { + if let Err(e) = output.write(&buf[..v]) { + break oserr(&argv[0], e) + } + }, + Err(e) if e.kind() == ErrorKind::Interrupted && force => continue, + Err(e) => break oserr(&argv[0], e) + } + } +}