Skip to content

Instantly share code, notes, and snippets.

@stefanoc
Created February 5, 2015 20:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stefanoc/c85857b124b31c3ca86b to your computer and use it in GitHub Desktop.
Save stefanoc/c85857b124b31c3ca86b to your computer and use it in GitHub Desktop.
Rust word counter
[package]
name = "wc"
version = "0.0.1"
authors = ["stefano"]
[dependencies]
regex = "0.1.12"
regex_macros = "0.1.6"
#![feature(core)]
#![feature(collections)]
#![feature(std_misc)]
#![feature(io)]
#![feature(plugin)]
#[plugin] #[no_link] extern crate regex_macros;
extern crate regex;
use std::collections::btree_map::{BTreeMap, Occupied, Vacant};
use std::old_io as io;
use std::sync::mpsc::channel;
use std::sync::mpsc::{Sender};
use std::thread::Thread;
macro_rules! val [
($inp:expr) => { match $inp { Ok(val) => val, _ => { panic!("Value expected"); } } }
];
macro_rules! stop [
($tx:ident) => { $tx.send(STOP.to_string()).ok(); }
];
macro_rules! send [
($tx:expr, $val:expr) => { $tx.send($val).ok(); }
];
macro_rules! map_incr [
($dict:expr, $key:expr) => {
match $dict.entry($key) {
Vacant(entry) => { entry.insert(1); },
Occupied(mut entry) => *entry.get_mut() += 1,
}
}
];
static STOP: &'static str = ".STOP";
fn spawn_line_worker(tx_word: Sender<String>) -> Sender<String> {
let (tx_line, rx_line) = channel::<String>();
Thread::spawn(move || {
let re = regex!(r"\w+");
loop {
let line = rx_line.recv().unwrap();
if &line[] == STOP {
stop!(tx_word);
break;
}
for (a, b) in re.find_iter(&line[]) {
send!(tx_word, line.slice_chars(a, b).to_string());
}
}
});
return tx_line;
}
fn main() {
let pool_size = 4;
let mut line_workers = vec![];
let (tx_word, rx_word) = channel::<String>();
for _ in range(0, pool_size) { line_workers.push(spawn_line_worker(tx_word.clone())); }
let counter = Thread::scoped(move || -> BTreeMap<_, _> {
let mut dict = BTreeMap::new();
let mut finished = 0;
loop {
let word = rx_word.recv().unwrap();
if &word[] == STOP {
finished += 1;
if finished == pool_size { break; }
} else {
map_incr!(dict, word);
}
}
return dict;
});
let mut line_no = 0;
for line in io::stdin().lock().lines() {
send!(line_workers[line_no % pool_size], line.unwrap());
line_no += 1;
}
for tx in line_workers.iter() { stop!(tx); }
let dict = val!(counter.join());
println!("{:?}", dict);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment