<commit_before>#![feature(collections)]
#![feature(io)]
#![feature(os)]
#![feature(rand)]

extern crate "rustc-serialize" as serialize;
extern crate getopts;

use std::os;
use std::rand::{ Rng, OsRng };
use std::iter::repeat;
use std::old_io::{ stdio, IoError, IoErrorKind, IoResult, BufferedReader };

use serialize::base64::{ self, FromBase64, ToBase64 };
use getopts::Options;

use gf256::Gf256;

mod gf256;

fn new_vec<T: Clone>(n: usize, x: T) -> Vec<T> {
	repeat(x).take(n).collect()
}

fn other_io_err(s: &'static str) -> IoError {
	IoError {
		kind: IoErrorKind::OtherIoError,
		desc: s,
		detail: None
	}
}

/// evaluates a polynomial at x=1, 2, 3, ... n (inclusive)
fn encode<W: Writer>(src: &[u8], n: u8, w: &mut W) -> IoResult<()> {
	for raw_x in 1 .. ((n as u16) + 1) {
		let x = Gf256::from_byte(raw_x as u8);
		let mut fac = Gf256::one();
		let mut acc = Gf256::zero();
		for &coeff in src.iter() {
			acc = acc + fac * Gf256::from_byte(coeff);
			fac = fac * x;
		}
		try!(w.write_u8(acc.to_byte()));
	}
	Ok(())
}

/// evaluates an interpolated polynomial at `raw_x` where
/// the polynomial is determined using Lagrangian interpolation
/// based on the given x/y coordinates `src`.
fn lagrange_interpolate(src: &[(u8, u8)], raw_x: u8) -> u8 {
	let x = Gf256::from_byte(raw_x);
	let mut sum = Gf256::zero();
	for (i, &(raw_xi, raw_yi)) in src.iter().enumerate() {
		let xi = Gf256::from_byte(raw_xi);
		let yi = Gf256::from_byte(raw_yi);
		let mut lix = Gf256::one();
		for (j, &(raw_xj, _)) in src.iter().enumerate() {
			if i != j {
				let xj = Gf256::from_byte(raw_xj);
				let delta = xi - xj;
				assert!(delta.poly !=0, "Duplicate shares");
				lix = lix * (x - xj) / delta;
			}
		}
		sum = sum + lix * yi;
	}
	sum.to_byte()
}

fn secret_share(src: &[u8], k: u8, n: u8) -> IoResult<Vec<Vec<u8>>> {
	let mut result = Vec::with_capacity(n as usize);
	for _ in 0 .. (n as usize) {
		result.push(new_vec(src.len(), 0u8));
	}
	let mut col_in = new_vec(k as usize, 0u8);
	let mut col_out = Vec::with_capacity(n as usize);
	let mut osrng = try!(OsRng::new());
	for (c, &s) in src.iter().enumerate() {
		col_in[0] = s;
		osrng.fill_bytes(&mut col_in[1..]);
		col_out.clear();
		try!(encode(&*col_in, n, &mut col_out));
		for (&y, share) in col_out.iter().zip(result.iter_mut()) {
			share[c] = y;
		}
	}
	Ok(result)
}

enum Action {
	Encode(u8, u8), // k and n parameter
	Decode
}

fn parse_k_n(s: &str) -> Option<(u8, u8)> {
	let mut iter = s.split(',');
	let first = match iter.next() { Some(x) => x, None => return None };
	let second = match iter.next() { Some(x) => x, None => return None };
	let k = match first.parse() { Some(x) => x, None => return None };
	let n = match second.parse() { Some(x) => x, None => return None };
	Some((k, n))
}

/// tries to read everything but stops early if the input seems to be
/// larger than `max` bytes and returns an IoError in this case
fn read_no_more_than<R: Reader>(r: &mut R, max: usize) -> IoResult<Vec<u8>> {
	let mut data = Vec::new();
	loop {
		if let Err(e) = r.push(max + 1 - data.len(), &mut data) {
			if e.kind == IoErrorKind::EndOfFile {
				break; // EOF condition is actually OK
			} else {
				return Err(e);
			}
		}
		if data.len() > max {
			return Err(other_io_err("Input too long"));
		}
	}
	Ok(data)
}

fn perform_encode(k: u8, n: u8) -> IoResult<()> {
	let secret = try!(read_no_more_than(&mut stdio::stdin(), 0x10000));
	let shares = try!(secret_share(&*secret, k, n));
	for (index, share) in shares.iter().enumerate() {
		println!("{}-{}-{}", k, index+1, share.to_base64(base64::STANDARD));
	}
	Ok(())
}

/// reads shares from stdin and returns Ok(k, shares) on success
/// where shares is a Vec<(u8, Vec<u8>)> representing x-coordinates
/// and share data.
fn read_shares() -> IoResult<(u8, Vec<(u8,Vec<u8>)>)> {
	let mut stdin = BufferedReader::new(stdio::stdin());
	let mut opt_k_l: Option<(u8, usize)> = None;
	let mut counter = 0u8;
	let mut shares: Vec<(u8,Vec<u8>)> = Vec::new();
	for line in stdin.lines() {
		let line = try!(line);
		let parts: Vec<_> = line.split('-').collect();
		let (k, n, raw) = match
			Some(parts).and_then(|p| {
				if p.len() != 3 { None } else { Some(p) }
			}).and_then(|p| {
				let mut iter = p.into_iter();
				let p1 = iter.next().unwrap().parse::<u8>();
				let p2 = iter.next().unwrap().parse::<u8>();
				let p3 = iter.next().unwrap();
				match (p1, p2) {
					(Some(k), Some(n)) => Some((k,n,p3)),
					_ => None
				}
			}).and_then(|(k,n,text)| {
				match text.from_base64() {
					Ok(v) => Some((k,n,v)),
					_ => None
				}
			}) {
				None => return Err(other_io_err("Share parse error")),
				Some(s) => s
			};
		if let Some((ck,cl)) = opt_k_l {
			if ck != k || cl != raw.len() {
				return Err(other_io_err("Incompatible shares"));
			}
		} else {
			opt_k_l = Some((k,raw.len()));
		}
		if shares.iter().all(|s| s.0 != n) {
			shares.push((n, raw));
			counter += 1;
			if counter == k {
				return Ok((k, shares));
			}
		}
	}
	Err(other_io_err("Not enough shares provided!"))
}

fn perform_decode() -> IoResult<()> {
	let (k, shares) = try!(read_shares());
	assert!(!shares.is_empty());
	let slen = shares[0].1.len();
	let mut col_in = Vec::with_capacity(k as usize);
	let mut secret = Vec::with_capacity(slen);
	for byteindex in 0 .. slen {
		col_in.clear();
		for s in shares.iter().take(k as usize) {
			col_in.push((s.0, s.1[byteindex]));
		}
		secret.push(lagrange_interpolate(&*col_in, 0u8));
	}
	let mut out = stdio::stdout_raw();
	try!(out.write_all(&*secret));
	out.flush()
}

fn main() {
	let mut stderr = stdio::stderr();
	let args = os::args();

	let mut opts = Options::new();
	opts.optflag("h", "help", "print this help text");
	opts.optflag("d", "decode", "for decoding");
	opts.optopt("e", "encode", "for encoding, K is the required number of \
	                            shares for decoding, N is the number of shares \
	                            to generate. 1 <= K <= N <= 255", "K,N");
	let opt_matches = match opts.parse(args.tail()) {
		Ok(m) => m,
		Err(f) => panic!(f.to_string())
	};

	if args.len() < 2 || opt_matches.opt_present("h") {
		println!(
"The program secretshare is an implementation of Shamir's secret sharing scheme.\n\
 It is applied byte-wise within a finite field for arbitraty long secrets.\n");
		println!("{}", opts.usage("Usage: secretshare [options]"));
		println!("Input is read from STDIN and output is written to STDOUT.");
 		return;
	}

	let action: Result<_,_> =
		match (opt_matches.opt_present("e"), opt_matches.opt_present("d")) {
			(false, false) => Err("Nothing to do! Use -e or -d"),
			(true, true) => Err("Use either -e or -d and not both"),
			(false, true) => Ok(Action::Decode),
			(true, false) => {
				if let Some(param) = opt_matches.opt_str("e") {
					if let Some((k,n)) = parse_k_n(&*param) {
						if 0 < k && k <= n {
							Ok(Action::Encode(k,n))
						} else {
							Err("Invalid encoding parameters K,N")
						}
					} else {
						Err("Could not parse K,N parameters")
					}
				} else {
					Err("No parameter for -e or -d provided")
				}
			}
		};

	let result =
		match action {
			Ok(Action::Encode(k,n)) => perform_encode(k,n),
			Ok(Action::Decode) => perform_decode(),
			Err(e) => {
				drop(writeln!(&mut stderr, "Error: {}", e));
				os::set_exit_status(1);
				return;
			}
		};

	if let Err(e) = result {
		drop(writeln!(&mut stderr, "{}", e));
		os::set_exit_status(1);
	}
}

<commit_msg>disable padding in base64 encoding<commit_after>#![feature(collections)]
#![feature(io)]
#![feature(os)]
#![feature(rand)]

extern crate "rustc-serialize" as serialize;
extern crate getopts;

use std::os;
use std::rand::{ Rng, OsRng };
use std::iter::repeat;
use std::old_io::{ stdio, IoError, IoErrorKind, IoResult, BufferedReader };

use serialize::base64::{ self, FromBase64, ToBase64 };
use getopts::Options;

use gf256::Gf256;

mod gf256;

fn new_vec<T: Clone>(n: usize, x: T) -> Vec<T> {
	repeat(x).take(n).collect()
}

fn other_io_err(s: &'static str) -> IoError {
	IoError {
		kind: IoErrorKind::OtherIoError,
		desc: s,
		detail: None
	}
}

/// evaluates a polynomial at x=1, 2, 3, ... n (inclusive)
fn encode<W: Writer>(src: &[u8], n: u8, w: &mut W) -> IoResult<()> {
	for raw_x in 1 .. ((n as u16) + 1) {
		let x = Gf256::from_byte(raw_x as u8);
		let mut fac = Gf256::one();
		let mut acc = Gf256::zero();
		for &coeff in src.iter() {
			acc = acc + fac * Gf256::from_byte(coeff);
			fac = fac * x;
		}
		try!(w.write_u8(acc.to_byte()));
	}
	Ok(())
}

/// evaluates an interpolated polynomial at `raw_x` where
/// the polynomial is determined using Lagrangian interpolation
/// based on the given x/y coordinates `src`.
fn lagrange_interpolate(src: &[(u8, u8)], raw_x: u8) -> u8 {
	let x = Gf256::from_byte(raw_x);
	let mut sum = Gf256::zero();
	for (i, &(raw_xi, raw_yi)) in src.iter().enumerate() {
		let xi = Gf256::from_byte(raw_xi);
		let yi = Gf256::from_byte(raw_yi);
		let mut lix = Gf256::one();
		for (j, &(raw_xj, _)) in src.iter().enumerate() {
			if i != j {
				let xj = Gf256::from_byte(raw_xj);
				let delta = xi - xj;
				assert!(delta.poly !=0, "Duplicate shares");
				lix = lix * (x - xj) / delta;
			}
		}
		sum = sum + lix * yi;
	}
	sum.to_byte()
}

fn secret_share(src: &[u8], k: u8, n: u8) -> IoResult<Vec<Vec<u8>>> {
	let mut result = Vec::with_capacity(n as usize);
	for _ in 0 .. (n as usize) {
		result.push(new_vec(src.len(), 0u8));
	}
	let mut col_in = new_vec(k as usize, 0u8);
	let mut col_out = Vec::with_capacity(n as usize);
	let mut osrng = try!(OsRng::new());
	for (c, &s) in src.iter().enumerate() {
		col_in[0] = s;
		osrng.fill_bytes(&mut col_in[1..]);
		col_out.clear();
		try!(encode(&*col_in, n, &mut col_out));
		for (&y, share) in col_out.iter().zip(result.iter_mut()) {
			share[c] = y;
		}
	}
	Ok(result)
}

enum Action {
	Encode(u8, u8), // k and n parameter
	Decode
}

fn parse_k_n(s: &str) -> Option<(u8, u8)> {
	let mut iter = s.split(',');
	let first = match iter.next() { Some(x) => x, None => return None };
	let second = match iter.next() { Some(x) => x, None => return None };
	let k = match first.parse() { Some(x) => x, None => return None };
	let n = match second.parse() { Some(x) => x, None => return None };
	Some((k, n))
}

/// tries to read everything but stops early if the input seems to be
/// larger than `max` bytes and returns an IoError in this case
fn read_no_more_than<R: Reader>(r: &mut R, max: usize) -> IoResult<Vec<u8>> {
	let mut data = Vec::new();
	loop {
		if let Err(e) = r.push(max + 1 - data.len(), &mut data) {
			if e.kind == IoErrorKind::EndOfFile {
				break; // EOF condition is actually OK
			} else {
				return Err(e);
			}
		}
		if data.len() > max {
			return Err(other_io_err("Input too long"));
		}
	}
	Ok(data)
}

fn perform_encode(k: u8, n: u8) -> IoResult<()> {
	let secret = try!(read_no_more_than(&mut stdio::stdin(), 0x10000));
	let shares = try!(secret_share(&*secret, k, n));
	let config = base64::Config {
		pad: false,
		..base64::STANDARD
	};
	for (index, share) in shares.iter().enumerate() {
		println!("{}-{}-{}", k, index+1, share.to_base64(config));
	}
	Ok(())
}

/// reads shares from stdin and returns Ok(k, shares) on success
/// where shares is a Vec<(u8, Vec<u8>)> representing x-coordinates
/// and share data.
fn read_shares() -> IoResult<(u8, Vec<(u8,Vec<u8>)>)> {
	let mut stdin = BufferedReader::new(stdio::stdin());
	let mut opt_k_l: Option<(u8, usize)> = None;
	let mut counter = 0u8;
	let mut shares: Vec<(u8,Vec<u8>)> = Vec::new();
	for line in stdin.lines() {
		let line = try!(line);
		let parts: Vec<_> = line.split('-').collect();
		let (k, n, raw) = match
			Some(parts).and_then(|p| {
				if p.len() != 3 { None } else { Some(p) }
			}).and_then(|p| {
				let mut iter = p.into_iter();
				let p1 = iter.next().unwrap().parse::<u8>();
				let p2 = iter.next().unwrap().parse::<u8>();
				let p3 = iter.next().unwrap();
				match (p1, p2) {
					(Some(k), Some(n)) => Some((k,n,p3)),
					_ => None
				}
			}).and_then(|(k,n,text)| {
				match text.from_base64() {
					Ok(v) => Some((k,n,v)),
					_ => None
				}
			}) {
				None => return Err(other_io_err("Share parse error")),
				Some(s) => s
			};
		if let Some((ck,cl)) = opt_k_l {
			if ck != k || cl != raw.len() {
				return Err(other_io_err("Incompatible shares"));
			}
		} else {
			opt_k_l = Some((k,raw.len()));
		}
		if shares.iter().all(|s| s.0 != n) {
			shares.push((n, raw));
			counter += 1;
			if counter == k {
				return Ok((k, shares));
			}
		}
	}
	Err(other_io_err("Not enough shares provided!"))
}

fn perform_decode() -> IoResult<()> {
	let (k, shares) = try!(read_shares());
	assert!(!shares.is_empty());
	let slen = shares[0].1.len();
	let mut col_in = Vec::with_capacity(k as usize);
	let mut secret = Vec::with_capacity(slen);
	for byteindex in 0 .. slen {
		col_in.clear();
		for s in shares.iter().take(k as usize) {
			col_in.push((s.0, s.1[byteindex]));
		}
		secret.push(lagrange_interpolate(&*col_in, 0u8));
	}
	let mut out = stdio::stdout_raw();
	try!(out.write_all(&*secret));
	out.flush()
}

fn main() {
	let mut stderr = stdio::stderr();
	let args = os::args();

	let mut opts = Options::new();
	opts.optflag("h", "help", "print this help text");
	opts.optflag("d", "decode", "for decoding");
	opts.optopt("e", "encode", "for encoding, K is the required number of \
	                            shares for decoding, N is the number of shares \
	                            to generate. 1 <= K <= N <= 255", "K,N");
	let opt_matches = match opts.parse(args.tail()) {
		Ok(m) => m,
		Err(f) => panic!(f.to_string())
	};

	if args.len() < 2 || opt_matches.opt_present("h") {
		println!(
"The program secretshare is an implementation of Shamir's secret sharing scheme.\n\
 It is applied byte-wise within a finite field for arbitraty long secrets.\n");
		println!("{}", opts.usage("Usage: secretshare [options]"));
		println!("Input is read from STDIN and output is written to STDOUT.");
 		return;
	}

	let action: Result<_,_> =
		match (opt_matches.opt_present("e"), opt_matches.opt_present("d")) {
			(false, false) => Err("Nothing to do! Use -e or -d"),
			(true, true) => Err("Use either -e or -d and not both"),
			(false, true) => Ok(Action::Decode),
			(true, false) => {
				if let Some(param) = opt_matches.opt_str("e") {
					if let Some((k,n)) = parse_k_n(&*param) {
						if 0 < k && k <= n {
							Ok(Action::Encode(k,n))
						} else {
							Err("Invalid encoding parameters K,N")
						}
					} else {
						Err("Could not parse K,N parameters")
					}
				} else {
					Err("No parameter for -e or -d provided")
				}
			}
		};

	let result =
		match action {
			Ok(Action::Encode(k,n)) => perform_encode(k,n),
			Ok(Action::Decode) => perform_decode(),
			Err(e) => {
				drop(writeln!(&mut stderr, "Error: {}", e));
				os::set_exit_status(1);
				return;
			}
		};

	if let Err(e) = result {
		drop(writeln!(&mut stderr, "{}", e));
		os::set_exit_status(1);
	}
}

<|endoftext|>


<commit_before>//Author: J. Pace <github.com/jpace121>
//Copyright: 2015
//License: http://opensource.org/licenses/BSD-2-Clause

// Make units we can enforce math with.
// Use enums? Or structs? Or phantom something or the other?

// Use a struct for the current status of the coaster.
// (Should this be more OOP-ish?)
struct CoasterStatus{
    m:f32, //mass in kg
    v:f32, //velocity in m/s
    h:f32, //height in m
    u:f32, //Potential energy in J
    k:f32 //Kinetic Energy in J
}

fn main() {
    // Set some current parameters.
    let mut status = CoasterStatus{
        m:10f32,
        v:10f32,
        h:0f32,
        u:0f32,
        k:0f32
    };

    status.k = get_kinetic(&status);
    status.u = get_potential(&status);
    println!("Velocity is {} m/s.",status.v );
    println!("Mass is {} kg", status.m);
    println!("Height is {} m", status.h);
    println!("");
    println!("Kinetic Energy: {}", status.k);
    println!("Potential Energy: {}", status.u);
}

fn get_kinetic(status:&CoasterStatus) -> f32{
    // Calculate the energy given the mass and the velocity
    // mass in kg, velocity in m/s, energy in J
    0.5*status.m*status.v
}

fn get_potential(status:&CoasterStatus) -> f32{
    // Calculate the potential energy, gven the mass and current height
    // from the zeroth point.
    let g = 9.81; // acceleration of gravity in m/s^2
    status.m*g*status.h
}
<commit_msg>Readability improvements.<commit_after>//Author: J. Pace <github.com/jpace121>
//Copyright: 2015
//License: http://opensource.org/licenses/BSD-2-Clause

// Make units we can enforce math with.
// Use enums? Or structs? Or phantom something or the other?

// Use a struct for the current status of the coaster.
// (Should this be more OOP-ish?)
struct CoasterStatus{
    m:f32, //mass in kg
    v:f32, //velocity in m/s
    h:f32, //height in m
    u:f32, //Potential energy in J
    k:f32 //Kinetic Energy in J
}

fn main() {
    // Set some current parameters.
    let mut status = CoasterStatus{
        m: 10.,
        v: 10.,
        h: 0.,
        u: 0.,
        k: 0.
    };

    status.k = get_kinetic(&status);
    status.u = get_potential(&status);
    println!("Velocity is {} m/s.",status.v );
    println!("Mass is {} kg", status.m);
    println!("Height is {} m", status.h);
    println!("");
    println!("Kinetic Energy: {}", status.k);
    println!("Potential Energy: {}", status.u);
}

fn get_kinetic(status:&CoasterStatus) -> f32{
    // Calculate the energy given the mass and the velocity
    // mass in kg, velocity in m/s, energy in J
    0.5*status.m*status.v
}

fn get_potential(status:&CoasterStatus) -> f32{
    // Calculate the potential energy, gven the mass and current height
    // from the zeroth point.
    let g = 9.81; // acceleration of gravity in m/s^2
    status.m*g*status.h
}
<|endoftext|>


<commit_before><commit_msg>added ability to run tty apps on branch<commit_after><|endoftext|>


<commit_before><commit_msg>Refactor(Sync): use a hashmap instead of a vector for actions (prep for scanning sync dir)<commit_after><|endoftext|>


<commit_before><commit_msg>We now pre-allocate the buffer we read the file from.<commit_after><|endoftext|>


<commit_before><commit_msg>keep a cache of crate/vs/rlib-name from 'cargo build'<commit_after>use std::path::{Path,PathBuf};
use std::fs::File;
use std::io::Write;

use super::es;
use es::traits::*;
use super::crate_utils::proper_crate_name;

use semver::Version;

fn read_entry(txt: &str) -> Option<(&str,Version,&str,&str)> {
    use strutil::*;
    // features field
    if let Some(s) = after(txt,"features\":[") {
        let idx = s.find(']').unwrap();
        let features = &s[0..idx];

        // filenames field _usually_ single path
        let s = after(&s[idx..],"\"filenames\":[\"").unwrap();
        let endq = s.find('"').unwrap();
        let path = &s[0..endq];
        let slashp = path.rfind('/').unwrap();
        let filename = &path[slashp+1..];
        let idx = filename.find('.').unwrap_or(filename.len()-1);
        let ext = &filename[idx+1..];
        if ! (ext == "" || ext == "exe") { // ignore build artifacts
            // package_id has both name and version
            let s = after(&s[endq+1..],"package_id\":\"").unwrap();
            let (name,vs) = next_2(s.split_whitespace());
            let vs = Version::parse(vs).or_die("bad semver");
            Some((name,vs,features,filename))
        } else {
            None
        }
    } else {
        None
    }
 }

fn file_name(cache: &Path) -> PathBuf {
    cache.join("cargo.meta")
}

#[derive(Debug)]
struct MetaEntry {
    package: String,
    crate_name: String,
    version: Version,
    features: String,
    debug_name: String,
    release_name: String,
}

pub struct Meta {
    entries: Vec<MetaEntry>
}

impl Meta {

    pub fn new() -> Meta {
        Meta {
            entries: Vec::new()
        }
    }

    pub fn new_from_file(cache: &Path) -> Meta {
        let mut v = Vec::new();
        let meta_f = file_name(cache);
        for line in es::lines(es::open(&meta_f)) {
            let parts = line.split(',').to_vec();
            v.push(MetaEntry{
                package: parts[0].into(),
                crate_name: parts[1].into(),
                version: Version::parse(parts[2]).unwrap(),
                features: parts[3].into(),
                debug_name: parts[4].into(),
                release_name: parts[5].into(),
            });
        }
        Meta {
            entries: v
        }
    }

    fn get_meta_entry<'a>(&'a self, name: &str) -> Option<&'a MetaEntry> {
        let mut v = self.entries.iter().filter(|e| e.crate_name == name).to_vec();
        if v.len() == 0 {
            return None;
        }
        if v.len() > 1 { // sort by semver in ascending order...
            v.sort_by(|a,b| a.version.cmp(&b.version));
        }
        Some(v[v.len()-1])
    }

    pub fn get_full_crate_name(&self, name: &str, debug: bool) -> Option<String> {
        self.get_meta_entry(name)
            .map(|e| if debug {e.debug_name.clone()} else {e.release_name.clone()})
    }

    pub fn dump_crates (&mut self, maybe_name: Option<String>) {
        if let Some(name) = maybe_name {
            if let Some(e) = self.get_meta_entry(&name) {
                println!("{}\t{}",e.crate_name,e.version);
            } else {
                es::quit("no such crate");
            }
        } else {
            self.entries.sort_by(|a,b| a.crate_name.cmp(&b.crate_name));
            for e in self.entries.iter() {
                println!("{}\t{}",e.crate_name,e.version);
            }
        }
    }

    // constructing from output of 'cargo build'

    pub fn debug(&mut self, txt: String) {
        for line in txt.lines() {
            // note that features is in form '"foo","bar"' which we
            // store as 'foo bar'
            if let Some((name,vs,features,filename)) = read_entry(line) {
                let package = name.to_string();
                let crate_name = proper_crate_name(&package);
                self.entries.push(MetaEntry{
                    package: package,
                    crate_name: crate_name,
                    version: vs,
                    features: features.replace(','," ").replace('"',""),
                    debug_name: filename.into(),
                    release_name: String::new()
                });
            }
        }
    }

    pub fn release(&mut self, txt: String) {
        for line in txt.lines() {
            if let Some((name,vs,_,filename)) = read_entry(line) {
                if let Some(entry) = self.entries.iter_mut()
                    .find(|e| e.package == name && e.version == vs) {
                        entry.release_name = filename.into();
                } else {
                    eprintln!("cannot find {} in release build",name);
                }
            }
        }
    }

    pub fn update(self, cache: &Path) {
        let meta_f = file_name(cache);
        let mut f = File::create(&meta_f).or_die("cannot create cargo.meta");
        for e in self.entries {
            write!(f,"{},{},{},{},{},{}\n",
                e.package,e.crate_name,e.version,e.features,e.debug_name,e.release_name).or_die("i/o?");
        }
    }

}
<|endoftext|>


<commit_before><commit_msg>Add prefix free decoder function<commit_after><|endoftext|>


<commit_before>// TODO: Doc the rest

use core::{cmp, intrinsics, mem};
use core::ops::{Index, IndexMut};
use core::ptr;

use scheduler;

use common::paging::PAGE_END;

pub const CLUSTER_ADDRESS: usize = PAGE_END;
pub const CLUSTER_COUNT: usize = 1024 * 1024; // 4 GiB
pub const CLUSTER_SIZE: usize = 4096; // Of 4 K chunks

/// A wrapper around raw pointers
pub struct Memory<T> {
    pub ptr: *mut T,
}

impl<T> Memory<T> {
    /// Create an empty
    pub fn new(count: usize) -> Option<Self> {
        let alloc = unsafe { alloc(count * mem::size_of::<T>()) };
        if alloc > 0 {
            Some(Memory { ptr: alloc as *mut T })
        } else {
            None
        }
    }

    pub fn new_align(count: usize, align: usize) -> Option<Self> {
        let alloc = unsafe { alloc_aligned(count * mem::size_of::<T>(), align) };
        if alloc > 0 {
            Some(Memory { ptr: alloc as *mut T })
        } else {
            None
        }
    }

    /// Renew the memory
    pub fn renew(&mut self, count: usize) -> bool {
        let address = unsafe { realloc(self.ptr as usize, count * mem::size_of::<T>()) };
        if address > 0 {
            self.ptr = address as *mut T;
            true
        } else {
            false
        }
    }

    /// Get the size in bytes
    pub fn size(&self) -> usize {
        unsafe { alloc_size(self.ptr as usize) }
    }

    /// Get the length in T elements
    pub fn length(&self) -> usize {
        unsafe { alloc_size(self.ptr as usize) / mem::size_of::<T>() }
    }

    /// Get the address
    pub unsafe fn address(&self) -> usize {
        self.ptr as usize
    }

    /// Read the memory
    pub unsafe fn read(&self, i: usize) -> T {
        ptr::read(self.ptr.offset(i as isize))
    }

    /// Load the memory
    pub unsafe fn load(&self, i: usize) -> T {
        intrinsics::atomic_singlethreadfence();
        ptr::read(self.ptr.offset(i as isize))
    }

    /// Overwrite the memory
    pub unsafe fn write(&mut self, i: usize, value: T) {
        ptr::write(self.ptr.offset(i as isize), value);
    }

    /// Store the memory
    pub unsafe fn store(&mut self, i: usize, value: T) {
        intrinsics::atomic_singlethreadfence();
        ptr::write(self.ptr.offset(i as isize), value)
    }

    /// Convert into a raw pointer
    pub unsafe fn into_raw(&mut self) -> *mut T {
        let ptr = self.ptr;
        self.ptr = 0 as *mut T;
        ptr
    }
}

impl<T> Drop for Memory<T> {
    fn drop(&mut self) {
        if self.ptr as usize > 0 {
            unsafe { unalloc(self.ptr as usize) };
        }
    }
}

impl<T> Index<usize> for Memory<T> {
    type Output = T;

    fn index<'a>(&'a self, _index: usize) -> &'a T {
        unsafe { &*self.ptr.offset(_index as isize) }
    }
}

impl<T> IndexMut<usize> for Memory<T> {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut T {
        unsafe { &mut *self.ptr.offset(_index as isize) }
    }
}

/// A memory map entry
#[repr(packed)]
struct MemoryMapEntry {
    base: u64,
    len: u64,
    class: u32,
    acpi: u32,
}

const MEMORY_MAP: *const MemoryMapEntry = 0x500 as *const MemoryMapEntry;

pub unsafe fn cluster(number: usize) -> usize {
    if number < CLUSTER_COUNT {
        ptr::read((CLUSTER_ADDRESS + number * mem::size_of::<usize>()) as *const usize)
    } else {
        0
    }
}

pub unsafe fn set_cluster(number: usize, address: usize) {
    if number < CLUSTER_COUNT {
        ptr::write((CLUSTER_ADDRESS + number * mem::size_of::<usize>()) as *mut usize,
                   address);
    }
}

pub unsafe fn address_to_cluster(address: usize) -> usize {
    if address >= CLUSTER_ADDRESS + CLUSTER_COUNT * mem::size_of::<usize>() {
        (address - CLUSTER_ADDRESS - CLUSTER_COUNT * mem::size_of::<usize>()) / CLUSTER_SIZE
    } else {
        0
    }
}

pub unsafe fn cluster_to_address(number: usize) -> usize {
    CLUSTER_ADDRESS + CLUSTER_COUNT * mem::size_of::<usize>() + number * CLUSTER_SIZE
}

