Initial commit

pull/6/head
Jim Blandy 7 years ago
commit e85d6ddfe5

@ -0,0 +1,125 @@
# Code Examples for _Programming Rust_
This repository contains complete code for the larger example programs
from the book “Programming Rust”, by Jim Blandy and Jason Orendorff.
Each subdirectory is a distinct Rust project, with its own Cargo.toml file. You
should be able to enter each directory and use `cargo build` and `cargo test`.
For those projects that define programs, `cargo run` should run them.
## Chapter 2: A Tour of Rust
- The `gcd` directory holds the command-line program for computing the greatest
common denominator of a list of numbers.
- The `iron-gcd` directory holds the code for the simple web service,
implemented using the [`iron`] framework, that computes greatest common
denominators.
- The Mandelbrot plotting program has its own repository, at
`https://github.com/ProgrammingRust/mandelbrot`. This repository contains
several branches, each showing a different implementation strategy. The
`single-threaded` branch holds the code for the single-threaded version, and
the `bands` branch holds the multi-threaded version. Chapter 19,
“Concurrency”, shows several other approaches, which appear on other branches;
see the repository's [README.md][mandel-readme] file for details.
[`iron`]: https://crates.io/crates/iron
## Chapter 8: Crates and Modules
- We did not actually write a fern simulator. Please accept our sincere apology
for this feckless deception. But the skeleton of modules and definitions we
show in the book is in the `fern_sim` subdirectory.
## Chapter 9: Structs
- The `queue` directory holds a library that defines the `Queue` type,
representing a queue of `char` values.
- The `generic-queue` directory holds code for generic `Queue` type.
## Chapter 10: Enums and Patterns
- The `binary-tree` directory holds the source code for the `BinaryTree` type
that appears in the “Generic Enums” and “Populating a Binary Tree” sections.
## Chapter 12: Operator Overloading
- The `complex` directory holds the `Complex` type used as a running example
throughout the chapter.
- The `interval` directory holds the `Interval` type for which the book
implements the `std::cmp::PartialOrd` trait.
## Chapter 14: Closures
- The 'basic-router' directory holds the `BasicRouter` type used as an example
in the “Callbacks” section.
## Chapter 15: Iterators
- The `binary-tree` directory holds the implementation of the `Iterator` trait
for the `BinaryTree` type originally defined in the “Enums and Patterns”
chapter.
## Chapter 17: Strings and Text
- The `complex` directory includes the implementation of the `std::fmt::Display`
formatting trait for a complex number type, shown in the section “Formatting
Your Own Types”.
## Chapter 18: Input and Output
- The `grep` directory holds the simple grep-like program shown in the section
“Reading Lines”.
- The `copy` directory holds the program for copying directory trees from the
section “Reading Directories”, including the additions shown in the next
section, “Platform-Specific Features”.
- The `echo-server` directory holds the simple network service shown in the
“Networking” section.
- The `http-get` directory holds the command-line program that uses the
`reqwest` crate to carry out an HTTP request.
## Chapter 19: Concurrency
- The search engine used as a running example throughout the book has its own
repository, at `https://github.com/ProgrammingRust/fingertips`.
- The Mandelbrot set plotter discussed in the section “Revisiting the Mandelbrot
Set” also has its own repository, at `https://github.com/ProgrammingRust/mandelbrot`.
The repository includes several branches exploring different implementations;
see the repository's [README.md][mandel-readme] file for details.
[mandel-readme]: https://github.com/ProgrammingRust/mandelbrot/blob/master/README.md
## Chapter 20: Macros
- The `json-macro` directory holds the definition of the `json!` macro built in
the section “The json! Macro”.
## Chapter 21: Unsafe Code
- The `ascii` directory holds the `Ascii` type used as an example in the
sections “Unsafe Blocks” and “Unsafe Functions”.
- The `ref-with-flag` directory holds the `RefWithFlag` type from the “Raw
Pointers” section.
- The `gap-buffer` directory holds the `GapBuffer` type, used in the “Raw
Pointers” section to illustrate pointer arithmetic and `std::ptr::read` and
`std::ptr::write`.
- The `libgit2-rs` and `libgit2-rs-safe` directories contain the two versions of
the program that uses Rust's foreign function interface to call functions from
the `libgit2` C library. The version in `libgit2-rs` is written as a single
giant block of unsafe code, whereas the version in `libgit2-rs-safe`
implements a safe Rust interface to the same functionality, using Rust's type
system to enforce libgit2's rules for proper use of the library.
Note that both of these require you to have a copy of `libgit2` present on
your system. The chapter provides detailed instructions for building the
correct version, for Linux, macOS, and Microsoft Windows.

1
ascii/.gitignore vendored

@ -0,0 +1 @@
target

4
ascii/Cargo.lock generated

@ -0,0 +1,4 @@
[[package]]
name = "ascii"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "ascii"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,101 @@
mod my_ascii {
use std::ascii::AsciiExt; // for u8::is_ascii
/// An ASCII-encoded string.
#[derive(Debug, Eq, PartialEq)]
pub struct Ascii(
// This must hold only well-formed ASCII text:
// bytes from `0` to `0x7f`.
Vec<u8>
);
impl Ascii {
/// Create an `Ascii` from the ASCII text in `bytes`. Return a
/// `NotAsciiError` error if `bytes` contains any non-ASCII
/// characters.
pub fn from_bytes(bytes: Vec<u8>) -> Result<Ascii, NotAsciiError> {
if bytes.iter().any(|&byte| !byte.is_ascii()) {
return Err(NotAsciiError(bytes));
}
Ok(Ascii(bytes))
}
}
// When conversion fails, we give back the vector we couldn't convert.
// This should implement `std::error::Error`; omitted for brevity.
#[derive(Debug, Eq, PartialEq)]
pub struct NotAsciiError(pub Vec<u8>);
// Safe, efficient conversion, implemented using unsafe code.
impl From<Ascii> for String {
fn from(ascii: Ascii) -> String {
// If this module has no bugs, this is safe, because
// well-formed ASCII text is also well-formed UTF-8.
unsafe {
String::from_utf8_unchecked(ascii.0)
}
}
}
impl From<Ascii> for Vec<u8> {
fn from(ascii: Ascii) -> Vec<u8> { ascii.0 }
}
// This must be placed inside the `my_ascii` module.
impl Ascii {
/// Construct an `Ascii` value from `bytes`, without checking
/// whether `bytes` actually contains well-formed ASCII.
///
/// This constructor is infallible, and returns an `Ascii` directly,
/// rather than a `Result<Ascii, NotAsciiError>` as the `from_bytes`
/// constructor does.
///
/// # Safety
///
/// The caller must ensure that `bytes` contains only ASCII
/// characters: bytes no greater than 0x7f. Otherwise, the effect is
/// undefined.
pub unsafe fn from_bytes_unchecked(bytes: Vec<u8>) -> Ascii {
Ascii(bytes)
}
}
}
#[test]
fn good_ascii() {
use self::my_ascii::Ascii;
let bytes: Vec<u8> = b"ASCII and ye shall receive".to_vec();
// This call entails no allocation or text copies, just a scan.
let ascii: Ascii = Ascii::from_bytes(bytes)
.unwrap(); // We know these chosen bytes are legit.
// This call is zero-cost: no allocation, copies, or scans.
let string = String::from(ascii);
assert_eq!(string, "ASCII and ye shall receive");
}
#[test]
fn bad_ascii() {
use self::my_ascii::Ascii;
// Imagine that this vector is the result of some complicated process
// that we expected to produce ASCII. Something went wrong!
let bytes = vec![0xf7, 0xbf, 0xbf, 0xbf];
let ascii = unsafe {
// This unsafe function's contract is violated
// when `bytes` holds non-ASCII bytes.
Ascii::from_bytes_unchecked(bytes)
};
let bogus: String = ascii.into();
// `bogus` now holds ill-formed UTF-8. Parsing its first character
// produces a `char` that is not a valid Unicode code point.
assert_eq!(bogus.chars().next().unwrap() as u32, 0x1fffff);
}

@ -0,0 +1 @@
target

@ -0,0 +1,4 @@
[[package]]
name = "basic-router"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "basic-router"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,89 @@
#![allow(dead_code)]
use std::collections::HashMap;
struct Request {
method: String,
url: String,
headers: HashMap<String, String>,
body: Vec<u8>
}
struct Response {
code: u32,
headers: HashMap<String, String>,
body: Vec<u8>
}
type BoxedCallback = Box<Fn(&Request) -> Response>;
struct BasicRouter {
routes: HashMap<String, BoxedCallback>
}
impl BasicRouter {
// Create an empty router.
fn new() -> BasicRouter {
BasicRouter { routes: HashMap::new() }
}
// Add a route to the router.
fn add_route<C>(&mut self, url: &str, callback: C)
where C: Fn(&Request) -> Response + 'static
{
self.routes.insert(url.to_string(), Box::new(callback));
}
}
impl BasicRouter {
fn handle_request(&self, request: &Request) -> Response {
match self.routes.get(&request.url) {
None => not_found_response(),
Some(callback) => callback(request)
}
}
}
fn not_found_response() -> Response {
Response {
code: 404,
headers: HashMap::new(),
body: b"<h1>Page not found</h1>".to_vec()
}
}
fn get_form_response() -> Response {
Response {
code: 200,
headers: HashMap::new(),
body: b"<form>".to_vec()
}
}
fn get_gcd_response(_req: &Request) -> Response {
Response {
code: 500,
headers: HashMap::new(),
body: b"<h1>Internal server error</h1>".to_vec()
}
}
fn req(url: &str) -> Request {
Request {
method: "GET".to_string(),
url: url.to_string(),
headers: HashMap::new(),
body: vec![]
}
}
#[test]
fn test_router() {
let mut router = BasicRouter::new();
router.add_route("/", |_| get_form_response());
router.add_route("/gcd", |req| get_gcd_response(req));
assert_eq!(router.handle_request(&req("/piano")).code, 404);
assert_eq!(router.handle_request(&req("/")).code, 200);
assert_eq!(router.handle_request(&req("/gcd")).code, 500);
}

