The Evolution of a Rust Programmer
Freshman Rust Programmer
fn main() {
let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
let mut sum = 0;
for word in line.split_whitespace() {
let num = word.parse::<i64>().unwrap();
sum += num;
}
println!("Sum: {}", sum);
}
Sophomore Rust Programmer
(studied C as a freshman)
extern crate libc;
use libc::{c_char, printf, scanf, EOF};
fn main() {
unsafe {
let mut num = 0;
let mut sum = 0;
while(scanf(b"%d\0" as *const u8 as *const c_char, &mut num) != EOF) {
sum += num;
}
printf(b"Sum: %d\n\0" as *const u8 as *const c_char, sum);
}
}
Junior Rust Programmer
(read that unwrap()
foils rust’s error management philosophy and joined the "It should be removed in favor of expect()
"-movement)
fn main() {
let mut line = String::new();
std::io::stdin().read_line(&mut line).expect("read line");
let mut sum = 0;
for word in line.split_whitespace() {
let num = word.parse::<i64>().expect("parse");
sum += num;
}
println!("Sum: {}", sum);
}
Senior Rust Programmer
(learned proper error management)
use std::error;
use std::fmt::{self, Display, Formatter};
use std::io;
use std::num::ParseIntError;
use std::result;
#[derive(Debug)]
enum Error {
Io(io::Error),
Parse(ParseIntError),
}
impl Display for Error {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
match *self {
Error::Io(ref error) => error.fmt(formatter),
Error::Parse(ref error) => error.fmt(formatter),
}
}
}
impl error::Error for Error {
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Error::Io(error)
}
}
impl From<ParseIntError> for Error {
fn from(error: ParseIntError) -> Self {
Error::Parse(error)
}
}
type Result<T> = result::Result<T, Error>;
fn main() -> Result<()> {
let mut line = String::new();
std::io::stdin().read_line(&mut line)?;
let mut sum = 0;
for word in line.split_whitespace() {
let num = word.parse::<i64>()?;
sum += num;
}
println!("Sum: {}", sum);
Ok(())
}
Functional Rust Programmer
(studied Haskell as a freshman and loathes mutability)
use std::io::BufRead;
fn main() {
let stdin = std::io::stdin();
let line = stdin.lock().lines().next().unwrap().unwrap();
let sum: i64 =
line.split_whitespace()
.map(|word| word.parse::<i64>().unwrap())
.sum();
println!("Sum: {}", sum);
}
Object-oriented Programmer
(studied Java as a freshman)
use std::ops::Deref;
struct Nums {
vector: Vec<i64>,
}
impl Nums {
fn new() -> Self {
Nums {
vector: Vec::new(),
}
}
fn add(&mut self, num: i64) {
self.vector.push(num);
}
fn get_sum(&self) -> i64 {
(*self).iter().sum()
}
}
impl Deref for Nums {
type Target = Vec<i64>;
fn deref(&self) -> &Self::Target {
&self.vector
}
}
fn main() {
let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
let mut nums = Nums::new();
for word in line.split_whitespace() {
let num = word.parse::<i64>().unwrap();
nums.add(num);
}
println!("Sum: {}", nums.get_sum());
}
Macro-man
(misses Lisp macros)
use std::fmt::{self, Display, Formatter};
use std::io;
use std::num::ParseIntError;
use std::result;
macro_rules! from {
($from:ty, $typ:ty, $result:expr) => {
impl From<$from> for $typ {
fn from(error: $from) -> Self {
$result(error)
}
}
};
}
macro_rules! display {
($typ:ty, [$($patterns:path),*]) => {
impl Display for $typ {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
match *self {
$($patterns(ref error) => error.fmt(formatter)),*
}
}
}
};
}
macro_rules! error {
($typ:ty) => {
impl ::std::error::Error for $typ {
}
};
}
#[derive(Debug)]
enum Error {
Io(io::Error),
Parse(ParseIntError),
}
display!(Error, [Error::Io, Error::Parse]);
error!(Error);
from!(io::Error, Error, Error::Io);
from!(ParseIntError, Error, Error::Parse);
type Result<T> = result::Result<T, Error>;
fn main() -> Result<()> {
let mut line = String::new();
std::io::stdin().read_line(&mut line)?;
let mut sum = 0;
for word in line.split_whitespace() {
let num = word.parse::<i64>()?;
sum += num;
}
println!("Sum: {}", sum);
Ok(())
}
Macroceptor
(watched Inception)
use std::fmt::{self, Display, Formatter};
use std::io;
use std::num::ParseIntError;
use std::result;
macro_rules! display {
($typ:ty, [$($patterns:path),*]) => {
impl Display for $typ {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
match *self {
$($patterns(ref error) => error.fmt(formatter)),*
}
}
}
};
}
macro_rules! error {
($typ:ty) => {
impl ::std::error::Error for $typ {
}
macro_rules! from {
($from:ty, $result:expr) => {
impl From<$from> for $typ {
fn from(error: $from) -> Self {
$result(error)
}
}
};
}
};
}
#[derive(Debug)]
enum Error {
Io(io::Error),
Parse(ParseIntError),
}
display!(Error, [Error::Io, Error::Parse]);
error!(Error);
from!(io::Error, Error::Io);
from!(ParseIntError, Error::Parse);
type Result<T> = result::Result<T, Error>;
fn main() -> Result<()> {
let mut line = String::new();
std::io::stdin().read_line(&mut line)?;
let mut sum = 0;
for word in line.split_whitespace() {
let num = word.parse::<i64>()?;
sum += num;
}
println!("Sum: {}", sum);
Ok(())
}
Procedural Macro God
(needs more power)
main.rs
#![feature(proc_macro_hygiene)]
extern crate lib;
use lib::scanfold;
fn main() {
let sum = scanfold!("%ld+", |num: i64, acc: i64| num + acc);
println!("Sum: {}", sum);
}
lib.rs
extern crate proc_macro;
extern crate proc_macro2;
extern crate quote;
extern crate syn;
use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::{quote, quote_spanned};
use syn::{Error, Expr, ExprClosure, LitStr, Token, parse};
use syn::parse::{Parse, ParseStream, Result};
use syn::spanned::Spanned;
struct Parameters {
format: LitStr,
closure: ExprClosure,
}
impl Parse for Parameters {
fn parse(input: ParseStream) -> Result<Self> {
let format = input.parse()?;
let _comma: Token![,] = input.parse()?;
let closure: Expr = input.parse()?;
match closure {
Expr::Closure(closure) =>
Ok(Parameters {
format,
closure,
}),
_ => Err(Error::new(closure.span(), "Argument must be a closure"))
}
}
}
#[derive(PartialEq)]
enum Param {
Unknown,
Int,
Long,
LongInt,
Repeat(Box<Param>),
}
fn to_code(span: Span, param: &Param, recursive: bool) -> proc_macro2::TokenStream {
let start =
if recursive {
quote! {
}
}
else {
quote! {
let word = line.split_whitespace().next().unwrap();
}
};
match param {
Param::Unknown => quote_spanned! {
span => compile_error!("invalid format string")
},
Param::Int => quote! {{
#start
let num = word.parse::<i32>().unwrap();
closure(num, acc)
}},
Param::Long | Param::LongInt => quote! {{
#start
let num = word.parse::<i64>().unwrap();
closure(num, acc)
}},
Param::Repeat(ref inner_param) => {
let inner_code = to_code(span, inner_param, true);
quote! {{
for word in line.split_whitespace() {
acc = #inner_code;
}
acc
}}
},
}
}
#[proc_macro]
pub fn scanfold(input: TokenStream) -> TokenStream {
let parameters: Result<Parameters> = parse(input);
let result =
match parameters {
Ok(params) => {
let format = params.format.value();
let mut is_param = false;
let mut param = Param::Unknown;
for char in format.chars() {
if is_param {
match char {
'd' =>
if param == Param::Long {
param = Param::LongInt;
}
else {
param = Param::Int;
},
'l' => param = Param::Long,
'+' => param = Param::Repeat(Box::new(param)),
_ => (),
}
}
else if char == '%' {
is_param = true;
}
}
let code = to_code(params.format.span(), ¶m, false);
let closure = params.closure;
quote! {{
let closure = #closure;
let mut line = String::new();
let mut acc = 0;
std::io::stdin().read_line(&mut line).unwrap();
#code
}}
},
Err(error) => {
let msg = error.to_string();
quote_spanned! { error.span() =>
compile_error!(#msg)
}
},
};
result.into()
}
Another senior Rust programmer
(learned to reduce boilerplate with macros)
extern crate error_chain;
use std::io;
use std::num::ParseIntError;
use error_chain::*;
error_chain! {
types {
Error, ErrorKind, ResultExt, Result;
}
foreign_links {
Io(io::Error);
Parse(ParseIntError);
}
}
fn main() -> Result<()> {
let mut line = String::new();
std::io::stdin().read_line(&mut line)?;
let mut sum = 0;
for word in line.split_whitespace() {
let num = word.parse::<i64>()?;
sum += num;
}
println!("Sum: {}", sum);
Ok(())
}
Yet another senior Rust programmer
(switched from error-chain to stay up-to-date)
extern crate failure;
extern crate failure_derive;
use std::result;
use failure::bail;
use failure_derive::Fail;
#[derive(Debug, Fail)]
enum Error {
#[fail(display = "empty string")]
Empty,
}
type Result<T> = result::Result<T, failure::Error>;
fn main() -> Result<()> {
let mut line = String::new();
std::io::stdin().read_line(&mut line)?;
let mut sum = 0;
let mut empty = true;
for word in line.split_whitespace() {
empty = false;
let num = word.parse::<i64>()?;
sum += num;
}
if empty {
bail!(Error::Empty);
}
println!("Sum: {}", sum);
Ok(())
}
Hyper-Functional Rust Programmer
(misses Haskell so much that he needs an additional library for more functional power)
extern crate itertools;
use std::io::BufRead;
use itertools::fold;
fn main() {
let stdin = std::io::stdin();
let line = stdin.lock().lines().next().unwrap().unwrap();
let iter =
line.split_whitespace()
.map(|word| word.parse::<i64>().unwrap());
let sum = fold(iter, 0, |a, b| a + b);
println!("Sum: {}", sum);
}
Combinative Rust Programmer
(learned that nom is faster than parsec)
extern crate nom;
use std::str::FromStr;
use nom::{call, digit, error_position, many1, map_res, named, recognize, sep, wrap_sep, ws};
use nom::types::CompleteStr;
named!(numbers<CompleteStr, Vec<i64>>,
many1!(ws!(
map_res!(recognize!(digit), |complete_str: CompleteStr| i64::from_str(&*complete_str))
))
);
fn main() {
let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
line.pop();
let (_input, nums) = numbers(line.as_str().into()).unwrap();
let sum: i64 = nums.iter().sum();
println!("Sum: {}", sum);
}
Rust Fast and Elegant Parser Writer
(learned that pest is faster than nom)
extern crate pest;
#[macro_use]
extern crate pest_derive;
use pest::Parser;
#[derive(Parser)]
#[grammar = "nums.pest"]
struct Nums;
fn main() {
let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
let pairs = Nums::parse(Rule::nums, &line).unwrap();
let mut sum = 0;
for pair in pairs {
for word in pair.into_inner() {
let num = word.as_str().parse::<i64>().unwrap();
sum += num;
}
}
println!("Sum: {}", sum);
}
Outdated Rust Programmer
(learned Rust in 2009)
extern crate rustc_serialize;
use std::collections::VecDeque;
use std::num::ParseIntError;
use rustc_serialize::Decodable;
#[derive(RustcDecodable)]
struct Nums {
nums: Vec<i64>,
}
fn main() {
let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
let nums: Nums = decode(line).unwrap();
let sum: i64 = nums.nums.iter().sum();
println!("Sum: {}", sum);
}
struct Decoder {
nums: VecDeque<i64>,
}
impl Decoder {
fn new(input: String) -> Result<Self, ParseIntError> {
let nums: Result<VecDeque<i64>, ParseIntError> = input.split_whitespace().map(|word| word.parse::<i64>())
.collect();
Ok(Self {
nums: nums?,
})
}
}
impl rustc_serialize::Decoder for Decoder {
fn read_i64(&mut self) -> Result<i64, Self::Error> {
self.nums.pop_front().ok_or(())
}
fn read_struct<T, F>(&mut self, _struct_name: &str, _len: usize, f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> {
f(self)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> {
f(self)
}
fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error> {
let len = self.nums.len();
f(self, len)
}
fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
where
F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
type Error = ();
fn read_nil(&mut self) -> Result<(), Self::Error> { unimplemented!() }
fn read_usize(&mut self) -> Result<usize, Self::Error> { unimplemented!() }
fn read_u64(&mut self) -> Result<u64, Self::Error> { unimplemented!() }
fn read_u32(&mut self) -> Result<u32, Self::Error> { unimplemented!() }
fn read_u16(&mut self) -> Result<u16, Self::Error> { unimplemented!() }
fn read_u8(&mut self) -> Result<u8, Self::Error> { unimplemented!() }
fn read_isize(&mut self) -> Result<isize, Self::Error> { unimplemented!() }
fn read_i32(&mut self) -> Result<i32, Self::Error> { unimplemented!() }
fn read_i16(&mut self) -> Result<i16, Self::Error> { unimplemented!() }
fn read_i8(&mut self) -> Result<i8, Self::Error> { unimplemented!() }
fn read_bool(&mut self) -> Result<bool, Self::Error> { unimplemented!() }
fn read_f64(&mut self) -> Result<f64, Self::Error> { unimplemented!() }
fn read_f32(&mut self) -> Result<f32, Self::Error> { unimplemented!() }
fn read_char(&mut self) -> Result<char, Self::Error> { unimplemented!() }
fn read_str(&mut self) -> Result<String, Self::Error> { unimplemented!() }
fn read_enum<T, F>(&mut self, _name: &str, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> { unimplemented!() }
fn read_enum_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Self::Error> where F: FnMut(&mut Self, usize) -> Result<T, Self::Error> { unimplemented!() }
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> { unimplemented!() }
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) -> Result<T, Self::Error> where F: FnMut(&mut Self, usize) -> Result<T, Self::Error> { unimplemented!() }
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> { unimplemented!() }
fn read_tuple<T, F>(&mut self, _len: usize, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> { unimplemented!() }
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> { unimplemented!() }
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> { unimplemented!() }
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> { unimplemented!() }
fn read_option<T, F>(&mut self, _f: F) -> Result<T, Self::Error> where F: FnMut(&mut Self, bool) -> Result<T, Self::Error> { unimplemented!() }
fn read_map<T, F>(&mut self, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error> { unimplemented!() }
fn read_map_elt_key<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> { unimplemented!() }
fn read_map_elt_val<T, F>(&mut self, _idx: usize, _f: F) -> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error> { unimplemented!() }
fn error(&mut self, _err: &str) -> Self::Error { unimplemented!() }
}
fn decode<T: Decodable>(string: String) -> Option<T> {
let mut decoder = Decoder::new(string).unwrap();
Decodable::decode(&mut decoder).ok()
}
Hyped Rust Programmer
(learned that serde is the new shiny thing for serialization)
extern crate serde;
extern crate serde_derive;
use std::collections::VecDeque;
use std::num::ParseIntError;
use serde::{Deserialize, Deserializer};
use serde::de::{DeserializeSeed, SeqAccess, Visitor};
use serde::de::value::Error;
pub fn from_str<T>(s: &str) -> Result<T, Error>
where for<'a> T: Deserialize<'a>,
{
let mut deserializer = Decoder::from_str(s.to_string()).unwrap();
let t = T::deserialize(&mut deserializer)?;
if deserializer.nums.is_empty() {
Ok(t)
}
else {
use serde::de::Error;
Err(Error::custom("empty input"))
}
}
fn main() {
let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
let nums: Vec<i64> = from_str(&line).unwrap();
let sum: i64 = nums.iter().sum();
println!("Sum: {}", sum);
}
struct Decoder {
nums: VecDeque<i64>,
}
impl Decoder {
fn from_str(input: String) -> Result<Self, ParseIntError> {
let nums: Result<VecDeque<i64>, ParseIntError> = input.split_whitespace().map(|word| word.parse::<i64>())
.collect();
Ok(Self {
nums: nums?,
})
}
}
impl<'de, 'a> Deserializer<'de> for &'a mut Decoder {
type Error = Error;
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de> {
visitor.visit_i64(self.nums.pop_front().unwrap())
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de> {
visitor.visit_seq(Struct { de: self })
}
fn deserialize_struct<V>(self, _name: &'static str, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!(); }
fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!(); }
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_bool<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_i16<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_i32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_u8<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_u32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_option<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_unit_struct<V>(self, _name: &'static str, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_newtype_struct<V>(self, _name: &'static str, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_tuple_struct<V>(self, _name: &'static str, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_enum<V>(self, _name: &'static str, _variants: &'static [&'static str], _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> { unimplemented!() }
}
struct Struct<'a> {
de: &'a mut Decoder,
}
impl<'de, 'a> SeqAccess<'de> for Struct<'a> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where
T: DeserializeSeed<'de>,
{
if self.de.nums.is_empty() {
return Ok(None);
}
seed.deserialize(&mut *self.de).map(Some)
}
}
Blazingly Concurrent Programmer
(wanted a proof that Rust indeed prevents data races)
extern crate rayon;
use rayon::iter::ParallelIterator;
use rayon::str::ParallelString;
use std::io::BufRead;
fn main() {
let stdin = std::io::stdin();
let line = stdin.lock().lines().next().unwrap().unwrap();
let sum: i64 =
line.par_split_whitespace()
.map(|word| word.parse::<i64>().unwrap())
.sum();
println!("Sum: {}", sum);
}
Outdated Async Rust Programmer
(learned Rust async library in 2009)
extern crate mio;
use std::io;
use mio::{Events, Poll, Ready, PollOpt, Token};
use mio::unix::EventedFd;
const STDIN_FD: i32 = 0;
const STDIN_TOKEN: Token = Token(0);
fn main() -> io::Result<()> {
let mut sum = 0;
let poll = Poll::new()?;
poll.register(&EventedFd(&STDIN_FD), STDIN_TOKEN, Ready::readable(), PollOpt::edge())?;
let mut events = Events::with_capacity(1);
'event_loop:
loop {
poll.poll(&mut events, None)?;
for event in &events {
match event.token() {
STDIN_TOKEN => {
let mut line = String::new();
std::io::stdin().read_line(&mut line).unwrap();
for word in line.split_whitespace() {
let num = word.parse::<i64>().unwrap();
sum += num;
}
break 'event_loop;
},
_ => unreachable!(),
}
}
}
println!("Sum: {}", sum);
Ok(())
}
Senior Dependenciely-Typed Rust Programmer
(learned to use all the best crates of the Rust ecosystem)
// High score (total number of dependencies): 99
#![feature(generators, proc_macro_hygiene, try_trait)]
extern crate error_chain;
extern crate futures_await as futures;
extern crate lazy_static;
extern crate rayon;
extern crate serde;
extern crate serde_derive;
extern crate tokio;
extern crate tokio_codec;
extern crate tokio_fs;
extern crate tokio_io;
extern crate tokio_threadpool;
use std::collections::VecDeque;
use std::fmt::Display;
use std::io;
use std::num::ParseIntError;
use std::option::NoneError;
use std::sync::Mutex;
use futures::prelude::{async, await};
use lazy_static::lazy_static;
use rayon::iter::ParallelIterator;
use rayon::str::ParallelString;
use serde::{Deserialize, Deserializer};
use serde::de::{self, DeserializeSeed, SeqAccess, Visitor};
use tokio::prelude::Future;
use tokio_codec::{FramedRead, LinesCodec};
use tokio_fs::{stdin, stdout};
use tokio_io::io::write_all;
use tokio_threadpool::Builder;
use error_chain::*;
lazy_static! {
static ref NUMS: Mutex<VecDeque<i64>> = Mutex::new(VecDeque::new());
}
error_chain! {
types {
Error, ErrorKind, ResultExt, Result;
}
foreign_links {
Io(io::Error);
Parse(ParseIntError);
}
errors {
Async {
description("async error")
display("useful async error")
}
EmptyVec {
description("empty vec")
display("empty vec")
}
}
}
impl From<()> for Error {
fn from((): ()) -> Self {
ErrorKind::Async.into()
}
}
impl From<NoneError> for Error {
fn from(_: NoneError) -> Self {
ErrorKind::EmptyVec.into()
}
}
impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
msg.to_string().into()
}
}
#[async]
fn future() -> Result<()> {
let stdin = FramedRead::new(stdin(), LinesCodec::new());
#[async]
for line in stdin {
let nums: Vec<i64> = from_str(&line)?;
let sum: i64 = nums.iter().sum();
await!(write_all(stdout(), format!("Sum: {}\n", sum).into_bytes()))?;
}
Ok(())
}
fn main() -> Result<()> {
let pool = Builder::new().pool_size(1).build();
pool.spawn(future().map_err(|_| ()));
pool.shutdown_on_idle().wait()?;
Ok(())
}
pub fn from_str<T>(s: &str) -> Result<T>
where for<'a> T: Deserialize<'a>,
{
let mut deserializer = Decoder::from_str(s.to_string())?;
let t = T::deserialize(&mut deserializer)?;
if NUMS.lock().unwrap().is_empty() {
Ok(t)
}
else {
Err(serde::de::Error::custom("empty input"))
}
}
struct Decoder {
}
impl Decoder {
fn from_str(input: String) -> Result<Self> {
let nums: Result<VecDeque<i64>> = input.par_split_whitespace().map(|word| word.parse::<i64>().map_err(|err| err.into()))
.collect();
*NUMS.lock().unwrap() = nums?;
Ok(Self {
})
}
}
impl<'de, 'a> Deserializer<'de> for &'a mut Decoder {
type Error = Error;
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de> {
visitor.visit_i64(NUMS.lock().unwrap().pop_front()?)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de> {
visitor.visit_seq(Struct { de: self })
}
fn deserialize_struct<V>(self, _name: &'static str, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!(); }
fn deserialize_identifier<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!(); }
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_bool<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_i8<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_i16<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_i32<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_u8<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_u16<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_u32<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_f32<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_char<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_str<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_string<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_option<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_unit_struct<V>(self, _name: &'static str, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_newtype_struct<V>(self, _name: &'static str, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_tuple_struct<V>(self, _name: &'static str, _len: usize, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_enum<V>(self, _name: &'static str, _variants: &'static [&'static str], _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value> where V: Visitor<'de> { unimplemented!() }
}
struct Struct<'a> {
de: &'a mut Decoder,
}
impl<'de, 'a> SeqAccess<'de> for Struct<'a> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<<T as serde::de::DeserializeSeed<'de>>::Value>>
where
T: DeserializeSeed<'de>,
{
if NUMS.lock().unwrap().is_empty() {
return Ok(None);
}
seed.deserialize(&mut *self.de).map(Some)
}
}
Copyright © 2019 Antoni Boucher All rights reserved