๐Ÿฆ€ Functional Rust

341: Buffered Stream

Difficulty: Intermediate Category: IO Concept: BufReader/BufWriter wrapping stdin/stdout Key Insight: Buffering reduces system calls โ€” wrapping raw I/O in buffers is essential for performance
// 341: Buffered Stream
// BufReader/BufWriter wrapping for efficient I/O

use std::io::{self, BufRead, BufWriter, Write, BufReader, Cursor};

// Approach 1: BufReader for efficient reading
fn count_lines(input: &[u8]) -> usize {
    let reader = BufReader::new(input);
    reader.lines().count()
}

fn read_lines(input: &[u8]) -> Vec<String> {
    let reader = BufReader::new(input);
    reader.lines().filter_map(|l| l.ok()).collect()
}

// Approach 2: BufWriter for efficient writing
fn write_lines(lines: &[&str]) -> Vec<u8> {
    let mut output = Vec::new();
    {
        let mut writer = BufWriter::new(&mut output);
        for line in lines {
            writeln!(writer, "{}", line).unwrap();
        }
        writer.flush().unwrap();
    }
    output
}

// Approach 3: String building with buffered writes
fn build_csv(headers: &[&str], rows: &[Vec<String>]) -> String {
    let mut buf = Vec::new();
    {
        let mut writer = BufWriter::new(&mut buf);
        writeln!(writer, "{}", headers.join(",")).unwrap();
        for row in rows {
            writeln!(writer, "{}", row.join(",")).unwrap();
        }
        writer.flush().unwrap();
    }
    String::from_utf8(buf).unwrap()
}

fn main() {
    let input = b"hello\nworld\ntest\n";
    println!("lines: {}", count_lines(input));
    println!("read: {:?}", read_lines(input));

    let output = write_lines(&["hello", "world"]);
    println!("written: {:?}", String::from_utf8(output).unwrap());

    let csv = build_csv(
        &["name", "age"],
        &[vec!["Alice".into(), "30".into()], vec!["Bob".into(), "25".into()]],
    );
    println!("csv:\n{}", csv);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_count_lines() {
        assert_eq!(count_lines(b"a\nb\nc\n"), 3);
        assert_eq!(count_lines(b""), 0);
    }

    #[test]
    fn test_read_lines() {
        let lines = read_lines(b"hello\nworld\n");
        assert_eq!(lines, vec!["hello", "world"]);
    }

    #[test]
    fn test_write_lines() {
        let output = write_lines(&["hello", "world"]);
        let s = String::from_utf8(output).unwrap();
        assert!(s.contains("hello"));
        assert!(s.contains("world"));
    }

    #[test]
    fn test_csv() {
        let csv = build_csv(&["a", "b"], &[vec!["1".into(), "2".into()]]);
        assert!(csv.starts_with("a,b\n"));
        assert!(csv.contains("1,2"));
    }
}
(* 341: Buffered Stream *)
(* OCaml channels are already buffered by default *)

(* Approach 1: Buffered input *)
let read_lines_buffered ic =
  let rec aux acc =
    match input_line ic with
    | line -> aux (line :: acc)
    | exception End_of_file -> List.rev acc
  in
  aux []

(* Approach 2: Buffered output *)
let write_lines_buffered oc lines =
  List.iter (fun line ->
    output_string oc line;
    output_char oc '\n'
  ) lines;
  flush oc

(* Approach 3: Buffer module for string building *)
let build_string parts =
  let buf = Buffer.create 256 in
  List.iter (fun s ->
    Buffer.add_string buf s;
    Buffer.add_char buf '\n'
  ) parts;
  Buffer.contents buf

(* Tests *)
let () =
  let result = build_string ["hello"; "world"; "test"] in
  assert (result = "hello\nworld\ntest\n");
  let buf = Buffer.create 16 in
  Buffer.add_string buf "abc";
  Buffer.add_string buf "def";
  assert (Buffer.contents buf = "abcdef");
  Printf.printf "โœ“ All tests passed\n"

๐Ÿ“Š Detailed Comparison

Core Insight

Buffering reduces system calls โ€” wrapping raw I/O in buffers is essential for performance

OCaml Approach

  • See example.ml for implementation

Rust Approach

  • See example.rs for implementation

Comparison Table

FeatureOCamlRust
Seeexample.mlexample.rs