@ -0,0 +1 @@
target

@ -0,0 +1,48 @@
[[package]]
name = "binary-tree"
version = "0.1.0"
dependencies = [
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fuchsia-zircon"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"

@ -0,0 +1,7 @@
[package]
name = "binary-tree"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]
rand = "0.3.14"

@ -0,0 +1,286 @@
#![allow(dead_code)]
extern crate rand;
// An ordered collection of `T`s.
enum BinaryTree<T> {
Empty,
NonEmpty(Box<TreeNode<T>>)
}
// A part of a BinaryTree.
struct TreeNode<T> {
element: T,
left: BinaryTree<T>,
right: BinaryTree<T>
}
#[test]
fn binary_tree_size() {
use std::mem::size_of;
let word = size_of::<usize>();
assert_eq!(size_of::<BinaryTree<String>>(), word);
type Triple = (&'static str, BinaryTree<&'static str>, BinaryTree<&'static str>);
assert_eq!(size_of::<Triple>(), 4 * word);
}
#[test]
fn test_hand_building_tree_of_planets() {
use self::BinaryTree::*;
let jupiter_tree = NonEmpty(Box::new(TreeNode {
element: "Jupiter",
left: Empty,
right: Empty
}));
let mercury_tree = NonEmpty(Box::new(TreeNode {
element: "Mercury",
left: Empty,
right: Empty
}));
let mars_tree = NonEmpty(Box::new(TreeNode {
element: "Mars",
left: jupiter_tree,
right: mercury_tree
}));
let venus_tree = NonEmpty(Box::new(TreeNode {
element: "Venus",
left: Empty,
right: Empty
}));
let uranus_tree = NonEmpty(Box::new(TreeNode {
element: "Uranus",
left: Empty,
right: venus_tree
}));
let tree = NonEmpty(Box::new(TreeNode {
element: "Saturn",
left: mars_tree,
right: uranus_tree
}));
assert_eq!(tree.walk(),
vec!["Jupiter", "Mars", "Mercury", "Saturn", "Uranus", "Venus"]);
}
impl<T: Clone> BinaryTree<T> {
fn walk(&self) -> Vec<T> {
match *self {
BinaryTree::Empty => vec![],
BinaryTree::NonEmpty(ref boxed) => {
let mut result = boxed.left.walk();
result.push(boxed.element.clone());
result.extend(boxed.right.walk());
result
}
}
}
}
impl<T: Ord> BinaryTree<T> {
fn add(&mut self, value: T) {
match *self {
BinaryTree::Empty =>
*self = BinaryTree::NonEmpty(Box::new(TreeNode {
element: value,
left: BinaryTree::Empty,
right: BinaryTree::Empty
})),
BinaryTree::NonEmpty(ref mut node) =>
if value <= node.element {
node.left.add(value);
} else {
node.right.add(value);
}
}
}
}
#[test]
fn test_add_method_1() {
let planets = vec!["Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus"];
let mut tree = BinaryTree::Empty;
for planet in planets {
tree.add(planet);
}
assert_eq!(tree.walk(),
vec!["Jupiter", "Mars", "Mercury", "Saturn", "Uranus", "Venus"]);
}
#[test]
fn test_add_method_2() {
let mut tree = BinaryTree::Empty;
tree.add("Mercury");
tree.add("Venus");
for planet in vec!["Mars", "Jupiter", "Saturn", "Uranus"] {
tree.add(planet);
}
assert_eq!(tree.walk(),
vec!["Jupiter", "Mars", "Mercury", "Saturn", "Uranus", "Venus"]);
}
use self::BinaryTree::*;
// The state of an in-order traversal of a `BinaryTree`.
struct TreeIter<'a, T: 'a> {
// A stack of references to tree nodes. Since we use `Vec`'s
// `push` and `pop` methods, the top of the stack is the end of the
// vector.
//
// The node the iterator will visit next is at the top of the stack,
// with those ancestors still unvisited below it. If the stack is empty,
// the iteration is over.
unvisited: Vec<&'a TreeNode<T>>
}
impl<'a, T: 'a> TreeIter<'a, T> {
fn push_left_edge(&mut self, mut tree: &'a BinaryTree<T>) {
while let NonEmpty(ref node) = *tree {
self.unvisited.push(node);
tree = &node.left;
}
}
}
impl<T> BinaryTree<T> {
fn iter(&self) -> TreeIter<T> {
let mut iter = TreeIter { unvisited: Vec::new() };
iter.push_left_edge(self);
iter
}
}
impl<'a, T: 'a> IntoIterator for &'a BinaryTree<T> {
type Item = &'a T;
type IntoIter = TreeIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> Iterator for TreeIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
// Find the node this iteration must produce,
// or finish the iteration.
let node = match self.unvisited.pop() {
None => return None,
Some(n) => n
};
// The next node after this one is the leftmost child of
// this node's right child, so push the path from here down.
self.push_left_edge(&node.right);
// Produce a reference to this node's value.
Some(&node.element)
}
}
#[test]
fn external_iterator() {
fn make_node<T>(left: BinaryTree<T>, element: T, right: BinaryTree<T>)
-> BinaryTree<T>
{
NonEmpty(Box::new(TreeNode { left, element, right }))
}
// Build a small tree.
let subtree_l = make_node(Empty, "mecha", Empty);
let subtree_rl = make_node(Empty, "droid", Empty);
let subtree_r = make_node(subtree_rl, "robot", Empty);
let tree = make_node(subtree_l, "Jaeger", subtree_r);
// Iterate over it.
let mut v = Vec::new();
for kind in &tree {
v.push(*kind);
}
assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]);
let left_subtree = make_node(Empty, "mecha", Empty);
let right_subtree = make_node(make_node(Empty, "droid", Empty),
"robot",
Empty);
let tree = make_node(left_subtree, "Jaeger", right_subtree);
let mut v = Vec::new();
let mut iter = TreeIter { unvisited: vec![] };
iter.push_left_edge(&tree);
for kind in iter {
v.push(*kind);
}
assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]);
let mut v = Vec::new();
for kind in &tree {
v.push(*kind);
}
assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]);
let mut v = Vec::new();
let mut state = tree.into_iter();
while let Some(kind) = state.next() {
v.push(*kind);
}
assert_eq!(v, ["mecha", "Jaeger", "droid", "robot"]);
assert_eq!(tree.iter()
.map(|name| format!("mega-{}", name))
.collect::<Vec<_>>(),
vec!["mega-mecha", "mega-Jaeger",
"mega-droid", "mega-robot"]);
let mut iterator = tree.into_iter();
assert_eq!(iterator.next(), Some(&"mecha"));
assert_eq!(iterator.next(), Some(&"Jaeger"));
assert_eq!(iterator.next(), Some(&"droid"));
assert_eq!(iterator.next(), Some(&"robot"));
assert_eq!(iterator.next(), None);
}
#[test]
fn other_cloned() {
use std::collections::BTreeSet;
let mut set = BTreeSet::new();
set.insert("mecha");
set.insert("Jaeger");
set.insert("droid");
set.insert("robot");
assert_eq!(set.iter().cloned().collect::<Vec<_>>(),
["Jaeger", "droid", "mecha", "robot"]);
}
#[test]
fn fuzz() {
fn make_random_tree(p: f32) -> BinaryTree<i32> {
use rand::{ThreadRng, thread_rng};
use rand::distributions::range::Range;
use rand::distributions::Sample;
fn make(p: f32, next: &mut i32, rng: &mut ThreadRng) -> BinaryTree<i32> {
let mut range = Range::new(0.0, 1.0);
if range.sample(rng) > p {
Empty
} else {
let left = make(p * p, next, rng);
let element = *next;
*next += 1;
let right = make(p * p, next, rng);
NonEmpty(Box::new(TreeNode { left, element, right }))
}
}
make(p, &mut 0, &mut thread_rng())
}
for _ in 0..100 {
let tree = make_random_tree(0.9999);
assert!(tree.into_iter().fold(Some(0), |s, &i| {
s.and_then(|expected| if i == expected { Some(expected+1) } else { None })
}).is_some());
}
}

@ -0,0 +1 @@
target

4
complex/Cargo.lock generated

@ -0,0 +1,4 @@
[[package]]
name = "complex"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "complex"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,192 @@
#[derive(Clone, Copy, Debug)]
struct Complex<T> {
/// Real portion of the complex number
re: T,
/// Imaginary portion of the complex number
im: T
}
use std::ops::Add;
use std::ops::Mul;
#[cfg(skip)]
impl Add for Complex<i32> {
type Output = Complex<i32>;
fn add(self, rhs: Self) -> Self {
Complex { re: self.re + rhs.re, im: self.im + rhs.im }
}
}
impl<T> Add for Complex<T>
where T: Add<Output=T>
{
type Output = Self;
fn add(self, rhs: Self) -> Self {
Complex { re: self.re + rhs.re, im: self.im + rhs.im }
}
}
#[cfg(skip)]
impl<L, R, O> Add<Complex<R>> for Complex<L>
where L: Add<R, Output=O>
{
type Output = Complex<O>;
fn add(self, rhs: Complex<R>) -> Self::Output {
Complex { re: self.re + rhs.re, im: self.im + rhs.im }
}
}
#[cfg(skip)]
impl<'a, P, Rhs> Add for &'a Complex<P>
where P: Add<Output=P>,
Rhs: AsRef<Complex<P>>
{
type Output = Complex<P>;
fn add(self, rhs: Rhs) -> Self::Output {
let rhs = rhs.as_ref();
Complex { re: self.re + rhs.re, im: self.im + rhs.im }
}
}
use std::ops::Sub;
impl<T> Mul<Complex<T>> for Complex<T>
where T: Add<Output=T> + Sub<Output=T> + Mul<Output=T> + Copy
{
type Output = Self;
fn mul(self, rhs: Self) -> Self {
Complex { re: self.re * rhs.re - self.im * rhs.im,
im: self.re * rhs.im + self.im * rhs.re }
}
}
#[test]
fn test() {
let z = Complex { re: -2, im: 6 };
let c = Complex { re: 1, im: 2 };
assert_eq!(z + c, Complex { re: -1, im: 8 });
assert_eq!(z * c, Complex { re: -14, im: 2 });
assert_eq!(z.add(c), Complex { re: -1, im: 8 });
}
#[test]
fn test_explicit() {
use std::ops::Add;
assert_eq!(4.125f32.add(5.75), 9.875);
assert_eq!(10.add(20), 10 + 20);
}
impl Add<Complex<f64>> for f64 {
type Output = Complex<f64>;
fn add(self, rhs: Complex<f64>) -> Complex<f64> {
Complex { re: rhs.re + self, im: rhs.im }
}
}
#[test]
fn add_complex_to_real() {
assert_eq!(30f64 + Complex { re: 10.0f64, im: 20.0 },
Complex { re: 40.0, im: 20.0 });
}
use std::ops::Neg;
impl<T, O> Neg for Complex<T>
where T: Neg<Output=O>
{
type Output = Complex<O>;
fn neg(self) -> Complex<O> {
Complex { re: -self.re, im: -self.im }
}
}
#[test]
fn negate_complex() {
let z = Complex { re: 3, im: 4 };
assert_eq!(-z, Complex { re: -3, im: -4 });
}
use std::ops::AddAssign;
impl<T> AddAssign for Complex<T>
where T: AddAssign<T>
{
fn add_assign(&mut self, rhs: Complex<T>) {
self.re += rhs.re;
self.im += rhs.im;
}
}
#[test]
fn compound_assignment() {
let mut z = Complex { re: 5, im: 6 };
z += Complex { re: 7, im: 8 };
assert_eq!(z, Complex { re: 12, im: 14 });
let mut title = "Love".to_string();
title += ", Actually";
assert_eq!(title, "Love, Actually");
}
impl<T: PartialEq> PartialEq for Complex<T> {
fn eq(&self, other: &Complex<T>) -> bool {
self.re == other.re && self.im == other.im
}
}
impl<T: Eq> Eq for Complex<T> { }
#[test]
fn comparison() {
let x = Complex { re: 5, im: 2 };
let y = Complex { re: 2, im: 5 };
assert_eq!(x * y, Complex { re: 0, im: 29 });
}
use std::fmt;
// To make the formatting examples mesh with the rest of this file, I've adapted
// them to work on the type `Complex<f64>`, where the book simply defines a new
// non-generic `Complex` type. The only changes are adding `<f64>`, and changing
// the field names.
#[cfg(skip)]
impl fmt::Display for Complex<f64> {
fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
let i_sign = if self.i < 0.0 { '-' } else { '+' };
write!(dest, "{} {} {}i", self.r, i_sign, f64::abs(self.i))
}
}
impl fmt::Display for Complex<f64> {
fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
let (r, i) = (self.re, self.im);
if dest.alternate() {
let abs = f64::sqrt(r * r + i * i);
let angle = f64::atan2(i, r) / std::f64::consts::PI * 180.0;
write!(dest, "{} ∠ {}°", abs, angle)
} else {
let i_sign = if i < 0.0 { '-' } else { '+' };
write!(dest, "{} {} {}i", r, i_sign, f64::abs(i))
}
}
}
#[test]
fn custom_display_impl() {
let one_twenty = Complex { re: -0.5, im: 0.866 };
assert_eq!(format!("{}", one_twenty),
"-0.5 + 0.866i");
let two_forty = Complex { re: -0.5, im: -0.866 };
assert_eq!(format!("{}", two_forty),
"-0.5 - 0.866i");
let ninety = Complex { re: 0.0, im: 2.0 };
assert_eq!(format!("{}", ninety),
"0 + 2i");
assert_eq!(format!("{:#}", ninety),
"2 ∠ 90°");
}

1
copy/.gitignore vendored

@ -0,0 +1 @@
target

4
copy/Cargo.lock generated

@ -0,0 +1,4 @@
[[package]]
name = "copy"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "copy"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,110 @@
use std::fs;
use std::io;
use std::path::Path;
/// Copy the existing directory `src` to the target path `dst`.
fn copy_dir_to(src: &Path, dst: &Path) -> io::Result<()> {
if !dst.is_dir() {
fs::create_dir(dst)?;
}
for entry_result in src.read_dir()? {
let entry = entry_result?;
let file_type = entry.file_type()?;
copy_to(&entry.path(), &file_type, &dst.join(entry.file_name()))?;
}
Ok(())
}
#[cfg(unix)]
use std::os::unix::fs::symlink;
/// Stub implementation of `symlink` for platforms that don't provide it.
#[cfg(not(unix))]
fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, _dst: Q) -> std::io::Result<()> {
Err(io::Error::new(io::ErrorKind::Other,
format!("can't copy symbolic link: {}",
src.as_ref().display())))
}
/// Copy whatever is at `src` to the target path `dst`.
fn copy_to(src: &Path, src_type: &fs::FileType, dst: &Path) -> io::Result<()> {
if src_type.is_file() {
fs::copy(src, dst)?;
} else if src_type.is_dir() {
copy_dir_to(src, dst)?;
} else if src_type.is_symlink() {
let target = src.read_link()?;
symlink(target, dst)?;
} else {
return Err(io::Error::new(io::ErrorKind::Other,
format!("don't know how to copy: {}",
src.display())));
}
Ok(())
}
fn copy_into<P, Q>(source: P, destination: Q) -> io::Result<()>
where P: AsRef<Path>,
Q: AsRef<Path>
{
let src = source.as_ref();
let dst = destination.as_ref();
match src.file_name() {
None => {
return Err(io::Error::new(io::ErrorKind::Other,
format!("can't copy nameless directory: {}",
src.display())));
}
Some(src_name) => {
let md = src.metadata()?;
copy_to(src, &md.file_type(), &dst.join(src_name))?;
}
}
Ok(())
}
fn dwim_copy<P, Q>(source: P, destination: Q) -> io::Result<()>
where P: AsRef<Path>,
Q: AsRef<Path>
{
let src = source.as_ref();
let dst = destination.as_ref();
if dst.is_dir() {
copy_into(src, dst)
} else {
let md = src.metadata()?;
copy_to(src, &md.file_type(), dst)
}
}
fn copy_main() -> io::Result<()> {
let args = std::env::args_os().collect::<Vec<_>>();
if args.len() < 3 {
println!("usage: copy FILE... DESTINATION");
} else if args.len() == 3 {
dwim_copy(&args[1], &args[2])?;
} else {
let dst = Path::new(&args[args.len() - 1]);
if !dst.is_dir() {
return Err(io::Error::new(io::ErrorKind::Other,
format!("target '{}' is not a directory",
dst.display())));
}
for i in 1 .. args.len() - 1 {
copy_into(&args[i], dst)?;
}
}
Ok(())
}
fn main() {
use std::io::Write;
if let Err(err) = copy_main() {
writeln!(io::stderr(), "error: {}", err).unwrap();
}
}

@ -0,0 +1 @@
target

@ -0,0 +1,4 @@
[[package]]
name = "echo-server"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "echo-server"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,27 @@
use std::net::TcpListener;
use std::io;
use std::thread::spawn;
/// Accept connections forever, spawning a thread for each one.
fn echo_main(addr: &str) -> io::Result<()> {
let listener = TcpListener::bind(addr)?;
println!("listening on {}", addr);
loop {
// Wait for a client to connect.
let (mut stream, addr) = listener.accept()?;
println!("connection received from {}", addr);
// Spawn a thread to handle this client.
let mut write_stream = stream.try_clone()?;
spawn(move || {
// Echo everything we receive from `stream` back to it.
io::copy(&mut stream, &mut write_stream)
.expect("error in client thread: ");
println!("connection closed");
});
}
}
fn main() {
echo_main("127.0.0.1:17007").expect("error: ");
}

@ -0,0 +1 @@
target

@ -0,0 +1,4 @@
[[package]]
name = "fern_sim"
version = "0.1.0"

@ -0,0 +1,13 @@
[package]
name = "fern_sim"
version = "0.1.0"
authors = ["You <you@example.com>"]
license = "MIT"
homepage = "https://fernsim.example.com/"
repository = "https://git.example.com/fernsim"
documentation = "http://fernsim.example.com/docs"
description = """
Fern simulation, from the cellular level up.
"""
[dependencies]

@ -0,0 +1,12 @@
//! The simulation of biological cells, which is as low-level as we go.
pub struct Cell {
x: f64,
y: f64
}
impl Cell {
pub fn distance_from_origin(&self) -> f64 {
f64::hypot(self.x, self.y)
}
}

@ -0,0 +1,13 @@
//! Simulate the growth of ferns, from the level of
//! individual cells on up.
pub mod cells;
pub mod plant_structures;
pub mod simulation;
pub mod spores;
pub use plant_structures::Fern;
pub use simulation::Terrarium;
pub mod net;
pub use net::connect;

@ -0,0 +1,17 @@
pub struct Session;
pub fn connect() -> Session {
Session
}
impl Session {
/// Upload all local terrariums to the online gallery.
///
/// ```no_run
/// let mut session = fern_sim::connect();
/// session.upload_all();
/// ```
pub fn upload_all(&mut self) {
unimplemented!();
}
}

@ -0,0 +1,6 @@
#![allow(dead_code)]
//! Simulation of individual leaves (for the formation of leaves, see `stem`).
pub struct Leaf {
x: bool
}