pub unsafe fn cluster_init() {
    // First, set all clusters to the not present value
    for cluster in 0..CLUSTER_COUNT {
        set_cluster(cluster, 0xFFFFFFFF);
    }

    // Next, set all valid clusters to the free value
    // TODO: Optimize this function
    for i in 0..((0x5000 - 0x500) / mem::size_of::<MemoryMapEntry>()) {
        let entry = &*MEMORY_MAP.offset(i as isize);
        if entry.len > 0 && entry.class == 1 {
            for cluster in 0..CLUSTER_COUNT {
                let address = cluster_to_address(cluster);
                if address as u64 >= entry.base &&
                   (address as u64 + CLUSTER_SIZE as u64) <= (entry.base + entry.len) {
                    set_cluster(cluster, 0);
                }
            }
        }
    }
}

/// Allocate memory
pub unsafe fn alloc(size: usize) -> usize {
    let mut ret = 0;

    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    // Memory allocation must be atomic
    scheduler::end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_aligned(size: usize, align: usize) -> usize {
    let mut ret = 0;

    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 && (count > 0 || cluster_to_address(i) % align == 0) {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    // Memory allocation must be atomic
    scheduler::end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_type<T>() -> *mut T {
    alloc(mem::size_of::<T>()) as *mut T
}

pub unsafe fn alloc_size(ptr: usize) -> usize {
    let mut size = 0;

    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                size += CLUSTER_SIZE;
            } else {
                break;
            }
        }
    }

    // Memory allocation must be atomic
    scheduler::end_no_ints(reenable);

    size
}

pub unsafe fn unalloc(ptr: usize) {
    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            } else {
                break;
            }
        }
    }

    // Memory allocation must be atomic
    scheduler::end_no_ints(reenable);
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    let mut ret = 0;

    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if size == 0 {
        if ptr > 0 {
            unalloc(ptr);
        }
    } else {
        let old_size = alloc_size(ptr);
        if size <= old_size {
            ret = ptr;
        } else {
            ret = alloc(size);
            if ptr > 0 {
                if ret > 0 {
                    let copy_size = cmp::min(old_size, size);

                    ::memmove(ret as *mut u8, ptr as *const u8, copy_size);
                }
                unalloc(ptr);
            }
        }
    }

    scheduler::end_no_ints(reenable);

    ret
}

pub unsafe fn realloc_inplace(ptr: usize, size: usize) -> usize {
    let old_size = alloc_size(ptr);
    if size <= old_size {
        size
    } else {
        old_size
    }
}

pub fn memory_used() -> usize {
    let mut ret = 0;
    unsafe {
        // Memory allocation must be atomic
        let reenable = scheduler::start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) != 0 && cluster(i) != 0xFFFFFFFF {
                ret += CLUSTER_SIZE;
            }
        }

        // Memory allocation must be atomic
        scheduler::end_no_ints(reenable);
    }
    ret
}

pub fn memory_free() -> usize {
    let mut ret = 0;
    unsafe {
        // Memory allocation must be atomic
        let reenable = scheduler::start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                ret += CLUSTER_SIZE;
            }
        }

        // Memory allocation must be atomic
        scheduler::end_no_ints(reenable);
    }
    ret
}
<commit_msg>Doc memory.rs<commit_after>// TODO: Doc the rest

use core::{cmp, intrinsics, mem};
use core::ops::{Index, IndexMut};
use core::ptr;

use scheduler;

use common::paging::PAGE_END;

pub const CLUSTER_ADDRESS: usize = PAGE_END;
pub const CLUSTER_COUNT: usize = 1024 * 1024; // 4 GiB
pub const CLUSTER_SIZE: usize = 4096; // Of 4 K chunks

/// A wrapper around raw pointers
pub struct Memory<T> {
    pub ptr: *mut T,
}

impl<T> Memory<T> {
    /// Create an empty
    pub fn new(count: usize) -> Option<Self> {
        let alloc = unsafe { alloc(count * mem::size_of::<T>()) };
        if alloc > 0 {
            Some(Memory { ptr: alloc as *mut T })
        } else {
            None
        }
    }

    pub fn new_align(count: usize, align: usize) -> Option<Self> {
        let alloc = unsafe { alloc_aligned(count * mem::size_of::<T>(), align) };
        if alloc > 0 {
            Some(Memory { ptr: alloc as *mut T })
        } else {
            None
        }
    }

    /// Renew the memory
    pub fn renew(&mut self, count: usize) -> bool {
        let address = unsafe { realloc(self.ptr as usize, count * mem::size_of::<T>()) };
        if address > 0 {
            self.ptr = address as *mut T;
            true
        } else {
            false
        }
    }

    /// Get the size in bytes
    pub fn size(&self) -> usize {
        unsafe { alloc_size(self.ptr as usize) }
    }

    /// Get the length in T elements
    pub fn length(&self) -> usize {
        unsafe { alloc_size(self.ptr as usize) / mem::size_of::<T>() }
    }

    /// Get the address
    pub unsafe fn address(&self) -> usize {
        self.ptr as usize
    }

    /// Read the memory
    pub unsafe fn read(&self, i: usize) -> T {
        ptr::read(self.ptr.offset(i as isize))
    }

    /// Load the memory
    pub unsafe fn load(&self, i: usize) -> T {
        intrinsics::atomic_singlethreadfence();
        ptr::read(self.ptr.offset(i as isize))
    }

    /// Overwrite the memory
    pub unsafe fn write(&mut self, i: usize, value: T) {
        ptr::write(self.ptr.offset(i as isize), value);
    }

    /// Store the memory
    pub unsafe fn store(&mut self, i: usize, value: T) {
        intrinsics::atomic_singlethreadfence();
        ptr::write(self.ptr.offset(i as isize), value)
    }

    /// Convert into a raw pointer
    pub unsafe fn into_raw(&mut self) -> *mut T {
        let ptr = self.ptr;
        self.ptr = 0 as *mut T;
        ptr
    }
}

impl<T> Drop for Memory<T> {
    fn drop(&mut self) {
        if self.ptr as usize > 0 {
            unsafe { unalloc(self.ptr as usize) };
        }
    }
}

impl<T> Index<usize> for Memory<T> {
    type Output = T;

    fn index<'a>(&'a self, _index: usize) -> &'a T {
        unsafe { &*self.ptr.offset(_index as isize) }
    }
}

impl<T> IndexMut<usize> for Memory<T> {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut T {
        unsafe { &mut *self.ptr.offset(_index as isize) }
    }
}

/// A memory map entry
#[repr(packed)]
struct MemoryMapEntry {
    base: u64,
    len: u64,
    class: u32,
    acpi: u32,
}

const MEMORY_MAP: *const MemoryMapEntry = 0x500 as *const MemoryMapEntry;

/// Get the data (address) of a given cluster
pub unsafe fn cluster(number: usize) -> usize {
    if number < CLUSTER_COUNT {
        ptr::read((CLUSTER_ADDRESS + number * mem::size_of::<usize>()) as *const usize)
    } else {
        0
    }
}

/// Set the address of a cluster
pub unsafe fn set_cluster(number: usize, address: usize) {
    if number < CLUSTER_COUNT {
        ptr::write((CLUSTER_ADDRESS + number * mem::size_of::<usize>()) as *mut usize,
                   address);
    }
}

/// Convert an adress to the cluster number
pub unsafe fn address_to_cluster(address: usize) -> usize {
    if address >= CLUSTER_ADDRESS + CLUSTER_COUNT * mem::size_of::<usize>() {
        (address - CLUSTER_ADDRESS - CLUSTER_COUNT * mem::size_of::<usize>()) / CLUSTER_SIZE
    } else {
        0
    }
}

pub unsafe fn cluster_to_address(number: usize) -> usize {
    CLUSTER_ADDRESS + CLUSTER_COUNT * mem::size_of::<usize>() + number * CLUSTER_SIZE
}

