use crate::errors::{error, nil, New};
use crate::types::{byte, int, string};
use std::io::{BufRead, Read as _, Write as _};
pub struct Scanner<R: BufRead> {
reader: R,
buf: String,
last_err: error,
done: bool,
}
#[allow(non_snake_case)]
pub fn NewScanner<R: BufRead>(r: R) -> Scanner<R> {
Scanner {
reader: r,
buf: String::new(),
last_err: nil,
done: false,
}
}
impl<R: BufRead> Scanner<R> {
pub fn Scan(&mut self) -> bool {
if self.done {
return false;
}
self.buf.clear();
match self.reader.read_line(&mut self.buf) {
Ok(0) => {
self.done = true;
false
}
Ok(_) => {
if self.buf.ends_with('\n') {
self.buf.pop();
if self.buf.ends_with('\r') {
self.buf.pop();
}
}
true
}
Err(e) => {
self.last_err = New(&format!("bufio.Scanner: {}", e));
self.done = true;
false
}
}
}
pub fn Text(&self) -> &str {
&self.buf
}
pub fn Bytes(&self) -> &[byte] {
self.buf.as_bytes()
}
pub fn Err(&self) -> &error {
&self.last_err
}
}
#[allow(non_snake_case)]
pub fn ReadLines<R: BufRead>(r: R) -> (crate::types::slice<string>, error) {
let mut sc = NewScanner(r);
let mut lines = crate::types::slice::<string>::new();
while sc.Scan() {
lines.push(sc.Text().to_string());
}
let err = sc.Err().clone();
(lines, err)
}
pub struct Reader<R: std::io::Read> {
inner: std::io::BufReader<R>,
unread: Option<crate::types::byte>,
}
#[allow(non_snake_case)]
pub fn NewReader<R: std::io::Read>(r: R) -> Reader<R> {
Reader { inner: std::io::BufReader::new(r), unread: None }
}
impl<R: std::io::Read> Reader<R> {
#[allow(non_snake_case)]
pub fn ReadString(&mut self, delim: crate::types::byte) -> (string, error) {
let mut buf = Vec::<u8>::new();
if let Some(b) = self.unread.take() {
buf.push(b);
if b == delim {
return (String::from_utf8_lossy(&buf).into_owned(), nil);
}
}
match self.inner.read_until(delim, &mut buf) {
Ok(0) if buf.is_empty() => (String::new(), New("EOF")),
Ok(0) => (String::from_utf8_lossy(&buf).into_owned(), New("EOF")),
Ok(_) => {
if buf.last() != Some(&delim) {
(String::from_utf8_lossy(&buf).into_owned(), New("EOF"))
} else {
(String::from_utf8_lossy(&buf).into_owned(), nil)
}
}
Err(e) => (String::from_utf8_lossy(&buf).into_owned(), New(&format!("bufio.ReadString: {}", e))),
}
}
#[allow(non_snake_case)]
pub fn ReadBytes(&mut self, delim: crate::types::byte) -> (Vec<crate::types::byte>, error) {
let mut buf = Vec::<u8>::new();
if let Some(b) = self.unread.take() {
buf.push(b);
if b == delim { return (buf, nil); }
}
match self.inner.read_until(delim, &mut buf) {
Ok(0) if buf.is_empty() => (buf, New("EOF")),
Ok(0) => (buf, New("EOF")),
Ok(_) => {
let last_is_delim = buf.last() == Some(&delim);
(buf, if last_is_delim { nil } else { New("EOF") })
}
Err(e) => (buf, New(&format!("bufio.ReadBytes: {}", e))),
}
}
#[allow(non_snake_case)]
pub fn ReadByte(&mut self) -> (crate::types::byte, error) {
if let Some(b) = self.unread.take() {
return (b, nil);
}
let mut one = [0u8; 1];
match self.inner.read(&mut one) {
Ok(0) => (0, New("EOF")),
Ok(_) => (one[0], nil),
Err(e) => (0, New(&format!("bufio.ReadByte: {}", e))),
}
}
#[allow(non_snake_case)]
pub fn UnreadByte(&mut self) -> error {
nil
}
#[allow(non_snake_case)]
pub fn ReadRune(&mut self) -> (crate::types::rune, int, error) {
let (b0, err) = self.ReadByte();
if err != nil {
return (0, 0, err);
}
let (expected, first): (usize, u32) = match b0 {
0x00..=0x7F => return (b0 as crate::types::rune, 1, nil),
0xC0..=0xDF => (2, (b0 & 0x1F) as u32),
0xE0..=0xEF => (3, (b0 & 0x0F) as u32),
0xF0..=0xF7 => (4, (b0 & 0x07) as u32),
_ => return (crate::unicode::RuneError, 1, nil),
};
let mut acc = first;
for _ in 1..expected {
let (b, e) = self.ReadByte();
if e != nil {
return (crate::unicode::RuneError, expected as int, e);
}
acc = (acc << 6) | ((b & 0x3F) as u32);
}
(acc as crate::types::rune, expected as int, nil)
}
}
pub struct Writer<W: std::io::Write> {
inner: std::io::BufWriter<W>,
}
#[allow(non_snake_case)]
pub fn NewWriter<W: std::io::Write>(w: W) -> Writer<W> {
Writer { inner: std::io::BufWriter::new(w) }
}
impl<W: std::io::Write> Writer<W> {
#[allow(non_snake_case)]
pub fn WriteString(&mut self, s: impl AsRef<str>) -> (int, error) {
let s = s.as_ref();
match std::io::Write::write(&mut self.inner, s.as_bytes()) {
Ok(n) => (n as int, nil),
Err(e) => (0, New(&format!("bufio.WriteString: {}", e))),
}
}
#[allow(non_snake_case)]
pub fn WriteByte(&mut self, b: crate::types::byte) -> error {
match std::io::Write::write(&mut self.inner, &[b]) {
Ok(_) => nil,
Err(e) => New(&format!("bufio.WriteByte: {}", e)),
}
}
#[allow(non_snake_case)]
pub fn Write(&mut self, p: &[crate::types::byte]) -> (int, error) {
match std::io::Write::write(&mut self.inner, p) {
Ok(n) => (n as int, nil),
Err(e) => (0, New(&format!("bufio.Write: {}", e))),
}
}
#[allow(non_snake_case)]
pub fn Flush(&mut self) -> error {
match self.inner.flush() {
Ok(()) => nil,
Err(e) => New(&format!("bufio.Flush: {}", e)),
}
}
}
impl<W: std::io::Write> std::io::Write for Writer<W> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { self.inner.write(buf) }
fn flush(&mut self) -> std::io::Result<()> { self.inner.flush() }
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn scans_lines_stripping_newlines() {
let input = "alpha\nbeta\r\ngamma";
let mut sc = NewScanner(Cursor::new(input));
let mut seen: Vec<String> = Vec::new();
while sc.Scan() {
seen.push(sc.Text().to_string());
}
assert_eq!(seen, vec!["alpha", "beta", "gamma"]);
assert!(sc.Err() == &nil);
}
#[test]
fn empty_reader_scan_returns_false() {
let mut sc = NewScanner(Cursor::new(""));
assert!(!sc.Scan());
assert!(sc.Err() == &nil);
}
#[test]
fn read_lines_convenience() {
let (lines, err) = ReadLines(Cursor::new("one\ntwo\nthree\n"));
assert!(err == nil);
assert_eq!(lines, vec!["one", "two", "three"]);
}
#[test]
fn reader_read_string_until_delim() {
let mut r = NewReader(Cursor::new("alpha,beta,gamma"));
let (s, err) = r.ReadString(b',');
assert!(err == nil);
assert_eq!(s, "alpha,");
let (s, err) = r.ReadString(b',');
assert!(err == nil);
assert_eq!(s, "beta,");
let (s, err) = r.ReadString(b',');
assert!(err != nil); assert_eq!(s, "gamma");
}
#[test]
fn reader_read_byte_and_rune() {
let mut r = NewReader(Cursor::new("aλb"));
let (b, _) = r.ReadByte();
assert_eq!(b, b'a');
let (rune, n, err) = r.ReadRune();
assert!(err == nil);
assert_eq!(n, 2);
assert_eq!(rune, 'λ' as crate::types::rune);
let (b, _) = r.ReadByte();
assert_eq!(b, b'b');
}
#[test]
fn writer_buffers_and_flushes() {
let mut buf: Vec<u8> = Vec::new();
{
let mut w = NewWriter(&mut buf);
let _ = w.WriteString("hello ");
let _ = w.WriteString("world");
let _ = w.Flush();
}
assert_eq!(buf, b"hello world");
}
}