@ -0,0 +1,45 @@
//! Higher-level biological structures.
//!
//! We always simulate a sample of all chemical interactions at the cellular
//! level, but simulating everything that way is just too computationally
//! expensive. Therefore we keep higher-level data structures representing
//! each fern's roots, leaves, and so on. When we simulate physics (light, air
//! currents, gravity) we always use these structures as shorthand for the
//! millions of cells they typically represent. On a more morbid note, these
//! structures stick around when stuff dies, so that dead fronds have weight,
//! cast shadows, and so on.
// in plant_structures/mod.rs
pub mod roots;
pub mod stems;
pub mod leaves;
pub use self::leaves::Leaf;
pub use self::roots::Root;
use self::roots::RootSet;
use self::stems::StemSet;
pub enum FernType {
Fiddlehead
}
pub struct Fern {
pub roots: RootSet,
pub stems: StemSet
}
impl Fern {
pub fn new(_type: FernType) -> Fern {
Fern {
roots: vec![],
stems: vec![stems::Stem { furled: true }]
}
}
pub fn is_furled(&self) -> bool { !self.is_fully_unfurled() }
pub fn is_fully_unfurled(&self) -> bool {
self.stems.iter().all(|s| !s.furled)
}
}

@ -0,0 +1,7 @@
#![allow(dead_code)]
pub struct Root {
x: bool
}
pub type RootSet = Vec<Root>;

@ -0,0 +1,10 @@
//! Stems hold the weight of the plant and are largely responsible for its
//! shape. Parameters on `Stem` (not `Leaf`) are responsible for pinnation,
//! the feathery leaf structure that's the most immediately recognizable
//! property of ferns.
pub struct Stem {
pub furled: bool
}
pub type StemSet = Vec<Stem>;

@ -0,0 +1,52 @@
//! Overall simulation control.
//!
//! The simulation algorithm is complex and has a lot of tweakable parameters.
use std::fs::File;
use std::time::Duration;
use plant_structures::{Fern, FernType};
/// The simulated universe.
pub struct Terrarium {
ferns: Vec<Fern>
}
impl Terrarium {
/// Create a new empty terrarium.
pub fn new() -> Terrarium {
Terrarium { ferns: vec![] }
}
/// Load a terrarium from a `.tm` file.
pub fn load(filename: &str) -> Terrarium {
// This implementation is, like everything else in here, completely bogus
File::open(filename).unwrap(); // check that the file is there
Terrarium {
ferns: vec![
Fern::new(FernType::Fiddlehead)
]
}
}
/// Get a reference to a fern inside the simulation.
pub fn fern(&self, index: usize) -> &Fern {
&self.ferns[index]
}
#[allow(unused_variables)]
/// Let the sun shine in and run the simulation for a given
/// amount of time.
///
/// # use fern_sim::Terrarium;
/// # use std::time::Duration;
/// # let mut tm = Terrarium::new();
/// tm.apply_sunlight(Duration::from_secs(60));
///
pub fn apply_sunlight(&mut self, time: Duration) {
for f in &mut self.ferns {
for s in &mut f.stems {
s.furled = false;
}
}
}
}

@ -0,0 +1,28 @@
#![allow(dead_code, unused_variables)]
//! Fern reproduction.
use cells::Cell;
/// A cell made by an adult fern. It disperses on the wind as part of
/// the fern life cycle. A spore grows into a prothallus -- a whole
/// separate organism, up to 5mm across -- which produces a zygote,
/// which becomes a new fern. (Plant sex is complicated.)
pub struct Spore {
x: bool
}
/// A compartment, usually on the bottom of a leaf, where spores form.
pub struct Sporangium {
x: bool
}
/// Simulate the production of a spore by meiosis.
pub fn produce_spore(factory: &mut Sporangium) -> Spore {
Spore { x: false }
}
/// Mix genes to prepare for meiosis (part of interphase).
fn recombine(parent: &mut Cell) {
}

@ -0,0 +1,14 @@
// tests/unfurl.rs - Fiddleheads unfurl in sunlight
extern crate fern_sim;
use fern_sim::Terrarium;
use std::time::Duration;
#[test]
fn test_fiddlehead_unfurling() {
let mut world = Terrarium::load("tests/unfurl_files/fiddlehead.tm");
assert!(world.fern(0).is_furled());
let one_hour = Duration::from_secs(60 * 60);
world.apply_sunlight(one_hour);
assert!(world.fern(0).is_fully_unfurled());
}

@ -0,0 +1 @@
target

@ -0,0 +1,4 @@
[[package]]
name = "gap-buffer"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "gap-buffer"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,312 @@
#![allow(dead_code)]
mod gap {
use std;
use std::ops::Range;
/// A GapBuffer<T> is a sequence of elements of type `T` that can insert and
/// remove elements at any position in constant time. Indexing is also constant
/// time. However, changing the position at which insertion and removal occur
/// takes time proportional to the distance the insertion position is being
/// moved.
pub struct GapBuffer<T> {
// Storage for elements. This has the capacity we need, but its length
// always remains zero. GapBuffer puts its elements and the gap in this
// `Vec`'s "unused" capacity.
storage: Vec<T>,
// Range of uninitialized elements in the middle of `storage`.
// Elements before and after this range are always initialized.
gap: Range<usize>
}
impl<T> GapBuffer<T> {
pub fn new() -> GapBuffer<T> {
GapBuffer { storage: Vec::new(), gap: 0..0 }
}
/// Return the number of elements this GapBuffer could hold without
/// reallocation.
pub fn capacity(&self) -> usize {
self.storage.capacity()
}
/// Return the number of elements this GapBuffer currently holds.
pub fn len(&self) -> usize {
self.capacity() - self.gap.len()
}
/// Return the current insertion position.
pub fn position(&self) -> usize {
self.gap.start
}
/// Return a pointer to the `index`'th element of the underlying storage,
/// as if the gap were not there.
///
/// Safety: `index` must be less than self.capacity().
unsafe fn space(&self, index: usize) -> *const T {
self.storage.as_ptr().offset(index as isize)
}
/// Return a mutable pointer to the `index`'th element of the underlying
/// storage, as if the gap were not there.
///
/// Safety: `index` must be less than self.capacity().
unsafe fn space_mut(&mut self, index: usize) -> *mut T {
self.storage.as_mut_ptr().offset(index as isize)
}
/// Return the offset in the buffer of the `index`'th element, taking
/// the gap into account. This does not check whether index is in range,
/// but it never returns the index of space in the gap.
fn index_to_raw(&self, index: usize) -> usize {
if index < self.gap.start {
index
} else {
index + self.gap.len()
}
}
/// Return a reference to the `index`'th element,
/// or `None` if `index` is out of bounds.
pub fn get(&self, index: usize) -> Option<&T> {
let raw = self.index_to_raw(index);
if raw < self.capacity() {
unsafe {
// We just checked `raw` against self.capacity(),
// and index_to_raw skips the gap, so this is safe.
Some(&*self.space(raw))
}
} else {
None
}
}
/// Set the current insertion position to `pos`.
/// If `pos` is out of bounds, panic.
pub fn set_position(&mut self, pos: usize) {
if pos > self.len() {
panic!("index {} out of range for GapBuffer", pos);
}
unsafe {
let gap = self.gap.clone();
if pos > gap.start {
// `pos` falls after the gap. Move the gap right
// by shifting elements after the gap to before it.
let distance = pos - gap.start;
std::ptr::copy(self.space(gap.end),
self.space_mut(gap.start),
distance);
} else if pos < gap.start {
// `pos` falls before the gap. Move the gap left
// by shifting elements before the gap to after it.
let distance = gap.start - pos;
std::ptr::copy(self.space(pos),
self.space_mut(gap.end - distance),
distance);
}
self.gap = pos .. pos + gap.len();
}
}
/// Insert `elt` at the current insertion position,
/// and leave the insertion position after it.
pub fn insert(&mut self, elt: T) {
if self.gap.len() == 0 {
self.enlarge_gap();
}
unsafe {
let index = self.gap.start;
std::ptr::write(self.space_mut(index), elt);
}
self.gap.start += 1;
}
/// Insert the elements produced by `iter` at the current insertion
/// position, and leave the insertion position after them.
pub fn insert_iter<I>(&mut self, iterable: I)
where I: IntoIterator<Item=T>
{
for item in iterable {
self.insert(item)
}
}
/// Remove the element just after the insertion position
/// and return it, or return `None` if the insertion position
/// is at the end of the GapBuffer.
pub fn remove(&mut self) -> Option<T> {
if self.gap.end == self.capacity() {
return None;
}
let element = unsafe {
std::ptr::read(self.space(self.gap.end))
};
self.gap.end += 1;
Some(element)
}
/// Double the capacity of `self.storage`.
fn enlarge_gap(&mut self) {
let mut new_capacity = self.capacity() * 2;
if new_capacity == 0 {
// The existing vector is empty.
// Choose a reasonable starting capacity.
new_capacity = 4;
}
// We have no idea what resizing a Vec does with its "unused"
// capacity. So just create a new vector and move over the elements.
let mut new = Vec::with_capacity(new_capacity);
let after_gap = self.capacity() - self.gap.end;
let new_gap = self.gap.start .. new.capacity() - after_gap;
unsafe {
// Move the elements that fall before the gap.
std::ptr::copy_nonoverlapping(self.space(0),
new.as_mut_ptr(),
self.gap.start);
// Move the elements that fall after the gap.
let new_gap_end = new.as_mut_ptr().offset(new_gap.end as isize);
std::ptr::copy_nonoverlapping(self.space(self.gap.end),
new_gap_end,
after_gap);
}
// This frees the old Vec, but drops no elements,
// because the Vec's length is zero.
self.storage = new;
self.gap = new_gap;
}
}
impl<T> Drop for GapBuffer<T> {
fn drop(&mut self) {
unsafe {
for i in 0 .. self.gap.start {
std::ptr::drop_in_place(self.space_mut(i));
}
for i in self.gap.end .. self.capacity() {
drop(std::ptr::read(self.space(i)));
}
}
}
}
pub struct Iter<'a, T: 'a> {
buffer: &'a GapBuffer<T>,
pos: usize
}
impl<'a, T: 'a> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
if self.pos >= self.buffer.len() {
None
} else {
self.pos += 1;
self.buffer.get(self.pos - 1)
}
}
}
impl<'a, T: 'a> IntoIterator for &'a GapBuffer<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
Iter { buffer: self, pos: 0 }
}
}
impl GapBuffer<char> {
pub fn get_string(&self) -> String {
let mut text = String::new();
text.extend(self);
text
}
}
use std::fmt;
impl<T: fmt::Debug> fmt::Debug for GapBuffer<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let indices = (0..self.gap.start).chain(self.gap.end .. self.capacity());
let elements = indices.map(|i| unsafe { &*self.space(i) });
f.debug_list().entries(elements).finish()
}
}
}
mod gap_tests {
#[test]
fn test() {
use gap::GapBuffer;
let mut buf = GapBuffer::new();
buf.insert_iter("Lord of the Rings".chars());
buf.set_position(12);
buf.insert_iter("Onion ".chars());
assert_eq!(buf.get_string(), "Lord of the Onion Rings");
}
#[test]
fn misc() {
use gap::GapBuffer;
let mut gb = GapBuffer::new();
println!("{:?}", gb);
gb.insert("foo".to_string());
println!("{:?}", gb);
gb.insert("bar".to_string());
println!("{:?}", gb);
gb.insert("baz".to_string());
println!("{:?}", gb);
gb.insert("qux".to_string());
println!("{:?}", gb);
gb.insert("quux".to_string());
println!("{:?}", gb);
gb.set_position(2);
assert_eq!(gb.remove(), Some("baz".to_string()));
println!("{:?}", gb);
assert_eq!(gb.remove(), Some("qux".to_string()));
println!("{:?}", gb);
assert_eq!(gb.remove(), Some("quux".to_string()));
println!("{:?}", gb);
assert_eq!(gb.remove(), None);
println!("{:?}", gb);
gb.insert("quuux".to_string());
println!("{:?}", gb);
gb.set_position(0);
assert_eq!(gb.remove(), Some("foo".to_string()));
println!("{:?}", gb);
assert_eq!(gb.remove(), Some("bar".to_string()));
println!("{:?}", gb);
assert_eq!(gb.remove(), Some("quuux".to_string()));
println!("{:?}", gb);
assert_eq!(gb.remove(), None);
println!("{:?}", gb);
}
#[test]
fn drop_elements() {
use gap::GapBuffer;
let mut gb = GapBuffer::new();
gb.insert("foo".to_string());
gb.insert("bar".to_string());
gb.set_position(1);
}
}