/// Initialize clusters
pub unsafe fn cluster_init() {
    // First, set all clusters to the not present value
    for cluster in 0..CLUSTER_COUNT {
        set_cluster(cluster, 0xFFFFFFFF);
    }

    // Next, set all valid clusters to the free value
    // TODO: Optimize this function
    for i in 0..((0x5000 - 0x500) / mem::size_of::<MemoryMapEntry>()) {
        let entry = &*MEMORY_MAP.offset(i as isize);
        if entry.len > 0 && entry.class == 1 {
            for cluster in 0..CLUSTER_COUNT {
                let address = cluster_to_address(cluster);
                if address as u64 >= entry.base &&
                   (address as u64 + CLUSTER_SIZE as u64) <= (entry.base + entry.len) {
                    set_cluster(cluster, 0);
                }
            }
        }
    }
}

/// Allocate memory
pub unsafe fn alloc(size: usize) -> usize {
    let mut ret = 0;

    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    // Memory allocation must be atomic
    scheduler::end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_aligned(size: usize, align: usize) -> usize {
    let mut ret = 0;

    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 && (count > 0 || cluster_to_address(i) % align == 0) {
                if count == 0 {
                    number = i;
                }
                count += 1;
                if count * CLUSTER_SIZE > size {
                    break;
                }
            } else {
                count = 0;
            }
        }
        if count * CLUSTER_SIZE > size {
            let address = cluster_to_address(number);
            for i in number..number + count {
                set_cluster(i, address);
            }
            ret = address;
        }
    }

    // Memory allocation must be atomic
    scheduler::end_no_ints(reenable);

    ret
}

pub unsafe fn alloc_type<T>() -> *mut T {
    alloc(mem::size_of::<T>()) as *mut T
}

pub unsafe fn alloc_size(ptr: usize) -> usize {
    let mut size = 0;

    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                size += CLUSTER_SIZE;
            } else {
                break;
            }
        }
    }

    // Memory allocation must be atomic
    scheduler::end_no_ints(reenable);

    size
}

pub unsafe fn unalloc(ptr: usize) {
    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            } else {
                break;
            }
        }
    }

    // Memory allocation must be atomic
    scheduler::end_no_ints(reenable);
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    let mut ret = 0;

    // Memory allocation must be atomic
    let reenable = scheduler::start_no_ints();

    if size == 0 {
        if ptr > 0 {
            unalloc(ptr);
        }
    } else {
        let old_size = alloc_size(ptr);
        if size <= old_size {
            ret = ptr;
        } else {
            ret = alloc(size);
            if ptr > 0 {
                if ret > 0 {
                    let copy_size = cmp::min(old_size, size);

                    ::memmove(ret as *mut u8, ptr as *const u8, copy_size);
                }
                unalloc(ptr);
            }
        }
    }

    scheduler::end_no_ints(reenable);

    ret
}

pub unsafe fn realloc_inplace(ptr: usize, size: usize) -> usize {
    let old_size = alloc_size(ptr);
    if size <= old_size {
        size
    } else {
        old_size
    }
}

pub fn memory_used() -> usize {
    let mut ret = 0;
    unsafe {
        // Memory allocation must be atomic
        let reenable = scheduler::start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) != 0 && cluster(i) != 0xFFFFFFFF {
                ret += CLUSTER_SIZE;
            }
        }

        // Memory allocation must be atomic
        scheduler::end_no_ints(reenable);
    }
    ret
}

pub fn memory_free() -> usize {
    let mut ret = 0;
    unsafe {
        // Memory allocation must be atomic
        let reenable = scheduler::start_no_ints();

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 {
                ret += CLUSTER_SIZE;
            }
        }

        // Memory allocation must be atomic
        scheduler::end_no_ints(reenable);
    }
    ret
}
<|endoftext|>


<commit_before><commit_msg>(Maybe) Add statement and block expr parsing.<commit_after><|endoftext|>


<commit_before><commit_msg>added test case for macros with separators error message<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern:expected macro name without module separators

fn main() {
    globnar::brotz!();
}

<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use prelude::*;
use super::support::PathLike;
use super::{Reader, Writer, Seek};
use super::{SeekSet, SeekCur, SeekEnd, SeekStyle};
use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
use rt::io::{io_error, read_error, EndOfFile,
             FileMode, FileAccess, Open, Read, Create, ReadWrite};
use rt::local::Local;
use rt::test::*;

/// Open a file for reading/writing, as indicated by `path`.
pub fn open<P: PathLike>(path: &P,
                         mode: FileMode,
                         access: FileAccess
                        ) -> Option<FileStream> {
    let open_result = unsafe {
        let io: *mut IoFactoryObject = Local::unsafe_borrow();
        (*io).fs_open(path, mode, access)
    };
    match open_result {
        Ok(fd) => Some(FileStream {
            fd: fd,
            last_nread: -1
        }),
        Err(ioerr) => {
            io_error::cond.raise(ioerr);
            None
        }
    }
}

/// Unlink (remove) a file from the filesystem, as indicated
/// by `path`.
pub fn unlink<P: PathLike>(path: &P) {
    let unlink_result = unsafe {
        let io: *mut IoFactoryObject = Local::unsafe_borrow();
        (*io).fs_unlink(path)
    };
    match unlink_result {
        Ok(_) => (),
        Err(ioerr) => {
            io_error::cond.raise(ioerr);
        }
    }
}

/// Abstraction representing *positional* access to a file. In this case,
/// *positional* refers to it keeping an encounter *cursor* of where in the
/// file a subsequent `read` or `write` will begin from. Users of a `FileStream`
/// can `seek` to move the cursor to a given location *within the bounds of the
/// file* and can ask to have the `FileStream` `tell` them the location, in
/// bytes, of the cursor.
///
/// This abstraction is roughly modeled on the access workflow as represented
/// by `open(2)`, `read(2)`, `write(2)` and friends.
///
/// The `open` and `unlink` static methods are provided to manage creation/removal
/// of files. All other methods operatin on an instance of `FileStream`.
pub struct FileStream {
    fd: ~RtioFileStream,
    last_nread: int,
}

impl FileStream {
}

impl Reader for FileStream {
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        match self.fd.read(buf) {
            Ok(read) => {
                self.last_nread = read;
                match read {
                    0 => None,
                    _ => Some(read as uint)
                }
            },
            Err(ioerr) => {
                // EOF is indicated by returning None
                if ioerr.kind != EndOfFile {
                    read_error::cond.raise(ioerr);
                }
                return None;
            }
        }
    }

    fn eof(&mut self) -> bool {
        self.last_nread == 0
    }
}

impl Writer for FileStream {
    fn write(&mut self, buf: &[u8]) {
        match self.fd.write(buf) {
            Ok(_) => (),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
            }
        }
    }

    fn flush(&mut self) {
        match self.fd.flush() {
            Ok(_) => (),
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
            }
        }
    }
}

impl Seek for FileStream {
    fn tell(&self) -> u64 {
        let res = self.fd.tell();
        match res {
            Ok(cursor) => cursor,
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
                return -1;
            }
        }
    }

    fn seek(&mut self, pos: i64, style: SeekStyle) {
        match self.fd.seek(pos, style) {
            Ok(_) => {
                // successful seek resets EOF indicator
                self.last_nread = -1;
                ()
            },
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
            }
        }
    }
}

fn file_test_smoke_test_impl() {
    do run_in_mt_newsched_task {
        let message = "it's alright. have a good time";
        let filename = &Path("./tmp/file_rt_io_file_test.txt");
        {
            let mut write_stream = open(filename, Create, ReadWrite).unwrap();
            write_stream.write(message.as_bytes());
        }
        {
            use str;
            let mut read_stream = open(filename, Open, Read).unwrap();
            let mut read_buf = [0, .. 1028];
            let read_str = match read_stream.read(read_buf).unwrap() {
                -1|0 => fail!("shouldn't happen"),
                n => str::from_utf8(read_buf.slice_to(n))
            };
            assert!(read_str == message.to_owned());
        }
        unlink(filename);
    }
}