1
gcd/.gitignore vendored

@ -0,0 +1 @@
target

4
gcd/Cargo.lock generated

@ -0,0 +1,4 @@
[[package]]
name = "gcd"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "gcd"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,46 @@
fn gcd(mut n: u64, mut m: u64) -> u64 {
assert!(n != 0 && m != 0);
while m != 0 {
if m < n {
let t = m;
m = n;
n = t;
}
m = m % n;
}
n
}
#[test]
fn test_gcd() {
assert_eq!(gcd(14, 15), 1);
assert_eq!(gcd(2 * 3 * 5 * 11 * 17,
3 * 7 * 11 * 13 * 19),
3 * 11);
}
use std::io::Write;
use std::str::FromStr;
fn main() {
let mut numbers = Vec::new();
for arg in std::env::args().skip(1) {
numbers.push(u64::from_str(&arg)
.expect("error parsing argument"));
}
if numbers.len() == 0 {
writeln!(std::io::stderr(), "Usage: gcd NUMBER ...").unwrap();
std::process::exit(1);
}
let mut d = numbers[0];
for m in &numbers[1..] {
d = gcd(d, *m);
}
println!("The greatest common divisor of {:?} is {}",
numbers, d);
}

@ -0,0 +1 @@
target

@ -0,0 +1,4 @@
[[package]]
name = "generic-queue"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "generic-queue"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,90 @@
pub struct Queue<T> {
older: Vec<T>,
younger: Vec<T>
}
impl<T> Queue<T> {
pub fn new() -> Queue<T> {
Queue { older: Vec::new(), younger: Vec::new() }
}
pub fn push(&mut self, t: T) {
self.younger.push(t);
}
pub fn is_empty(&self) -> bool {
self.older.is_empty() && self.younger.is_empty()
}
pub fn pop(&mut self) -> Option<T> {
if self.older.is_empty() {
use std::mem::swap;
if self.younger.is_empty() {
return None;
}
// Bring the elements in younger over to older, and put them in
// the promised order.
swap(&mut self.older, &mut self.younger);
self.older.reverse();
}
// Now older is guaranteed to have something. Vec's pop method
// already returns an Option, so we're set.
self.older.pop()
}
pub fn split(self) -> (Vec<T>, Vec<T>) {
(self.older, self.younger)
}
}
#[test]
fn test() {
let mut q = Queue::new();
q.push('*');
assert_eq!(q.pop(), Some('*'));
assert_eq!(q.pop(), None);
q.push('0');
q.push('1');
assert_eq!(q.pop(), Some('0'));
q.push('∞');
assert_eq!(q.pop(), Some('1'));
assert_eq!(q.pop(), Some('∞'));
assert_eq!(q.pop(), None);
assert!(q.is_empty());
q.push('☉');
assert!(!q.is_empty());
q.pop();
assert!(q.is_empty());
let mut q = Queue::new();
q.push('P');
q.push('D');
assert_eq!(q.pop(), Some('P'));
q.push('X');
assert_eq!(q.split(), (vec!['D'], vec!['X']));
}
#[test]
fn test_generic() {
let mut q = Queue::<char>::new();
&mut q;
drop(q);
let mut q = Queue::new();
let mut r = Queue::new();
q.push("CAD"); // apparently a Queue<&'static str>
r.push(0.74); // apparently a Queue<f64>
q.push("BTC"); // Bitcoins per USD, 2017-5
r.push(2737.7); // Rust fails to detect irrational exuberance
}

1
grep/.gitignore vendored

@ -0,0 +1 @@
target

4
grep/Cargo.lock generated

@ -0,0 +1,4 @@
[[package]]
name = "grep"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "grep"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,49 @@
// grep - Search stdin or some files for lines matching a given string.
use std::error::Error;
use std::io::{self, BufReader};
use std::io::prelude::*;
use std::fs::File;
use std::path::PathBuf;
fn grep<R>(target: &str, reader: R) -> io::Result<()>
where R: BufRead
{
for line_result in reader.lines() {
let line = line_result?;
if line.contains(target) {
println!("{}", line);
}
}
Ok(())
}
fn grep_main() -> Result<(), Box<Error>> {
// Get the command-line arguments. The first argument is the
// string to search for; the rest are filenames.
let mut args = std::env::args().skip(1);
let target = match args.next() {
Some(s) => s,
None => Err("usage: grep PATTERN FILE...")?
};
let files: Vec<PathBuf> = args.map(PathBuf::from).collect();
if files.is_empty() {
let stdin = io::stdin();
grep(&target, stdin.lock())?;
} else {
for file in files {
let f = File::open(file)?;
grep(&target, BufReader::new(f))?;
}
}
Ok(())
}
fn main() {
let result = grep_main();
if let Err(err) = result {
let _ = writeln!(io::stderr(), "{}", err);
}
}

@ -0,0 +1 @@
target

476
http-get/Cargo.lock generated

@ -0,0 +1,476 @@
[[package]]
name = "advapi32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "antidote"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "core-foundation"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "core-foundation-sys"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crypt32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dtoa"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "foreign-types"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gcc"
version = "0.3.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gdi32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "http-get"
version = "0.1.0"
dependencies = [
"reqwest 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "httparse"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hyper"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hyper-native-tls"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "idna"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "language-tags"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libflate"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "matches"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mime"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "native-tls"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"openssl 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
"schannel 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num_cpus"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl-sys"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "reqwest"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hyper 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper-native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libflate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-serialize"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "schannel"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"crypt32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "secur32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "security-framework"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "security-framework-sys"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_json"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_urlencoded"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tempdir"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "traitobject"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "typeable"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicase"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-bidi"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-normalization"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "url"
version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "user32-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a"
"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
"checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67"
"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
"checksum crypt32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e34988f7e069e0b2f3bfc064295161e489b2d4e04a2e4248fb94360cdf00b4ec"
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae"
"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d"
"checksum hyper 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb15973f070a7de8bf3f61261726ef09647741110af6062d5ca1e21e6c4bd013"
"checksum hyper-native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "afe68f772f0497a7205e751626bb8e1718568b58534b6108c73a74ef80483409"
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
"checksum libflate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "202cf589fbdf78809ae1bb7fd5d1da2627136c966e756127cd14fa00c7e2da41"
"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1"
"checksum mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c93a4bd787ddc6e7833c519b73a50883deb5863d76d9b71eb8216fb7f94e66"
"checksum native-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e94a2fc65a44729fe969cc973da87c1052ae3f000b2cb33029f14aeb85550d5"
"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
"checksum num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55aabf4e2d6271a2e4e4c0f2ea1f5b07cc589cc1a9e9213013b54a76678ca4f3"
"checksum openssl 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8aa0eb7aad44f0da6f7dda13ddb4559d91a0f40cfab150b1f76ad5b39ec523f"
"checksum openssl-sys 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "14f5bfd12054d764510b887152d564ba11d99ae24ea7d740781778f646620576"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
"checksum reqwest 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5113a267e410c17d186189940711e49da445987299763f63503cfed4dbbcccc0"
"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
"checksum schannel 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b291854e37196c2b67249e09d6bdeff410b19e1acf05558168e9c4413b4e95"
"checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc"
"checksum security-framework 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "42ddf098d78d0b64564b23ee6345d07573e7d10e52ad86875d89ddf5f8378a02"
"checksum security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "5bacdada57ea62022500c457c8571c17dfb5e6240b7c8eac5916ffa8c7138a55"
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
"checksum serde 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "231dfd55909400769e437326cfb4af8bec97c3dd56ab3d02df8ef5c7e00f179b"
"checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1"
"checksum serde_urlencoded 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4cde9c1d41c4852426d097c53b9151c53e314e9c6ec8a7765e083137d45c76"
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764"
"checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f"
"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
"checksum url 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f024e241a55f5c88401595adc1d4af0c9649e91da82d0e190fe55950231ae575"
"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

@ -0,0 +1,7 @@
[package]
name = "http-get"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]
reqwest = "0.5.1"

@ -0,0 +1,30 @@
extern crate reqwest;
use std::error::Error;
use std::io::{self, Write};
fn http_get_main(url: &str) -> Result<(), Box<Error>> {
// Send the HTTP request and get a response.
let mut response = reqwest::get(url)?;
if !response.status().is_success() {
Err(format!("{}", response.status()))?;
}
// Read the response body and write it to stdout.
let stdout = io::stdout();
io::copy(&mut response, &mut stdout.lock())?;
Ok(())
}
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() != 2 {
writeln!(io::stderr(), "usage: http-get URL").unwrap();
return;
}
if let Err(err) = http_get_main(&args[1]) {
writeln!(io::stderr(), "error: {}", err).unwrap();
}
}

@ -0,0 +1 @@
target

@ -0,0 +1,4 @@
[[package]]
name = "interval"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "interval"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,30 @@
#[derive(Debug, PartialEq)]
struct Interval<T> {
lower: T, // inclusive
upper: T // exclusive
}
use std::cmp::{Ordering, PartialOrd};
impl<T: PartialOrd> PartialOrd<Interval<T>> for Interval<T> {
fn partial_cmp(&self, other: &Interval<T>) -> Option<Ordering> {
if self == other { Some(Ordering::Equal) }
else if self.lower >= other.upper { Some(Ordering::Greater) }
else if self.upper <= other.lower { Some(Ordering::Less) }
else { None }
}
}
#[test]
fn test() {
assert!(Interval { lower: 10, upper: 20 } < Interval { lower: 20, upper: 40 });
assert!(Interval { lower: 7, upper: 8 } >= Interval { lower: 0, upper: 1 });
assert!(Interval { lower: 7, upper: 8 } <= Interval { lower: 7, upper: 8 });
assert!(Interval { lower: 7, upper: 8 }.le(&Interval { lower: 7, upper: 8 }));
// Overlapping intervals aren't ordered with respect to each other.
let left = Interval { lower: 10, upper: 30 };
let right = Interval { lower: 20, upper: 40 };
assert!(!(left < right));
assert!(!(left >= right));
}

@ -0,0 +1 @@
target

382
iron-gcd/Cargo.lock generated

@ -0,0 +1,382 @@
[[package]]
name = "base64"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bodyparser"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"persistent 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byteorder"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "conduit-mime-types"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dtoa"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "error"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "httparse"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hyper"
version = "0.10.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "idna"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "iron"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "iron-gcd"
version = "0.1.0"
dependencies = [
"iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"router 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"urlencoded 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "language-tags"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "matches"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mime"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "modifier"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num-traits"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "num_cpus"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "persistent"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "plugin"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "route-recognizer"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "router"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"route-recognizer 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "safemem"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "semver"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_json"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "traitobject"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "typeable"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "typemap"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicase"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-bidi"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-normalization"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unsafe-any"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "url"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "urlencoded"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bodyparser 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
"checksum bodyparser 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6928e817538b74a73d1dd6e9a942a2a35c632a597b6bb14fd009480f859a6bf5"
"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d"
"checksum conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95ca30253581af809925ef68c2641cc140d6183f43e12e0af4992d53768bd7b8"
"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
"checksum error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e606f14042bb87cc02ef6a14db6c90ab92ed6f62d87e69377bc759fd7987cc"
"checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2"
"checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37"
"checksum iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2440ae846e7a8c7f9b401db8f6e31b4ea5e7d3688b91761337da7e054520c75b"
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "236eb37a62591d4a41a89b7763d7de3e06ca02d5ab2815446a8bae5d2f8c2d57"
"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1"
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
"checksum modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58"
"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
"checksum num_cpus 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6e850c7f35c3de263e6094e819f6b4b9c09190ff4438fc6dec1aef1568547bc"
"checksum persistent 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c9c94f2ef72dc272c6bcc8157ccf2bc7da14f4c58c69059ac2fc48492d6916"
"checksum plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0"
"checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b"
"checksum route-recognizer 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3255338088df8146ba63d60a9b8e3556f1146ce2973bc05a75181a42ce2256"
"checksum router 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9b1797ff166029cb632237bb5542696e54961b4cf75a324c6f05c9cf0584e4e"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
"checksum serde_json 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "67f7d2e9edc3523a9c8ec8cd6ec481b3a27810aafee3e625d311febd3e656b4c"
"checksum time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd7ccbf969a892bf83f1e441126968a07a3941c24ff522a26af9f9f4585d1a3"
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
"checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6"
"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764"
"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a"
"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
"checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f"
"checksum url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2ba3456fbe5c0098cb877cf08b92b76c3e18e0be9e47c35b487220d377d24e"
"checksum urlencoded 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c28708636d6f7298a53b1cdb6af40f1ab523209a7cb83cf4d41b3ebc671d319"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

@ -0,0 +1,10 @@
[package]
name = "iron-gcd"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]
iron = "0.5.1"
mime = "0.2.3"
router = "0.5.1"
urlencoded = "0.5.0"

@ -0,0 +1,5 @@
# A simple web server, in Rust
This program uses the `Iron` framework to implement a simple web server in Rust.
Run the program with `cargo run`, visit `http://localhost:3000/`, and then ask
it to compute the greatest common denominator of some numbers for you!