#[test]
#[ignore(cfg(windows))] // FIXME #8810
fn file_test_io_smoke_test() {
    file_test_smoke_test_impl();
}

fn file_test_invalid_path_opened_without_create_should_raise_condition_impl() {
    do run_in_mt_newsched_task {
        let filename = &Path("./tmp/file_that_does_not_exist.txt");
        let mut called = false;
        do io_error::cond.trap(|_| {
            called = true;
        }).inside {
            let result = open(filename, Open, Read);
            assert!(result.is_none());
        }
        assert!(called);
    }
}
#[test]
fn file_test_io_invalid_path_opened_without_create_should_raise_condition() {
    file_test_invalid_path_opened_without_create_should_raise_condition_impl();
}

fn file_test_unlinking_invalid_path_should_raise_condition_impl() {
    do run_in_mt_newsched_task {
        let filename = &Path("./tmp/file_another_file_that_does_not_exist.txt");
        let mut called = false;
        do io_error::cond.trap(|_| {
            called = true;
        }).inside {
            unlink(filename);
        }
        assert!(called);
    }
}
#[test]
fn file_test_iounlinking_invalid_path_should_raise_condition() {
    file_test_unlinking_invalid_path_should_raise_condition_impl();
}

fn file_test_io_non_positional_read_impl() {
    do run_in_mt_newsched_task {
        use str;
        let message = "ten-four";
        let mut read_mem = [0, .. 8];
        let filename = &Path("./tmp/file_rt_io_file_test_positional.txt");
        {
            let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(message.as_bytes());
        }
        {
            let mut read_stream = open(filename, Open, Read).unwrap();
            {
                let read_buf = read_mem.mut_slice(0, 4);
                read_stream.read(read_buf);
            }
            {
                let read_buf = read_mem.mut_slice(4, 8);
                read_stream.read(read_buf);
            }
        }
        unlink(filename);
        let read_str = str::from_utf8(read_mem);
        assert!(read_str == message.to_owned());
    }
}

#[test]
#[ignore(cfg(windows))] // FIXME #8810
fn file_test_io_non_positional_read() {
    file_test_io_non_positional_read_impl();
}

fn file_test_io_seeking_impl() {
    do run_in_mt_newsched_task {
        use str;
        let message = "ten-four";
        let mut read_mem = [0, .. 4];
        let set_cursor = 4 as u64;
        let mut tell_pos_pre_read;
        let mut tell_pos_post_read;
        let filename = &Path("./tmp/file_rt_io_file_test_seeking.txt");
        {
            let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(message.as_bytes());
        }
        {
            let mut read_stream = open(filename, Open, Read).unwrap();
            read_stream.seek(set_cursor as i64, SeekSet);
            tell_pos_pre_read = read_stream.tell();
            read_stream.read(read_mem);
            tell_pos_post_read = read_stream.tell();
        }
        unlink(filename);
        let read_str = str::from_utf8(read_mem);
        assert!(read_str == message.slice(4, 8).to_owned());
        assert!(tell_pos_pre_read == set_cursor);
        assert!(tell_pos_post_read == message.len() as u64);
    }
}
#[test]
#[ignore(cfg(windows))] // FIXME #8810
fn file_test_io_seek_and_tell_smoke_test() {
    file_test_io_seeking_impl();
}

fn file_test_io_seek_and_write_impl() {
    use io;
    do run_in_mt_newsched_task {
        use str;
        let initial_msg =   "food-is-yummy";
        let overwrite_msg =    "-the-bar!!";
        let final_msg =     "foo-the-bar!!";
        let seek_idx = 3;
        let mut read_mem = [0, .. 13];
        let filename = &Path("./tmp/file_rt_io_file_test_seek_and_write.txt");
        {
            let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(initial_msg.as_bytes());
            rw_stream.seek(seek_idx as i64, SeekSet);
            rw_stream.write(overwrite_msg.as_bytes());
        }
        {
            let mut read_stream = open(filename, Open, Read).unwrap();
            read_stream.read(read_mem);
        }
        unlink(filename);
        let read_str = str::from_utf8(read_mem);
        io::println(fmt!("read_str: '%?' final_msg: '%?'", read_str, final_msg));
        assert!(read_str == final_msg.to_owned());
    }
}
#[test]
#[ignore(cfg(windows))] // FIXME #8810
fn file_test_io_seek_and_write() {
    file_test_io_seek_and_write_impl();
}

fn file_test_io_seek_shakedown_impl() {
    do run_in_mt_newsched_task {
        use str;          // 01234567890123
        let initial_msg =   "qwer-asdf-zxcv";
        let chunk_one = "qwer";
        let chunk_two = "asdf";
        let chunk_three = "zxcv";
        let mut read_mem = [0, .. 4];
        let filename = &Path("./tmp/file_rt_io_file_test_seek_shakedown.txt");
        {
            let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(initial_msg.as_bytes());
        }
        {
            let mut read_stream = open(filename, Open, Read).unwrap();

            read_stream.seek(-4, SeekEnd);
            read_stream.read(read_mem);
            let read_str = str::from_utf8(read_mem);
            assert!(read_str == chunk_three.to_owned());

            read_stream.seek(-9, SeekCur);
            read_stream.read(read_mem);
            let read_str = str::from_utf8(read_mem);
            assert!(read_str == chunk_two.to_owned());

            read_stream.seek(0, SeekSet);
            read_stream.read(read_mem);
            let read_str = str::from_utf8(read_mem);
            assert!(read_str == chunk_one.to_owned());
        }
        unlink(filename);
    }
}
#[test]
#[ignore(cfg(windows))] // FIXME #8810
fn file_test_io_seek_shakedown() {
    file_test_io_seek_shakedown_impl();
}
<commit_msg>std::rt::io::file: Enable I/O tests on Win32<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use prelude::*;
use super::support::PathLike;
use super::{Reader, Writer, Seek};
use super::{SeekSet, SeekCur, SeekEnd, SeekStyle};
use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
use rt::io::{io_error, read_error, EndOfFile,
             FileMode, FileAccess, Open, Read, Create, ReadWrite};
use rt::local::Local;
use rt::test::*;

/// Open a file for reading/writing, as indicated by `path`.
pub fn open<P: PathLike>(path: &P,
                         mode: FileMode,
                         access: FileAccess
                        ) -> Option<FileStream> {
    let open_result = unsafe {
        let io: *mut IoFactoryObject = Local::unsafe_borrow();
        (*io).fs_open(path, mode, access)
    };
    match open_result {
        Ok(fd) => Some(FileStream {
            fd: fd,
            last_nread: -1
        }),
        Err(ioerr) => {
            io_error::cond.raise(ioerr);
            None
        }
    }
}

/// Unlink (remove) a file from the filesystem, as indicated
/// by `path`.
pub fn unlink<P: PathLike>(path: &P) {
    let unlink_result = unsafe {
        let io: *mut IoFactoryObject = Local::unsafe_borrow();
        (*io).fs_unlink(path)
    };
    match unlink_result {
        Ok(_) => (),
        Err(ioerr) => {
            io_error::cond.raise(ioerr);
        }
    }
}

/// Abstraction representing *positional* access to a file. In this case,
/// *positional* refers to it keeping an encounter *cursor* of where in the
/// file a subsequent `read` or `write` will begin from. Users of a `FileStream`
/// can `seek` to move the cursor to a given location *within the bounds of the
/// file* and can ask to have the `FileStream` `tell` them the location, in
/// bytes, of the cursor.
///
/// This abstraction is roughly modeled on the access workflow as represented
/// by `open(2)`, `read(2)`, `write(2)` and friends.
///
/// The `open` and `unlink` static methods are provided to manage creation/removal
/// of files. All other methods operatin on an instance of `FileStream`.
pub struct FileStream {
    fd: ~RtioFileStream,
    last_nread: int,
}