@ -0,0 +1,101 @@
extern crate iron;
#[macro_use] extern crate mime;
use iron::prelude::*;
use iron::status;
extern crate router;
use router::Router;
fn main() {
let mut router = Router::new();
router.get("/", get_form, "root");
router.post("/gcd", post_gcd, "gcd");
println!("Serving on http://localhost:3000...");
Iron::new(router).http("localhost:3000").unwrap();
}
fn get_form(_request: &mut Request) -> IronResult<Response> {
let mut response = Response::new();
response.set_mut(status::Ok);
response.set_mut(mime!(Text/Html; Charset=Utf8));
response.set_mut(r#"
<title>GCD Calculator</title>
<form action="/gcd" method="post">
<input type="text" name="n"/>
<input type="text" name="n"/>
<button type="submit">Compute GCD</button>
</form>
"#);
Ok(response)
}
extern crate urlencoded;
use std::str::FromStr;
use urlencoded::UrlEncodedBody;
fn post_gcd(request: &mut Request) -> IronResult<Response> {
let mut response = Response::new();
let form_data = match request.get_ref::<UrlEncodedBody>() {
Err(e) => {
response.set_mut(status::BadRequest);
response.set_mut(format!("Error parsing form data: {:?}\n", e));
return Ok(response);
}
Ok(map) => map
};
let unparsed_numbers = match form_data.get("n") {
None => {
response.set_mut(status::BadRequest);
response.set_mut(format!("form data has no 'n' parameter\n"));
return Ok(response);
}
Some(nums) => nums
};
let mut numbers = Vec::new();
for unparsed in unparsed_numbers {
match u64::from_str(&unparsed) {
Err(_) => {
response.set_mut(status::BadRequest);
response.set_mut(
format!("Value for 'n' parameter not a number: {:?}\n",
unparsed));
return Ok(response);
}
Ok(n) => { numbers.push(n); }
}
}
let mut d = numbers[0];
for m in &numbers[1..] {
d = gcd(d, *m);
}
response.set_mut(status::Ok);
response.set_mut(mime!(Text/Html; Charset=Utf8));
response.set_mut(
format!("The greatest common divisor of the numbers {:?} is <b>{}</b>\n",
numbers, d));
Ok(response)
}
fn gcd(mut n: u64, mut m: u64) -> u64 {
assert!(n != 0 && m != 0);
while m != 0 {
if m < n {
let t = m;
m = n;
n = t;
}
m = m % n;
}
n
}

@ -0,0 +1 @@
target

@ -0,0 +1,4 @@
[[package]]
name = "json-macro"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "json-macro"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,45 @@
use std::collections::HashMap;
#[macro_use] mod macros;
#[derive(Clone, PartialEq, Debug)]
pub enum Json {
Null,
Boolean(bool),
Number(f64),
String(String),
Array(Vec<Json>),
Object(Box<HashMap<String, Json>>)
}
impl From<bool> for Json {
fn from(b: bool) -> Json {
Json::Boolean(b)
}
}
impl From<String> for Json {
fn from(s: String) -> Json {
Json::String(s)
}
}
impl<'a> From<&'a str> for Json {
fn from(s: &'a str) -> Json {
Json::String(s.to_string())
}
}
macro_rules! impl_from_num_for_json {
( $( $t:ident )* ) => {
$(
impl From<$t> for Json {
fn from(n: $t) -> Json {
Json::Number(n as f64)
}
}
)*
};
}
impl_from_num_for_json!(u8 i8 u16 i16 u32 i32 u64 i64 usize isize f32 f64);

@ -0,0 +1,145 @@
// macros.rs
pub use std::collections::HashMap;
pub use std::boxed::Box;
pub use std::string::ToString;
#[macro_export]
macro_rules! json {
(null) => {
$crate::Json::Null
};
([ $( $element:tt ),* ]) => {
$crate::Json::Array(vec![ $( json!($element) ),* ])
};
({ $( $key:tt : $value:tt ),* }) => {
{
let mut fields = $crate::macros::Box::new(
$crate::macros::HashMap::new());
$( fields.insert($crate::macros::ToString::to_string($key),
json!($value)); )*
$crate::Json::Object(fields)
}
};
($other:tt) => {
$crate::Json::from($other)
};
}
#[cfg(test)]
mod tests {
use ::Json;
#[test]
fn json_with_rust_expressions() {
const HELLO: &'static str = "hello";
let macro_generated_value =
json!({
"math_works": (4 - 2 == 2),
"en": HELLO,
HELLO: "bonjour!"
})
;
let hand_coded_value = Json::Object(Box::new(vec![
("math_works".to_string(), Json::Boolean(true)),
("en".to_string(), Json::String("hello".to_string())),
("hello".to_string(), Json::String("bonjour!".to_string())),
].into_iter().collect()));
assert_eq!(macro_generated_value, hand_coded_value);
}
// Tests from earlier in the chapter should actually pass with this macro.
#[test]
fn original_example() {
let hand_coded_value = {
let students = Json::Array(vec![
Json::Object(Box::new(vec![
("name".to_string(), Json::String("Jim Blandy".to_string())),
("class_of".to_string(), Json::Number(1926.0)),
("major".to_string(), Json::String("Tibetan throat singing".to_string()))
].into_iter().collect())),
Json::Object(Box::new(vec![
("name".to_string(), Json::String("Jason Orendorff".to_string())),
("class_of".to_string(), Json::Number(1702.0)),
("major".to_string(), Json::String("Knots".to_string()))
].into_iter().collect()))
]);
students
};
let macro_generated_value = {
let students = json!([
{
"name": "Jim Blandy",
"class_of": 1926,
"major": "Tibetan throat singing"
},
{
"name": "Jason Orendorff",
"class_of": 1702,
"major": "Knots"
}
]);
students
};
assert_eq!(macro_generated_value, hand_coded_value);
}
#[test]
fn json_array_with_json_element() {
let macro_generated_value = json!(
[
// valid JSON that doesn't match `$element:expr`
{
"pitch": 440.0
}
]
);
let hand_coded_value =
Json::Array(vec![
Json::Object(Box::new(vec![
("pitch".to_string(), Json::Number(440.0))
].into_iter().collect()))
]);
assert_eq!(macro_generated_value, hand_coded_value);
}
#[test]
fn json_monolith() {
let width = 4.0;
let desc =
json!({
"width": width,
"height": (width * 9.0 / 4.0)
});
let hand_coded_value =
Json::Object(Box::new(vec![
("width".to_string(), Json::Number(width)),
("height".to_string(), Json::Number(width * 9.0 / 4.0))
].into_iter().collect()));
assert_eq!(desc, hand_coded_value);
}
#[test]
fn hygiene() {
// The surprise is that *the macro works as-is*.
// Rust renames the variable for you!
let fields = "Fields, W.C.";
let role = json!({
"name": "Larson E. Whipsnade",
"actor": fields
});
let hand_coded_value =
Json::Object(Box::new(vec![
("name".to_string(), Json::String("Larson E. Whipsnade".to_string())),
("actor".to_string(), Json::String("Fields, W.C.".to_string()))
].into_iter().collect()));
assert_eq!(role, hand_coded_value);
}
}

@ -0,0 +1 @@
target

@ -0,0 +1,14 @@
[[package]]
name = "git-toy"
version = "0.1.0"
dependencies = [
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e"

@ -0,0 +1,8 @@
[package]
name = "git-toy"
version = "0.1.0"
authors = ["You <you@example.com>"]
build = "build.rs"
[dependencies]
libc = "0.2.23"

@ -0,0 +1,3 @@
fn main() {
println!("cargo:rustc-link-search=native=/home/jimb/libgit2-0.25.1/build");
}

@ -0,0 +1,251 @@
mod raw;
use std::error;
use std::fmt;
use std::result;
#[derive(Debug)]
pub struct Error {
code: i32,
message: String,
class: i32
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
// Displaying an `Error` simply displays the message from libgit2.
self.message.fmt(f)
}
}
impl error::Error for Error {
fn description(&self) -> &str { &self.message }
}
pub type Result<T> = result::Result<T, Error>;
use std::os::raw::c_int;
use std::ffi::CStr;
fn check(code: c_int) -> Result<c_int> {
if code >= 0 {
return Ok(code);
}
unsafe {
let error = raw::giterr_last();
// libgit2 ensures that (*error).message is always non-null and null
// terminated, so this call is safe.
let message = CStr::from_ptr((*error).message)
.to_string_lossy()
.into_owned();
Err(Error {
code: code as i32,
message,
class: (*error).klass as i32
})
}
}
/// A Git repository.
pub struct Repository {
// This must always be a pointer to a live `git_repository` structure,
// No other `Repository` may point to it.
raw: *mut raw::git_repository
}
use std::path::Path;
impl Repository {
pub fn open<P: AsRef<Path>>(path: P) -> Result<Repository> {
ensure_initialized();
let path = path_to_cstring(path.as_ref())?;
let mut repo = null_mut();
unsafe {
check(raw::git_repository_open(&mut repo, path.as_ptr()))?;
}
Ok(Repository { raw: repo })
}
}
use std;
use libc;
fn ensure_initialized() {
static ONCE: std::sync::Once = std::sync::ONCE_INIT;
ONCE.call_once(|| {
unsafe {
check(raw::git_libgit2_init())
.expect("initializing libgit2 failed");
assert_eq!(libc::atexit(shutdown), 0);
}
});
}
use std::io::Write;
extern fn shutdown() {
unsafe {
if let Err(e) = check(raw::git_libgit2_shutdown()) {
let _ = writeln!(std::io::stderr(),
"shutting down libgit2 failed: {}",
e);
std::process::abort();
}
}
}
impl Drop for Repository {
fn drop(&mut self) {
unsafe {
raw::git_repository_free(self.raw);
}
}
}
use std::ffi::CString;
#[cfg(unix)]
fn path_to_cstring(path: &Path) -> Result<CString> {
// The `as_bytes` method exists only on Unix-like systems.
use std::os::unix::ffi::OsStrExt;
Ok(CString::new(path.as_os_str().as_bytes())?)
}
#[cfg(windows)]
fn path_to_cstring(path: &Path) -> Result<CString> {
// Try to convert to UTF-8. If this fails, libgit2 can't handle the path
// anyway.
match path.to_str() {
Some(s) => Ok(CString::new(s)?),
None => {
let message = format!("Couldn't convert path '{}' to UTF-8",
path.display());
Err(message.into())
}
}
}
impl From<String> for Error {
fn from(message: String) -> Error {
Error { code: -1, message, class: 0 }
}
}
// NulError is what `CString::new` returns if a string
// has embedded zero bytes.
impl From<std::ffi::NulError> for Error {
fn from(e: std::ffi::NulError) -> Error {
Error { code: -1, message: e.to_string(), class: 0 }
}
}
/// The identifier of some sort of object stored in the Git object
/// database: a commit, tree, blob, tag, etc. This is a wide hash of the
/// object's contents.
pub struct Oid {
pub raw: raw::git_oid
}
use std::mem::uninitialized;
use std::os::raw::c_char;
impl Repository {
pub fn reference_name_to_id(&self, name: &str) -> Result<Oid> {
let name = CString::new(name)?;
unsafe {
let mut oid = uninitialized();
check(raw::git_reference_name_to_id(&mut oid, self.raw,
name.as_ptr() as *const c_char))?;
Ok(Oid { raw: oid })
}
}
}
use std::marker::PhantomData;
pub struct Commit<'repo> {
// This must always be a pointer to a usable `git_commit` structure.
raw: *mut raw::git_commit,
_marker: PhantomData<&'repo Repository>
}
use std::ptr::null_mut;
impl Repository {
pub fn find_commit(&self, oid: &Oid) -> Result<Commit> {
let mut commit = null_mut();
unsafe {
check(raw::git_commit_lookup(&mut commit, self.raw, &oid.raw))?;
}
Ok(Commit { raw: commit, _marker: PhantomData })
}
}
impl<'repo> Drop for Commit<'repo> {
fn drop(&mut self) {
unsafe {
raw::git_commit_free(self.raw);
}
}
}
impl<'repo> Commit<'repo> {
pub fn author(&self) -> Signature {
unsafe {
Signature {
raw: raw::git_commit_author(self.raw),
_marker: PhantomData
}
}
}
pub fn message(&self) -> Option<&str> {
unsafe {
let message = raw::git_commit_message(self.raw);
char_ptr_to_str(self, message)
}
}
}
pub struct Signature<'text> {
raw: *const raw::git_signature,
_marker: PhantomData<&'text str>
}
impl<'text> Signature<'text> {
/// Return the author's name as a `&str`,
/// or `None` if it is not well-formed UTF-8.
pub fn name(&self) -> Option<&str> {
unsafe {
char_ptr_to_str(self, (*self.raw).name)
}
}
/// Return the author's email as a `&str`,
/// or `None` if it is not well-formed UTF-8.
pub fn email(&self) -> Option<&str> {
unsafe {
char_ptr_to_str(self, (*self.raw).email)
}
}
}
/// Try to borrow a `&str` from `ptr`, given that `ptr` may be null or
/// refer to ill-formed UTF-8. Give the result a lifetime as if it were
/// borrowed from `_owner`.
///
/// Safety: if `ptr` is non-null, it must point to a null-terminated C
/// string that is safe to access.
unsafe fn char_ptr_to_str<T>(_owner: &T, ptr: *const c_char) -> Option<&str> {
if ptr.is_null() {
return None;
} else {
CStr::from_ptr(ptr).to_str().ok()
}
}