impl FileStream {
}

impl Reader for FileStream {
    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
        match self.fd.read(buf) {
            Ok(read) => {
                self.last_nread = read;
                match read {
                    0 => None,
                    _ => Some(read as uint)
                }
            },
            Err(ioerr) => {
                // EOF is indicated by returning None
                if ioerr.kind != EndOfFile {
                    read_error::cond.raise(ioerr);
                }
                return None;
            }
        }
    }

    fn eof(&mut self) -> bool {
        self.last_nread == 0
    }
}

impl Writer for FileStream {
    fn write(&mut self, buf: &[u8]) {
        match self.fd.write(buf) {
            Ok(_) => (),
            Err(ioerr) => {
                io_error::cond.raise(ioerr);
            }
        }
    }

    fn flush(&mut self) {
        match self.fd.flush() {
            Ok(_) => (),
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
            }
        }
    }
}

impl Seek for FileStream {
    fn tell(&self) -> u64 {
        let res = self.fd.tell();
        match res {
            Ok(cursor) => cursor,
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
                return -1;
            }
        }
    }

    fn seek(&mut self, pos: i64, style: SeekStyle) {
        match self.fd.seek(pos, style) {
            Ok(_) => {
                // successful seek resets EOF indicator
                self.last_nread = -1;
                ()
            },
            Err(ioerr) => {
                read_error::cond.raise(ioerr);
            }
        }
    }
}

fn file_test_smoke_test_impl() {
    do run_in_mt_newsched_task {
        let message = "it's alright. have a good time";
        let filename = &Path("./tmp/file_rt_io_file_test.txt");
        {
            let mut write_stream = open(filename, Create, ReadWrite).unwrap();
            write_stream.write(message.as_bytes());
        }
        {
            use str;
            let mut read_stream = open(filename, Open, Read).unwrap();
            let mut read_buf = [0, .. 1028];
            let read_str = match read_stream.read(read_buf).unwrap() {
                -1|0 => fail!("shouldn't happen"),
                n => str::from_utf8(read_buf.slice_to(n))
            };
            assert!(read_str == message.to_owned());
        }
        unlink(filename);
    }
}

#[test]
fn file_test_io_smoke_test() {
    file_test_smoke_test_impl();
}

fn file_test_invalid_path_opened_without_create_should_raise_condition_impl() {
    do run_in_mt_newsched_task {
        let filename = &Path("./tmp/file_that_does_not_exist.txt");
        let mut called = false;
        do io_error::cond.trap(|_| {
            called = true;
        }).inside {
            let result = open(filename, Open, Read);
            assert!(result.is_none());
        }
        assert!(called);
    }
}
#[test]
fn file_test_io_invalid_path_opened_without_create_should_raise_condition() {
    file_test_invalid_path_opened_without_create_should_raise_condition_impl();
}

fn file_test_unlinking_invalid_path_should_raise_condition_impl() {
    do run_in_mt_newsched_task {
        let filename = &Path("./tmp/file_another_file_that_does_not_exist.txt");
        let mut called = false;
        do io_error::cond.trap(|_| {
            called = true;
        }).inside {
            unlink(filename);
        }
        assert!(called);
    }
}
#[test]
fn file_test_iounlinking_invalid_path_should_raise_condition() {
    file_test_unlinking_invalid_path_should_raise_condition_impl();
}

fn file_test_io_non_positional_read_impl() {
    do run_in_mt_newsched_task {
        use str;
        let message = "ten-four";
        let mut read_mem = [0, .. 8];
        let filename = &Path("./tmp/file_rt_io_file_test_positional.txt");
        {
            let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(message.as_bytes());
        }
        {
            let mut read_stream = open(filename, Open, Read).unwrap();
            {
                let read_buf = read_mem.mut_slice(0, 4);
                read_stream.read(read_buf);
            }
            {
                let read_buf = read_mem.mut_slice(4, 8);
                read_stream.read(read_buf);
            }
        }
        unlink(filename);
        let read_str = str::from_utf8(read_mem);
        assert!(read_str == message.to_owned());
    }
}

#[test]
fn file_test_io_non_positional_read() {
    file_test_io_non_positional_read_impl();
}

fn file_test_io_seeking_impl() {
    do run_in_mt_newsched_task {
        use str;
        let message = "ten-four";
        let mut read_mem = [0, .. 4];
        let set_cursor = 4 as u64;
        let mut tell_pos_pre_read;
        let mut tell_pos_post_read;
        let filename = &Path("./tmp/file_rt_io_file_test_seeking.txt");
        {
            let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(message.as_bytes());
        }
        {
            let mut read_stream = open(filename, Open, Read).unwrap();
            read_stream.seek(set_cursor as i64, SeekSet);
            tell_pos_pre_read = read_stream.tell();
            read_stream.read(read_mem);
            tell_pos_post_read = read_stream.tell();
        }
        unlink(filename);
        let read_str = str::from_utf8(read_mem);
        assert!(read_str == message.slice(4, 8).to_owned());
        assert!(tell_pos_pre_read == set_cursor);
        assert!(tell_pos_post_read == message.len() as u64);
    }
}

#[test]
fn file_test_io_seek_and_tell_smoke_test() {
    file_test_io_seeking_impl();
}

fn file_test_io_seek_and_write_impl() {
    use io;
    do run_in_mt_newsched_task {
        use str;
        let initial_msg =   "food-is-yummy";
        let overwrite_msg =    "-the-bar!!";
        let final_msg =     "foo-the-bar!!";
        let seek_idx = 3;
        let mut read_mem = [0, .. 13];
        let filename = &Path("./tmp/file_rt_io_file_test_seek_and_write.txt");
        {
            let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(initial_msg.as_bytes());
            rw_stream.seek(seek_idx as i64, SeekSet);
            rw_stream.write(overwrite_msg.as_bytes());
        }
        {
            let mut read_stream = open(filename, Open, Read).unwrap();
            read_stream.read(read_mem);
        }
        unlink(filename);
        let read_str = str::from_utf8(read_mem);
        io::println(fmt!("read_str: '%?' final_msg: '%?'", read_str, final_msg));
        assert!(read_str == final_msg.to_owned());
    }
}

#[test]
fn file_test_io_seek_and_write() {
    file_test_io_seek_and_write_impl();
}

fn file_test_io_seek_shakedown_impl() {
    do run_in_mt_newsched_task {
        use str;          // 01234567890123
        let initial_msg =   "qwer-asdf-zxcv";
        let chunk_one = "qwer";
        let chunk_two = "asdf";
        let chunk_three = "zxcv";
        let mut read_mem = [0, .. 4];
        let filename = &Path("./tmp/file_rt_io_file_test_seek_shakedown.txt");
        {
            let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
            rw_stream.write(initial_msg.as_bytes());
        }
        {
            let mut read_stream = open(filename, Open, Read).unwrap();

            read_stream.seek(-4, SeekEnd);
            read_stream.read(read_mem);
            let read_str = str::from_utf8(read_mem);
            assert!(read_str == chunk_three.to_owned());

            read_stream.seek(-9, SeekCur);
            read_stream.read(read_mem);
            let read_str = str::from_utf8(read_mem);
            assert!(read_str == chunk_two.to_owned());

            read_stream.seek(0, SeekSet);
            read_stream.read(read_mem);
            let read_str = str::from_utf8(read_mem);
            assert!(read_str == chunk_one.to_owned());
        }
        unlink(filename);
    }
}

#[test]
fn file_test_io_seek_shakedown() {
    file_test_io_seek_shakedown_impl();
}
<|endoftext|>


<commit_before><commit_msg>Test(delete): more commentary on the failing ignored test<commit_after><|endoftext|>