@ -0,0 +1,56 @@
#![allow(dead_code, non_camel_case_types)]
use std::os::raw::{c_int, c_char, c_uchar};
#[link(name = "git2")]
extern {
pub fn git_libgit2_init() -> c_int;
pub fn git_libgit2_shutdown() -> c_int;
pub fn giterr_last() -> *const git_error;
pub fn git_repository_open(out: *mut *mut git_repository, path: *const c_char) -> c_int;
pub fn git_repository_free(repo: *mut git_repository);
pub fn git_reference_name_to_id(out: *mut git_oid,
repo: *mut git_repository,
reference: *const c_char) -> c_int;
pub fn git_commit_lookup(out: *mut *mut git_commit,
repo: *mut git_repository,
id: *const git_oid) -> c_int;
pub fn git_commit_author(commit: *const git_commit) -> *const git_signature;
pub fn git_commit_message(commit: *const git_commit) -> *const c_char;
pub fn git_commit_free(commit: *mut git_commit);
}
pub enum git_repository {}
pub enum git_commit {}
#[repr(C)]
pub struct git_error {
pub message: *const c_char,
pub klass: c_int
}
pub const GIT_OID_RAWSZ: usize = 20;
#[repr(C)]
pub struct git_oid {
pub id: [c_uchar; GIT_OID_RAWSZ]
}
pub type git_time_t = i64;
#[repr(C)]
pub struct git_time {
pub time: git_time_t,
pub offset: c_int
}
#[repr(C)]
pub struct git_signature {
pub name: *const c_char,
pub email: *const c_char,
pub when: git_time
}

@ -0,0 +1,24 @@
mod git;
extern crate libc;
fn main() {
let path = std::env::args_os().skip(1).next()
.expect("usage: libgit2-rs PATH");
let repo = git::Repository::open(&path)
.expect("opening repository");
let commit_oid = repo.reference_name_to_id("HEAD")
.expect("looking up 'HEAD' reference");
let commit = repo.find_commit(&commit_oid)
.expect("looking up commit");
let author = commit.author();
println!("{} <{}>\n",
author.name().unwrap_or("(none)"),
author.email().unwrap_or("none"));
println!("{}", commit.message().unwrap_or("(none)"));
}

@ -0,0 +1 @@
target

@ -0,0 +1,4 @@
[[package]]
name = "libgit2-rs"
version = "0.1.0"

@ -0,0 +1,7 @@
[package]
name = "libgit2-rs"
version = "0.1.0"
authors = ["You <you@example.com>"]
build = "build.rs"
[dependencies]

@ -0,0 +1,3 @@
fn main() {
println!("cargo:rustc-link-search=native=/home/jimb/libgit2-0.25.1/build");
}

@ -0,0 +1,67 @@
mod raw;
use std::ffi::CStr;
use std::os::raw::c_int;
fn check(activity: &'static str, status: c_int) -> c_int {
if status < 0 {
unsafe {
let error = &*raw::giterr_last();
println!("error while {}: {} ({})",
activity,
CStr::from_ptr(error.message).to_string_lossy(),
error.klass);
std::process::exit(1);
}
}
status
}
unsafe fn show_commit(commit: *const raw::git_commit) {
let author = raw::git_commit_author(commit);
let name = CStr::from_ptr((*author).name).to_string_lossy();
let email = CStr::from_ptr((*author).email).to_string_lossy();
println!("{} <{}>\n", name, email);
let message = raw::git_commit_message(commit);
println!("{}", CStr::from_ptr(message).to_string_lossy());
}
use std::ffi::CString;
use std::mem;
use std::ptr;
use std::os::raw::c_char;
fn main() {
let path = std::env::args().skip(1).next()
.expect("usage: git-toy PATH");
let path = CString::new(path)
.expect("path contains null characters");
unsafe {
check("initializing library", raw::git_libgit2_init());
let mut repo = ptr::null_mut();
check("opening repository",
raw::git_repository_open(&mut repo, path.as_ptr()));
let c_name = b"HEAD\0".as_ptr() as *const c_char;
let mut oid = mem::uninitialized();
check("looking up HEAD",
raw::git_reference_name_to_id(&mut oid, repo, c_name));
let mut commit = ptr::null_mut();
check("looking up commit",
raw::git_commit_lookup(&mut commit, repo, &oid));
show_commit(commit);
raw::git_commit_free(commit);
raw::git_repository_free(repo);
check("shutting down library", raw::git_libgit2_shutdown());
}
}

@ -0,0 +1,55 @@
#![allow(non_camel_case_types)]
use std::os::raw::{c_int, c_char, c_uchar};
#[link(name = "git2")]
extern {
pub fn git_libgit2_init() -> c_int;
pub fn git_libgit2_shutdown() -> c_int;
pub fn giterr_last() -> *const git_error;
pub fn git_repository_open(out: *mut *mut git_repository,
path: *const c_char) -> c_int;
pub fn git_repository_free(repo: *mut git_repository);
pub fn git_reference_name_to_id(out: *mut git_oid,
repo: *mut git_repository,
reference: *const c_char) -> c_int;
pub fn git_commit_lookup(out: *mut *mut git_commit,
repo: *mut git_repository,
id: *const git_oid) -> c_int;
pub fn git_commit_author(commit: *const git_commit) -> *const git_signature;
pub fn git_commit_message(commit: *const git_commit) -> *const c_char;
pub fn git_commit_free(commit: *mut git_commit);
}
pub enum git_repository {}
pub enum git_commit {}
#[repr(C)]
pub struct git_error {
pub message: *const c_char,
pub klass: c_int
}
#[repr(C)]
pub struct git_oid {
pub id: [c_uchar; 20]
}
pub type git_time_t = i64;
#[repr(C)]
pub struct git_time {
pub time: git_time_t,
pub offset: c_int
}
#[repr(C)]
pub struct git_signature {
pub name: *const c_char,
pub email: *const c_char,
pub when: git_time
}

1
queue/.gitignore vendored

@ -0,0 +1 @@
target

4
queue/Cargo.lock generated

@ -0,0 +1,4 @@
[[package]]
name = "queue"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "queue"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,109 @@
/// A last-in, first-out queue of characters.
pub struct Queue {
older: Vec<char>, // older elements, eldest last.
younger: Vec<char> // younger elements, youngest last.
}
impl Queue {
/// Push a character onto the back of a queue.
pub fn push(&mut self, c: char) {
self.younger.push(c);
}
/// Pop a character off the front of a queue. Return `Some(c)` if there
/// was a character to pop, or `None` if the queue was empty.
pub fn pop(&mut self) -> Option<char> {
if self.older.is_empty() {
if self.younger.is_empty() {
return None;
}
// Bring the elements in younger over to older, and put them in
// the promised order.
use std::mem::swap;
swap(&mut self.older, &mut self.younger);
self.older.reverse();
}
// Now older is guaranteed to have something. Vec's pop method
// already returns an Option, so we're set.
self.older.pop()
}
}
#[test]
fn test_push_pop() {
let mut q = Queue { older: Vec::new(), younger: Vec::new() };
q.push('0');
q.push('1');
assert_eq!(q.pop(), Some('0'));
q.push('∞');
assert_eq!(q.pop(), Some('1'));
assert_eq!(q.pop(), Some('∞'));
assert_eq!(q.pop(), None);
(&mut q).push('0');
(&mut q).push('1');
assert_eq!(q.pop(), Some('0'));
assert_eq!(q.pop(), Some('1'));
}
impl Queue {
pub fn is_empty(&self) -> bool {
self.older.is_empty() && self.younger.is_empty()
}
}
#[test]
fn test_is_empty() {
let mut q = Queue { older: Vec::new(), younger: Vec::new() };
assert!(q.is_empty());
q.push('☉');
assert!(!q.is_empty());
q.pop();
assert!(q.is_empty());
}
impl Queue {
pub fn split(self) -> (Vec<char>, Vec<char>) {
(self.older, self.younger)
}
}
#[test]
fn test_split() {
let mut q = Queue { older: Vec::new(), younger: Vec::new() };
q.push('P');
q.push('D');
assert_eq!(q.pop(), Some('P'));
q.push('X');
let (older, younger) = q.split();
// q is now uninitialized.
assert_eq!(older, vec!['D']);
assert_eq!(younger, vec!['X']);
}
impl Queue {
pub fn new() -> Queue {
Queue { older: Vec::new(), younger: Vec::new() }
}
}
#[test]
fn test_new() {
let mut q = Queue::new();
q.push('*');
q.push('1');
assert_eq!(q.pop(), Some('*'));
q.push('∞');
assert_eq!(q.pop(), Some('1'));
assert_eq!(q.pop(), Some('∞'));
assert_eq!(q.pop(), None);
}

@ -0,0 +1 @@
target

@ -0,0 +1,4 @@
[[package]]
name = "ref-with-flag"
version = "0.1.0"

@ -0,0 +1,6 @@
[package]
name = "ref-with-flag"
version = "0.1.0"
authors = ["You <you@example.com>"]
[dependencies]

@ -0,0 +1,50 @@
#![allow(dead_code)]
mod ref_with_flag {
use std::marker::PhantomData;
use std::mem::align_of;
/// A `&T` and a `bool`, wrapped up in a single word.
/// The type `T` must require at least two-byte alignment.
///
/// If you're the kind of programmer who's never met a pointer whose
/// 2⁰-bit you didn't want to steal, well, now you can do it safely!
/// ("But it's not nearly as exciting this way...")
pub struct RefWithFlag<'a, T: 'a> {
ptr_and_bit: usize,
behaves_like: PhantomData<&'a T> // occupies no space
}
impl<'a, T: 'a> RefWithFlag<'a, T> {
pub fn new(ptr: &'a T, bit: bool) -> RefWithFlag<T> {
assert!(align_of::<T>() % 2 == 0);
RefWithFlag {
ptr_and_bit: ptr as *const T as usize | bit as usize,
behaves_like: PhantomData
}
}
pub fn as_ref(&self) -> &'a T {
let ptr = (self.ptr_and_bit & !1) as *const T;
unsafe {
&*ptr
}
}
pub fn as_bool(&self) -> bool {
self.ptr_and_bit & 1 != 0
}
}
}
mod ref_with_flag_tests {
#[test]
fn use_ref_with_flag() {
use ref_with_flag::RefWithFlag;
let vec = vec![10, 20, 30];
let pab = RefWithFlag::new(&vec, true);
assert_eq!(pab.as_ref()[1], 20);
assert_eq!(pab.as_bool(), true);
}
}
Loading…
Cancel
Save