<commit_before>use mbc::{MBC, ram_size};
use std::path;
use std::io::prelude::*;
use std::fs;
use podio::{BigEndian, ReadPodExt, WritePodExt};
use time;

pub struct MBC3 {
    rom: Vec<u8>,
    ram: Vec<u8>,
    rombank: usize,
    rambank: usize,
    ram_on: bool,
    savepath: Option<path::PathBuf>,
    rtc_ram: [u8; 5],
    rtc_lock: bool,
    rtc_zero: Option<i64>,
}

impl MBC3 {
    pub fn new(data: Vec<u8>, file: path::PathBuf) -> ::StrResult<MBC3> {
        let subtype = data[0x147];
        let svpath = match subtype {
            0x0F | 0x10 | 0x13 => Some(file.with_extension("gbsave")),
            _ => None,
        };
        let ramsize = match subtype {
            0x10 | 0x12 | 0x13 => ram_size(data[0x149]),
            _ => 0,
        };
        let rtc = match subtype {
            0x0F | 0x10 => Some(0),
            _ => None,
        };

        let mut res = MBC3 {
            rom: data,
            ram: ::std::iter::repeat(0u8).take(ramsize).collect(),
            rombank: 1,
            rambank: 0,
            ram_on: false,
            savepath: svpath,
            rtc_ram: [0u8; 5],
            rtc_lock: false,
            rtc_zero: rtc,
        };
        res.loadram().map(|_| res)
    }

    fn loadram(&mut self) -> ::StrResult<()> {
        match self.savepath {
            None => Ok(()),
            Some(ref savepath) => {
                let mut file = match fs::File::open(savepath) {
                    Ok(f) => f,
                    Err(..) => return Err("Could not open file"),
                };
                let rtc = try!(file.read_i64::<BigEndian>().map_err(|_| "Could not read RTC"));
                if self.rtc_zero.is_some() { self.rtc_zero = Some(rtc); }
                let mut data = vec![];
                match file.read_to_end(&mut data) {
                    Err(..) => Err("Could not read ROM"),
                    Ok(..) => { self.ram = data; Ok(()) },
                }
            },
        }
    }

    fn calc_rtc_reg(&mut self) {
        let tzero = match self.rtc_zero {
            Some(t) => t,
            None => return,
        };
        if self.rtc_ram[4] & 0x40 == 0x40 { return }

        let difftime: i64 = match time::now().to_timespec().sec - tzero {
            n if n >= 0 => { n },
            _ => { 0 },
        };
        self.rtc_ram[0] = (difftime % 60) as u8;
        self.rtc_ram[1] = ((difftime / 60) % 60) as u8;
        self.rtc_ram[2] = ((difftime / 3600) % 24) as u8;
        let days: i64 = difftime / (3600*24);
        self.rtc_ram[3] = days as u8;
        self.rtc_ram[4] = (self.rtc_ram[4] & 0xFE) | (((days >> 8) & 0x01) as u8);
        if days >= 512 {
            self.rtc_ram[4] |= 0x80;
            self.calc_rtc_zero();
        }
    }

    fn calc_rtc_zero(&mut self) {
        if self.rtc_zero.is_none() { return }
        let mut difftime: i64 = time::now().to_timespec().sec;
        difftime -= self.rtc_ram[0] as i64;
        difftime -= (self.rtc_ram[1] as i64) * 60;
        difftime -= (self.rtc_ram[2] as i64) * 3600;
        let days = ((self.rtc_ram[4] as i64 & 0x1) << 8) | (self.rtc_ram[3] as i64);
        difftime -= days * 3600 * 24;
        self.rtc_zero = Some(difftime);
    }
}

impl Drop for MBC3 {
    fn drop(&mut self) {
        match self.savepath {
            None => {},
            Some(ref path) => {
                let mut file = match fs::File::create(path) {
                    Ok(f) => f,
                    Err(..) => return,
                };
                let rtc = match self.rtc_zero {
                    Some(t) => t,
                    None => 0,
                };
                let mut ok = true;
                if ok { ok = file.write_i64::<BigEndian>(rtc).is_ok(); };
                if ok { let _ = file.write_all(&*self.ram); };
            },
        };
    }
}

impl MBC for MBC3 {
    fn readrom(&self, a: u16) -> u8 {
        if a < 0x4000 { self.rom[a as usize] }
        else { self.rom[self.rombank * 0x4000 | ((a as usize) & 0x3FFF)] }
    }
    fn readram(&self, a: u16) -> u8 {
        if !self.ram_on { return 0 }
        if self.rambank <= 3 {
            self.ram[self.rambank * 0x2000 | ((a as usize) & 0x1FFF)]
        } else {
            self.rtc_ram[self.rambank - 0x08]
        }
    }
    fn writerom(&mut self, a: u16, v: u8) {
        match a {
            0x0000 ... 0x1FFF => self.ram_on = v == 0x0A,
            0x2000 ... 0x3FFF => {
                self.rombank = match v & 0x7F { 0 => 1, n => n as usize }
            },
            0x4000 ... 0x5FFF => self.rambank = v as usize,
            0x6000 ... 0x7FFF => match v {
                0 => self.rtc_lock = false,
                1 => {
                    if !self.rtc_lock { self.calc_rtc_reg(); };
                    self.rtc_lock = true;
                },
                _ => {},
            },
            _ => panic!("Could not write to {:04X} (MBC3)", a),
        }
    }
    fn writeram(&mut self, a: u16, v: u8) {
        if self.ram_on == false { return }
        if self.rambank <= 3 {
            self.ram[self.rambank * 0x2000 | ((a as usize) & 0x1FFF)] = v;
        } else {
            self.rtc_ram[self.rambank - 0x8] = v;
            self.calc_rtc_zero();
        }
    }
}
<commit_msg>Not being able to read ROM is not an error<commit_after>use mbc::{MBC, ram_size};
use std::path;
use std::io::prelude::*;
use std::fs;
use podio::{BigEndian, ReadPodExt, WritePodExt};
use time;

pub struct MBC3 {
    rom: Vec<u8>,
    ram: Vec<u8>,
    rombank: usize,
    rambank: usize,
    ram_on: bool,
    savepath: Option<path::PathBuf>,
    rtc_ram: [u8; 5],
    rtc_lock: bool,
    rtc_zero: Option<i64>,
}

impl MBC3 {
    pub fn new(data: Vec<u8>, file: path::PathBuf) -> ::StrResult<MBC3> {
        let subtype = data[0x147];
        let svpath = match subtype {
            0x0F | 0x10 | 0x13 => Some(file.with_extension("gbsave")),
            _ => None,
        };
        let ramsize = match subtype {
            0x10 | 0x12 | 0x13 => ram_size(data[0x149]),
            _ => 0,
        };
        let rtc = match subtype {
            0x0F | 0x10 => Some(0),
            _ => None,
        };

        let mut res = MBC3 {
            rom: data,
            ram: ::std::iter::repeat(0u8).take(ramsize).collect(),
            rombank: 1,
            rambank: 0,
            ram_on: false,
            savepath: svpath,
            rtc_ram: [0u8; 5],
            rtc_lock: false,
            rtc_zero: rtc,
        };
        res.loadram().map(|_| res)
    }

    fn loadram(&mut self) -> ::StrResult<()> {
        match self.savepath {
            None => Ok(()),
            Some(ref savepath) => {
                let mut file = match fs::File::open(savepath) {
                    Ok(f) => f,
                    Err(..) => return Ok(()),
                };
                let rtc = try!(file.read_i64::<BigEndian>().map_err(|_| "Could not read RTC"));
                if self.rtc_zero.is_some() { self.rtc_zero = Some(rtc); }
                let mut data = vec![];
                match file.read_to_end(&mut data) {
                    Err(..) => Err("Could not read ROM"),
                    Ok(..) => { self.ram = data; Ok(()) },
                }
            },
        }
    }

    fn calc_rtc_reg(&mut self) {
        let tzero = match self.rtc_zero {
            Some(t) => t,
            None => return,
        };
        if self.rtc_ram[4] & 0x40 == 0x40 { return }

        let difftime: i64 = match time::now().to_timespec().sec - tzero {
            n if n >= 0 => { n },
            _ => { 0 },
        };
        self.rtc_ram[0] = (difftime % 60) as u8;
        self.rtc_ram[1] = ((difftime / 60) % 60) as u8;
        self.rtc_ram[2] = ((difftime / 3600) % 24) as u8;
        let days: i64 = difftime / (3600*24);
        self.rtc_ram[3] = days as u8;
        self.rtc_ram[4] = (self.rtc_ram[4] & 0xFE) | (((days >> 8) & 0x01) as u8);
        if days >= 512 {
            self.rtc_ram[4] |= 0x80;
            self.calc_rtc_zero();
        }
    }

    fn calc_rtc_zero(&mut self) {
        if self.rtc_zero.is_none() { return }
        let mut difftime: i64 = time::now().to_timespec().sec;
        difftime -= self.rtc_ram[0] as i64;
        difftime -= (self.rtc_ram[1] as i64) * 60;
        difftime -= (self.rtc_ram[2] as i64) * 3600;
        let days = ((self.rtc_ram[4] as i64 & 0x1) << 8) | (self.rtc_ram[3] as i64);
        difftime -= days * 3600 * 24;
        self.rtc_zero = Some(difftime);
    }
}

impl Drop for MBC3 {
    fn drop(&mut self) {
        match self.savepath {
            None => {},
            Some(ref path) => {
                let mut file = match fs::File::create(path) {
                    Ok(f) => f,
                    Err(..) => return,
                };
                let rtc = match self.rtc_zero {
                    Some(t) => t,
                    None => 0,
                };
                let mut ok = true;
                if ok { ok = file.write_i64::<BigEndian>(rtc).is_ok(); };
                if ok { let _ = file.write_all(&*self.ram); };
            },
        };
    }
}

impl MBC for MBC3 {
    fn readrom(&self, a: u16) -> u8 {
        if a < 0x4000 { self.rom[a as usize] }
        else { self.rom[self.rombank * 0x4000 | ((a as usize) & 0x3FFF)] }
    }
    fn readram(&self, a: u16) -> u8 {
        if !self.ram_on { return 0 }
        if self.rambank <= 3 {
            self.ram[self.rambank * 0x2000 | ((a as usize) & 0x1FFF)]
        } else {
            self.rtc_ram[self.rambank - 0x08]
        }
    }
    fn writerom(&mut self, a: u16, v: u8) {
        match a {
            0x0000 ... 0x1FFF => self.ram_on = v == 0x0A,
            0x2000 ... 0x3FFF => {
                self.rombank = match v & 0x7F { 0 => 1, n => n as usize }
            },
            0x4000 ... 0x5FFF => self.rambank = v as usize,
            0x6000 ... 0x7FFF => match v {
                0 => self.rtc_lock = false,
                1 => {
                    if !self.rtc_lock { self.calc_rtc_reg(); };
                    self.rtc_lock = true;
                },
                _ => {},
            },
            _ => panic!("Could not write to {:04X} (MBC3)", a),
        }
    }
    fn writeram(&mut self, a: u16, v: u8) {
        if self.ram_on == false { return }
        if self.rambank <= 3 {
            self.ram[self.rambank * 0x2000 | ((a as usize) & 0x1FFF)] = v;
        } else {
            self.rtc_ram[self.rambank - 0x8] = v;
            self.calc_rtc_zero();
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 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.

//! # The Rust Standard Library
//!
//! The Rust Standard Library provides the essential runtime
//! functionality for building portable Rust software.
//! It is linked to all Rust crates by default.
//!
//! ## Intrinsic types and operations
//!
//! The [`ptr`](ptr/index.html) and [`mem`](mem/index.html)
//! modules deal with unsafe pointers and memory manipulation.
//! [`marker`](marker/index.html) defines the special built-in traits,
//! and [`raw`](raw/index.html) the runtime representation of Rust types.
//! These are some of the lowest-level building blocks in Rust.
//!
//! ## Math on primitive types and math traits
//!
//! Although basic operations on primitive types are implemented
//! directly by the compiler, the standard library additionally
//! defines many common operations through traits defined in
//! mod [`num`](num/index.html).
//!
//! ## Pervasive types
//!
//! The [`option`](option/index.html) and [`result`](result/index.html)
//! modules define optional and error-handling types, `Option` and `Result`.
//! [`iter`](iter/index.html) defines Rust's iterator protocol
//! along with a wide variety of iterators.
//! [`Cell` and `RefCell`](cell/index.html) are for creating types that
//! manage their own mutability.
//!
//! ## Vectors, slices and strings
//!
//! The common container type, `Vec`, a growable vector backed by an array,
//! lives in the [`vec`](vec/index.html) module. Contiguous, unsized regions
//! of memory, `[T]`, commonly called "slices", and their borrowed versions,
//! `&[T]`, commonly called "borrowed slices", are built-in types for which the
//! for which the [`slice`](slice/index.html) module defines many methods.
//!
//! `&str`, a UTF-8 string, is a built-in type, and the standard library
//! defines methods for it on a variety of traits in the
//! [`str`](str/index.html) module. Rust strings are immutable;
//! use the `String` type defined in [`string`](string/index.html)
//! for a mutable string builder.
//!
//! For converting to strings use the [`format!`](fmt/index.html)
//! macro, and for converting from strings use the
//! [`FromStr`](str/trait.FromStr.html) trait.
//!
//! ## Platform abstractions
//!
//! Besides basic data types, the standard library is largely concerned
//! with abstracting over differences in common platforms, most notably
//! Windows and Unix derivatives. The [`os`](os/index.html) module
//! provides a number of basic functions for interacting with the
//! operating environment, including program arguments, environment
//! variables, and directory navigation. The [`path`](path/index.html)
//! module encapsulates the platform-specific rules for dealing
//! with file paths.
//!
//! `std` also includes the [`ffi`](ffi/index.html) module for interoperating
//! with the C language.
//!
//! ## Concurrency, I/O, and the runtime
//!
//! The [`thread`](thread/index.html) module contains Rust's threading abstractions.
//! [`sync`](sync/index.html) contains further, primitive, shared memory types,
//! including [`atomic`](sync/atomic/index.html), and [`mpsc`](sync/mpsc/index.html),
//! which contains the channel types for message passing.
//!
//! Common types of I/O, including files, TCP, UDP, pipes, Unix domain sockets,
//! timers, and process spawning, are defined in the
//! [`old_io`](old_io/index.html) module.
//!
//! Rust's I/O and concurrency depends on a small runtime interface
//! that lives, along with its support code, in mod [`rt`](rt/index.html).
//! While a notable part of the standard library's architecture, this
//! module is not intended for public use.
//!
//! ## The Rust prelude and macros
//!
//! Finally, the [`prelude`](prelude/index.html) defines a
//! common set of traits, types, and functions that are made available
//! to all code by default. [`macros`](macros/index.html) contains
//! all the standard macros, such as `assert!`, `panic!`, `println!`,
//! and `format!`, also available to all Rust code.
// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "std"]
#![stable(feature = "rust1", since = "1.0.0")]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]
#![doc(test(no_crate_inject))]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(linkage, thread_local, asm)]
#![feature(optin_builtin_traits)]
#![feature(rand)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(macro_reexport)]
#![feature(unique)]
#![feature(convert)]
#![feature(allow_internal_unstable)]
#![feature(str_char)]
#![feature(into_cow)]
#![feature(slice_patterns)]
#![feature(std_misc)]
#![feature(debug_builders)]
#![cfg_attr(test, feature(test, rustc_private, std_misc))]

// Don't link to std. We are std.
#![feature(no_std)]
#![no_std]

#![allow(trivial_casts)]
#![deny(missing_docs)]

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate log;

#[macro_use]
#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
    unreachable, unimplemented, write, writeln)]
extern crate core;

#[macro_use]
#[macro_reexport(vec, format)]
extern crate collections as core_collections;

#[allow(deprecated)] extern crate rand as core_rand;
extern crate alloc;
extern crate unicode;
extern crate libc;

#[macro_use] #[no_link] extern crate rustc_bitflags;

// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate std as realstd;
#[cfg(test)] pub use realstd::marker;
#[cfg(test)] pub use realstd::ops;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::boxed;

// NB: These reexports are in the order they should be listed in rustdoc

pub use core::any;
pub use core::cell;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
pub use core::convert;
pub use core::default;
#[allow(deprecated)]
pub use core::finally;
pub use core::hash;
pub use core::intrinsics;
pub use core::iter;
#[cfg(not(test))] pub use core::marker;
pub use core::mem;
#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::simd;
pub use core::result;
pub use core::option;
pub use core::error;

#[cfg(not(test))] pub use alloc::boxed;
pub use alloc::rc;

pub use core_collections::borrow;
pub use core_collections::fmt;
pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::vec;

pub use unicode::char;

/* Exported macros */

#[macro_use]
mod macros;

mod rtdeps;

/* The Prelude. */

pub mod prelude;

/* Primitive types */

// NB: slice and str are primitive types too, but their module docs + primitive doc pages
// are inlined from the public re-exports of core_collections::{slice, str} above.

#[path = "num/float_macros.rs"]
#[macro_use]
mod float_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"]  pub mod isize;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod ascii;
pub mod thunk;

/* Common traits */

pub mod num;

/* Runtime and platform support */

#[macro_use]
pub mod thread;

pub mod collections;
pub mod dynamic_lib;
pub mod env;
pub mod ffi;
pub mod fs;
pub mod io;
pub mod net;
pub mod old_io;
pub mod old_path;
pub mod os;
pub mod path;
pub mod process;
pub mod rand;
pub mod sync;
pub mod time;

#[macro_use]
#[path = "sys/common/mod.rs"] mod sys_common;

#[cfg(unix)]
#[path = "sys/unix/mod.rs"] mod sys;
#[cfg(windows)]
#[path = "sys/windows/mod.rs"] mod sys;

pub mod rt;
mod panicking;

// Modules that exist purely to document + host impl docs for primitive types

mod array;
mod bool;
mod unit;
mod tuple;

// A curious inner-module that's not exported that contains the binding
// 'std' so that macro-expanded references to std::error and such
// can be resolved within libstd.
#[doc(hidden)]
mod std {
    pub use sync; // used for select!()
    pub use error; // used for try!()
    pub use fmt; // used for any formatting strings
    #[allow(deprecated)]
    pub use old_io; // used for println!()
    pub use option; // used for bitflags!{}
    pub use rt; // used for panic!()
    pub use vec; // used for vec![]
    pub use cell; // used for tls!
    pub use thread; // used for thread_local!
    pub use marker;  // used for tls!
    pub use ops; // used for bitflags!

    // The test runner calls ::std::env::args() but really wants realstd
    #[cfg(test)] pub use realstd::env as env;
    // The test runner requires std::slice::Vector, so re-export std::slice just for it.
    //
    // It is also used in vec![]
    pub use slice;

    pub use boxed; // used for vec![]
}
<commit_msg>rollup merge of #23882: wettowelreactor/patch-2<commit_after>// Copyright 2012-2014 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.

//! # The Rust Standard Library
//!
//! The Rust Standard Library provides the essential runtime
//! functionality for building portable Rust software.
//! It is linked to all Rust crates by default.
//!
//! ## Intrinsic types and operations
//!
//! The [`ptr`](ptr/index.html) and [`mem`](mem/index.html)
//! modules deal with unsafe pointers and memory manipulation.
//! [`marker`](marker/index.html) defines the special built-in traits,
//! and [`raw`](raw/index.html) the runtime representation of Rust types.
//! These are some of the lowest-level building blocks in Rust.
//!
//! ## Math on primitive types and math traits
//!
//! Although basic operations on primitive types are implemented
//! directly by the compiler, the standard library additionally
//! defines many common operations through traits defined in
//! mod [`num`](num/index.html).
//!
//! ## Pervasive types
//!
//! The [`option`](option/index.html) and [`result`](result/index.html)
//! modules define optional and error-handling types, `Option` and `Result`.
//! [`iter`](iter/index.html) defines Rust's iterator protocol
//! along with a wide variety of iterators.
//! [`Cell` and `RefCell`](cell/index.html) are for creating types that
//! manage their own mutability.
//!
//! ## Vectors, slices and strings
//!
//! The common container type, `Vec`, a growable vector backed by an array,
//! lives in the [`vec`](vec/index.html) module. Contiguous, unsized regions
//! of memory, `[T]`, commonly called "slices", and their borrowed versions,
//! `&[T]`, commonly called "borrowed slices", are built-in types for which the
//! [`slice`](slice/index.html) module defines many methods.
//!
//! `&str`, a UTF-8 string, is a built-in type, and the standard library
//! defines methods for it on a variety of traits in the
//! [`str`](str/index.html) module. Rust strings are immutable;
//! use the `String` type defined in [`string`](string/index.html)
//! for a mutable string builder.
//!
//! For converting to strings use the [`format!`](fmt/index.html)
//! macro, and for converting from strings use the
//! [`FromStr`](str/trait.FromStr.html) trait.
//!
//! ## Platform abstractions
//!
//! Besides basic data types, the standard library is largely concerned
//! with abstracting over differences in common platforms, most notably
//! Windows and Unix derivatives. The [`os`](os/index.html) module
//! provides a number of basic functions for interacting with the
//! operating environment, including program arguments, environment
//! variables, and directory navigation. The [`path`](path/index.html)
//! module encapsulates the platform-specific rules for dealing
//! with file paths.
//!
//! `std` also includes the [`ffi`](ffi/index.html) module for interoperating
//! with the C language.
//!
//! ## Concurrency, I/O, and the runtime
//!
//! The [`thread`](thread/index.html) module contains Rust's threading abstractions.
//! [`sync`](sync/index.html) contains further, primitive, shared memory types,
//! including [`atomic`](sync/atomic/index.html), and [`mpsc`](sync/mpsc/index.html),
//! which contains the channel types for message passing.
//!
//! Common types of I/O, including files, TCP, UDP, pipes, Unix domain sockets,
//! timers, and process spawning, are defined in the
//! [`old_io`](old_io/index.html) module.
//!
//! Rust's I/O and concurrency depends on a small runtime interface
//! that lives, along with its support code, in mod [`rt`](rt/index.html).
//! While a notable part of the standard library's architecture, this
//! module is not intended for public use.
//!
//! ## The Rust prelude and macros
//!
//! Finally, the [`prelude`](prelude/index.html) defines a
//! common set of traits, types, and functions that are made available
//! to all code by default. [`macros`](macros/index.html) contains
//! all the standard macros, such as `assert!`, `panic!`, `println!`,
//! and `format!`, also available to all Rust code.
// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "std"]
#![stable(feature = "rust1", since = "1.0.0")]
#![staged_api]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]
#![doc(test(no_crate_inject))]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(linkage, thread_local, asm)]
#![feature(optin_builtin_traits)]
#![feature(rand)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(macro_reexport)]
#![feature(unique)]
#![feature(convert)]
#![feature(allow_internal_unstable)]
#![feature(str_char)]
#![feature(into_cow)]
#![feature(slice_patterns)]
#![feature(std_misc)]
#![feature(debug_builders)]
#![cfg_attr(test, feature(test, rustc_private, std_misc))]

// Don't link to std. We are std.
#![feature(no_std)]
#![no_std]

#![allow(trivial_casts)]
#![deny(missing_docs)]

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate log;

#[macro_use]
#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
    unreachable, unimplemented, write, writeln)]
extern crate core;

#[macro_use]
#[macro_reexport(vec, format)]
extern crate collections as core_collections;

#[allow(deprecated)] extern crate rand as core_rand;
extern crate alloc;
extern crate unicode;
extern crate libc;

#[macro_use] #[no_link] extern crate rustc_bitflags;

// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate std as realstd;
#[cfg(test)] pub use realstd::marker;
#[cfg(test)] pub use realstd::ops;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::boxed;

// NB: These reexports are in the order they should be listed in rustdoc

pub use core::any;
pub use core::cell;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
pub use core::convert;
pub use core::default;
#[allow(deprecated)]
pub use core::finally;
pub use core::hash;
pub use core::intrinsics;
pub use core::iter;
#[cfg(not(test))] pub use core::marker;
pub use core::mem;
#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::simd;
pub use core::result;
pub use core::option;
pub use core::error;

#[cfg(not(test))] pub use alloc::boxed;
pub use alloc::rc;

pub use core_collections::borrow;
pub use core_collections::fmt;
pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::vec;

pub use unicode::char;

/* Exported macros */

#[macro_use]
mod macros;

mod rtdeps;

/* The Prelude. */

pub mod prelude;

/* Primitive types */

// NB: slice and str are primitive types too, but their module docs + primitive doc pages
// are inlined from the public re-exports of core_collections::{slice, str} above.

#[path = "num/float_macros.rs"]
#[macro_use]
mod float_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"]  pub mod isize;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

pub mod ascii;
pub mod thunk;

/* Common traits */

pub mod num;

/* Runtime and platform support */

#[macro_use]
pub mod thread;

pub mod collections;
pub mod dynamic_lib;
pub mod env;
pub mod ffi;
pub mod fs;
pub mod io;
pub mod net;
pub mod old_io;
pub mod old_path;
pub mod os;
pub mod path;
pub mod process;
pub mod rand;
pub mod sync;
pub mod time;

#[macro_use]
#[path = "sys/common/mod.rs"] mod sys_common;

#[cfg(unix)]
#[path = "sys/unix/mod.rs"] mod sys;
#[cfg(windows)]
#[path = "sys/windows/mod.rs"] mod sys;

pub mod rt;
mod panicking;

// Modules that exist purely to document + host impl docs for primitive types

mod array;
mod bool;
mod unit;
mod tuple;

// A curious inner-module that's not exported that contains the binding
// 'std' so that macro-expanded references to std::error and such
// can be resolved within libstd.
#[doc(hidden)]
mod std {
    pub use sync; // used for select!()
    pub use error; // used for try!()
    pub use fmt; // used for any formatting strings
    #[allow(deprecated)]
    pub use old_io; // used for println!()
    pub use option; // used for bitflags!{}
    pub use rt; // used for panic!()
    pub use vec; // used for vec![]
    pub use cell; // used for tls!
    pub use thread; // used for thread_local!
    pub use marker;  // used for tls!
    pub use ops; // used for bitflags!

    // The test runner calls ::std::env::args() but really wants realstd
    #[cfg(test)] pub use realstd::env as env;
    // The test runner requires std::slice::Vector, so re-export std::slice just for it.
    //
    // It is also used in vec![]
    pub use slice;

    pub use boxed; // used for vec![]
}
<|endoftext|>


<commit_before>use ::std::io::prelude::*;

macro_rules! otry{
    ($e:expr) => {
        match $e {
            Some(x) => x,
            None => return None,
        }
    }
}

/// Yields lines from a reader, and allows to peek one byte
/// from the next line.
pub struct Charpeek<R: BufRead> {
    reader: R,
    peek: Option<[u8;1]>
}

impl<R: BufRead> Charpeek<R> {
    pub fn new(r: R) -> Self {
        Charpeek { reader: r, peek: None }
    }

    pub fn peek_byte(&mut self) -> Option<u8> {
        match self.peek {
            Some(x) => Some(x[0]),
            None => {
                let mut buf = [0u8];
                otry!( self.reader.read_exact(&mut buf).ok() );
                self.peek = Some(buf);
                Some(buf[0])
            }
        }
    }

    pub fn flush_peek<W: Write>(&mut self, mut writer: W) {
        {
            let peek = self.peek.as_ref().map_or(&[] as &[u8], |x| x);
            let _ = writer.write(&peek);
            let _ = writer.flush();
        }
        self.peek = None;
    }

    pub fn next_line(&mut self) -> Option<String> {
        let mut line = String::new();
        {
            let peek = self.peek.as_ref().map_or(&[] as &[u8], |x| x);
            otry!( peek.chain(&mut self.reader).read_line(&mut line).ok() );
        }
        if line.len() == 0 { return None; }
        self.peek = None;
        let tru_len = line.trim_right().len();
        line.truncate(tru_len);
        Some(line)
    }
}
<commit_msg>compiles on stable<commit_after>use ::std::io::prelude::*;

macro_rules! otry{
    ($e:expr) => {
        match $e {
            Some(x) => x,
            None => return None,
        }
    }
}

/// Yields lines from a reader, and allows to peek one byte
/// from the next line.
pub struct Charpeek<R: BufRead> {
    reader: R,
    peek: Option<[u8;1]>
}

impl<R: BufRead> Charpeek<R> {
    pub fn new(r: R) -> Self {
        Charpeek { reader: r, peek: None }
    }

    pub fn peek_byte(&mut self) -> Option<u8> {
        match self.peek {
            Some(x) => Some(x[0]),
            None => {
                let mut buf = [0u8];
                otry!( self.reader.read_exact(&mut buf).ok() );
                self.peek = Some(buf);
                Some(buf[0])
            }
        }
    }

    pub fn flush_peek<W: Write>(&mut self, mut writer: W) {
        {
            let peek = self.peek.as_ref().map_or(&[] as &[u8], |x| x);
            let _ = writer.write(&peek);
            let _ = writer.flush();
        }
        self.peek = None;
    }

    pub fn next_line(&mut self) -> Option<String> {
        let mut line = String::new();
        // Chain doesn't implement BufRead in Rust 1.8.
        // {
        //     let peek = self.peek.as_ref().map_or(&[] as &[u8], |x| x);
        //     otry!( peek.chain(&mut self.reader).read_line(&mut line).ok() );
        // }
        // The following WAR is incorrect for non-ascii first char (unlikely)
        line.extend(self.peek.map(|p| p[0] as char));
        otry!( self.reader.read_line(&mut line).ok() );
        if line.len() == 0 { return None; }
        self.peek = None;
        let tru_len = line.trim_right().len();
        line.truncate(tru_len);
        Some(line)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 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.

// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/)

#![cfg(not(test))]
#![deny(warnings)]

extern crate cargo_metadata;
extern crate getopts;
extern crate serde_json as json;

use std::env;
use std::fs;
use std::hash::{Hash, Hasher};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::str;
use std::collections::HashSet;
use std::iter::FromIterator;

use getopts::{Matches, Options};

fn main() {
    let exit_status = execute();
    std::io::stdout().flush().unwrap();
    std::process::exit(exit_status);
}

fn execute() -> i32 {
    let success = 0;
    let failure = 1;

    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("q", "quiet", "no output printed to stdout");
    opts.optflag("v", "verbose", "use verbose output");
    opts.optmulti(
        "p",
        "package",
        "specify package to format (only usable in workspaces)",
        "<package>",
    );
    opts.optflag("", "all", "format all packages (only usable in workspaces)");

    // If there is any invalid argument passed to `cargo fmt`, return without formatting.
    let mut is_package_arg = false;
    for arg in env::args().skip(2).take_while(|a| a != "--") {
        if arg.starts_with("-") {
            is_package_arg = arg.starts_with("--package");
        } else if !is_package_arg {
            print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg));
            return failure;
        } else {
            is_package_arg = false;
        }
    }

    let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) {
        Ok(m) => m,
        Err(e) => {
            print_usage_to_stderr(&opts, &e.to_string());
            return failure;
        }
    };

    let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) {
        (false, false) => Verbosity::Normal,
        (false, true) => Verbosity::Quiet,
        (true, false) => Verbosity::Verbose,
        (true, true) => {
            print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible");
            return failure;
        }
    };

    if matches.opt_present("h") {
        print_usage_to_stdout(&opts, "");
        return success;
    }

    let strategy = CargoFmtStrategy::from_matches(&matches);

    match format_crate(verbosity, &strategy) {
        Err(e) => {
            print_usage_to_stderr(&opts, &e.to_string());
            failure
        }
        Ok(status) => if status.success() {
            success
        } else {
            status.code().unwrap_or(failure)
        },
    }
}

macro_rules! print_usage {
    ($print:ident, $opts:ident, $reason:expr) => ({
        let msg = format!("{}\nusage: cargo fmt [options]", $reason);
        $print!(
            "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \
             Arguments after `--` are passed to rustfmt.",
            $opts.usage(&msg)
        );
    })
}

fn print_usage_to_stdout(opts: &Options, reason: &str) {
    print_usage!(println, opts, reason);
}

fn print_usage_to_stderr(opts: &Options, reason: &str) {
    print_usage!(eprintln, opts, reason);
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Verbosity {
    Verbose,
    Normal,
    Quiet,
}

fn format_crate(
    verbosity: Verbosity,
    strategy: &CargoFmtStrategy,
) -> Result<ExitStatus, io::Error> {
    let targets = get_targets(strategy)?;

    // Currently only bin and lib files get formatted
    let files: Vec<_> = targets
        .into_iter()
        .filter(|t| t.kind.should_format())
        .inspect(|t| {
            if verbosity == Verbosity::Verbose {
                println!("[{:?}] {:?}", t.kind, t.path)
            }
        })
        .map(|t| t.path)
        .collect();

    format_files(&files, &get_fmt_args(), verbosity)
}

fn get_fmt_args() -> Vec<String> {
    // All arguments after -- are passed to rustfmt
    env::args().skip_while(|a| a != "--").skip(1).collect()
}

#[derive(Debug)]
enum TargetKind {
    Lib,         // dylib, staticlib, lib
    Bin,         // bin
    Example,     // example file
    Test,        // test file
    Bench,       // bench file
    CustomBuild, // build script
    ProcMacro,   // a proc macro implementation
    Other,       // plugin,...
}

impl TargetKind {
    fn should_format(&self) -> bool {
        match *self {
            TargetKind::Lib
            | TargetKind::Bin
            | TargetKind::Example
            | TargetKind::Test
            | TargetKind::Bench
            | TargetKind::CustomBuild
            | TargetKind::ProcMacro => true,
            _ => false,
        }
    }

    fn from_str(s: &str) -> Self {
        match s {
            "bin" => TargetKind::Bin,
            "lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib,
            "test" => TargetKind::Test,
            "example" => TargetKind::Example,
            "bench" => TargetKind::Bench,
            "custom-build" => TargetKind::CustomBuild,
            "proc-macro" => TargetKind::ProcMacro,
            _ => TargetKind::Other,
        }
    }
}

/// Target uses a `path` field for equality and hashing.
#[derive(Debug)]
pub struct Target {
    /// A path to the main source file of the target.
    path: PathBuf,
    /// A kind of target (e.g. lib, bin, example, ...).
    kind: TargetKind,
}

impl Target {
    pub fn from_target(target: &cargo_metadata::Target) -> Self {
        let path = PathBuf::from(&target.src_path);
        let canonicalized = fs::canonicalize(&path).unwrap_or(path);

        Target {
            path: canonicalized,
            kind: TargetKind::from_str(&target.kind[0]),
        }
    }
}

impl PartialEq for Target {
    fn eq(&self, other: &Target) -> bool {
        self.path == other.path
    }
}

impl Eq for Target {}

impl Hash for Target {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.path.hash(state);
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum CargoFmtStrategy {
    /// Format every packages and dependencies.
    All,
    /// Format pacakges that are specified by the command line argument.
    Some(Vec<String>),
    /// Format the root packages only.
    Root,
}

impl CargoFmtStrategy {
    pub fn from_matches(matches: &Matches) -> CargoFmtStrategy {
        match (matches.opt_present("all"), matches.opt_present("p")) {
            (false, false) => CargoFmtStrategy::Root,
            (true, _) => CargoFmtStrategy::All,
            (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")),
        }
    }
}

/// Based on the specified CargoFmtStrategy, returns a set of main source files.
fn get_targets(strategy: &CargoFmtStrategy) -> Result<HashSet<Target>, io::Error> {
    let mut targets = HashSet::new();

    match *strategy {
        CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?,
        CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?,
        CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?,
    }

    if targets.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::Other,
            format!("Failed to find targets"),
        ))
    } else {
        Ok(targets)
    }
}

fn get_targets_root_only(targets: &mut HashSet<Target>) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    for package in metadata.packages {
        for target in package.targets {
            if target.name == package.name {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    Ok(())
}

fn get_targets_recursive(
    manifest_path: Option<&Path>,
    mut targets: &mut HashSet<Target>,
    visited: &mut HashSet<String>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(manifest_path)?;

    for package in metadata.packages {
        add_targets(&package.targets, &mut targets);

        // Look for local dependencies.
        for dependency in package.dependencies {
            if dependency.source.is_some() || visited.contains(&dependency.name) {
                continue;
            }

            let mut manifest_path = PathBuf::from(&package.manifest_path);

            manifest_path.pop();
            manifest_path.push(&dependency.name);
            manifest_path.push("Cargo.toml");

            if manifest_path.exists() {
                visited.insert(dependency.name);
                get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
            }
        }
    }

    Ok(())
}

fn get_targets_with_hitlist(
    hitlist: &[String],
    targets: &mut HashSet<Target>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist);

    for package in metadata.packages {
        for target in package.targets {
            if workspace_hitlist.remove(&target.name) {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    if workspace_hitlist.is_empty() {
        Ok(())
    } else {
        let package = workspace_hitlist.iter().next().unwrap();
        Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("package `{}` is not a member of the workspace", package),
        ))
    }
}

fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet<Target>) {
    for target in target_paths {
        targets.insert(Target::from_target(&target));
    }
}

fn format_files(
    files: &[PathBuf],
    fmt_args: &[String],
    verbosity: Verbosity,
) -> Result<ExitStatus, io::Error> {
    let stdout = if verbosity == Verbosity::Quiet {
        std::process::Stdio::null()
    } else {
        std::process::Stdio::inherit()
    };

    if verbosity == Verbosity::Verbose {
        print!("rustfmt");
        for a in fmt_args {
            print!(" {}", a);
        }
        for f in files {
            print!(" {}", f.display());
        }
        println!();
    }

    let mut command = Command::new("rustfmt")
        .stdout(stdout)
        .args(files)
        .args(fmt_args)
        .spawn()
        .map_err(|e| match e.kind() {
            io::ErrorKind::NotFound => io::Error::new(
                io::ErrorKind::Other,
                "Could not run rustfmt, please make sure it is in your PATH.",
            ),
            _ => e,
        })?;

    command.wait()
}

fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> {
    match cargo_metadata::metadata(manifest_path) {
        Ok(metadata) => Ok(metadata),
        Err(..) => Err(io::Error::new(
            io::ErrorKind::Other,
            "`cargo manifest` failed.",
        )),
    }
}
<commit_msg>Replace TargetKind with simple String<commit_after>// Copyright 2015-2016 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.

// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/)

#![cfg(not(test))]
#![deny(warnings)]

extern crate cargo_metadata;
extern crate getopts;
extern crate serde_json as json;

use std::env;
use std::fs;
use std::hash::{Hash, Hasher};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::str;
use std::collections::HashSet;
use std::iter::FromIterator;

use getopts::{Matches, Options};

fn main() {
    let exit_status = execute();
    std::io::stdout().flush().unwrap();
    std::process::exit(exit_status);
}

fn execute() -> i32 {
    let success = 0;
    let failure = 1;

    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("q", "quiet", "no output printed to stdout");
    opts.optflag("v", "verbose", "use verbose output");
    opts.optmulti(
        "p",
        "package",
        "specify package to format (only usable in workspaces)",
        "<package>",
    );
    opts.optflag("", "all", "format all packages (only usable in workspaces)");

    // If there is any invalid argument passed to `cargo fmt`, return without formatting.
    let mut is_package_arg = false;
    for arg in env::args().skip(2).take_while(|a| a != "--") {
        if arg.starts_with("-") {
            is_package_arg = arg.starts_with("--package");
        } else if !is_package_arg {
            print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg));
            return failure;
        } else {
            is_package_arg = false;
        }
    }

    let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) {
        Ok(m) => m,
        Err(e) => {
            print_usage_to_stderr(&opts, &e.to_string());
            return failure;
        }
    };

    let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) {
        (false, false) => Verbosity::Normal,
        (false, true) => Verbosity::Quiet,
        (true, false) => Verbosity::Verbose,
        (true, true) => {
            print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible");
            return failure;
        }
    };

    if matches.opt_present("h") {
        print_usage_to_stdout(&opts, "");
        return success;
    }

    let strategy = CargoFmtStrategy::from_matches(&matches);

    match format_crate(verbosity, &strategy) {
        Err(e) => {
            print_usage_to_stderr(&opts, &e.to_string());
            failure
        }
        Ok(status) => if status.success() {
            success
        } else {
            status.code().unwrap_or(failure)
        },
    }
}

macro_rules! print_usage {
    ($print:ident, $opts:ident, $reason:expr) => ({
        let msg = format!("{}\nusage: cargo fmt [options]", $reason);
        $print!(
            "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \
             Arguments after `--` are passed to rustfmt.",
            $opts.usage(&msg)
        );
    })
}

fn print_usage_to_stdout(opts: &Options, reason: &str) {
    print_usage!(println, opts, reason);
}

fn print_usage_to_stderr(opts: &Options, reason: &str) {
    print_usage!(eprintln, opts, reason);
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Verbosity {
    Verbose,
    Normal,
    Quiet,
}

fn format_crate(
    verbosity: Verbosity,
    strategy: &CargoFmtStrategy,
) -> Result<ExitStatus, io::Error> {
    let targets = get_targets(strategy)?;

    // Currently only bin and lib files get formatted
    let files: Vec<_> = targets
        .into_iter()
        .inspect(|t| {
            if verbosity == Verbosity::Verbose {
                println!("[{}] {:?}", t.kind, t.path)
            }
        })
        .map(|t| t.path)
        .collect();

    format_files(&files, &get_fmt_args(), verbosity)
}

fn get_fmt_args() -> Vec<String> {
    // All arguments after -- are passed to rustfmt
    env::args().skip_while(|a| a != "--").skip(1).collect()
}

/// Target uses a `path` field for equality and hashing.
#[derive(Debug)]
pub struct Target {
    /// A path to the main source file of the target.
    path: PathBuf,
    /// A kind of target (e.g. lib, bin, example, ...).
    kind: String,
}

impl Target {
    pub fn from_target(target: &cargo_metadata::Target) -> Self {
        let path = PathBuf::from(&target.src_path);
        let canonicalized = fs::canonicalize(&path).unwrap_or(path);

        Target {
            path: canonicalized,
            kind: target.kind[0].clone(),
        }
    }
}

impl PartialEq for Target {
    fn eq(&self, other: &Target) -> bool {
        self.path == other.path
    }
}

impl Eq for Target {}

impl Hash for Target {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.path.hash(state);
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum CargoFmtStrategy {
    /// Format every packages and dependencies.
    All,
    /// Format pacakges that are specified by the command line argument.
    Some(Vec<String>),
    /// Format the root packages only.
    Root,
}

impl CargoFmtStrategy {
    pub fn from_matches(matches: &Matches) -> CargoFmtStrategy {
        match (matches.opt_present("all"), matches.opt_present("p")) {
            (false, false) => CargoFmtStrategy::Root,
            (true, _) => CargoFmtStrategy::All,
            (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")),
        }
    }
}

/// Based on the specified CargoFmtStrategy, returns a set of main source files.
fn get_targets(strategy: &CargoFmtStrategy) -> Result<HashSet<Target>, io::Error> {
    let mut targets = HashSet::new();

    match *strategy {
        CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?,
        CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?,
        CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?,
    }

    if targets.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::Other,
            format!("Failed to find targets"),
        ))
    } else {
        Ok(targets)
    }
}

fn get_targets_root_only(targets: &mut HashSet<Target>) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    for package in metadata.packages {
        for target in package.targets {
            if target.name == package.name {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    Ok(())
}

fn get_targets_recursive(
    manifest_path: Option<&Path>,
    mut targets: &mut HashSet<Target>,
    visited: &mut HashSet<String>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(manifest_path)?;

    for package in metadata.packages {
        add_targets(&package.targets, &mut targets);

        // Look for local dependencies.
        for dependency in package.dependencies {
            if dependency.source.is_some() || visited.contains(&dependency.name) {
                continue;
            }

            let mut manifest_path = PathBuf::from(&package.manifest_path);

            manifest_path.pop();
            manifest_path.push(&dependency.name);
            manifest_path.push("Cargo.toml");

            if manifest_path.exists() {
                visited.insert(dependency.name);
                get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
            }
        }
    }

    Ok(())
}

fn get_targets_with_hitlist(
    hitlist: &[String],
    targets: &mut HashSet<Target>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist);

    for package in metadata.packages {
        for target in package.targets {
            if workspace_hitlist.remove(&target.name) {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    if workspace_hitlist.is_empty() {
        Ok(())
    } else {
        let package = workspace_hitlist.iter().next().unwrap();
        Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("package `{}` is not a member of the workspace", package),
        ))
    }
}

fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet<Target>) {
    for target in target_paths {
        targets.insert(Target::from_target(&target));
    }
}

fn format_files(
    files: &[PathBuf],
    fmt_args: &[String],
    verbosity: Verbosity,
) -> Result<ExitStatus, io::Error> {
    let stdout = if verbosity == Verbosity::Quiet {
        std::process::Stdio::null()
    } else {
        std::process::Stdio::inherit()
    };

    if verbosity == Verbosity::Verbose {
        print!("rustfmt");
        for a in fmt_args {
            print!(" {}", a);
        }
        for f in files {
            print!(" {}", f.display());
        }
        println!();
    }

    let mut command = Command::new("rustfmt")
        .stdout(stdout)
        .args(files)
        .args(fmt_args)
        .spawn()
        .map_err(|e| match e.kind() {
            io::ErrorKind::NotFound => io::Error::new(
                io::ErrorKind::Other,
                "Could not run rustfmt, please make sure it is in your PATH.",
            ),
            _ => e,
        })?;

    command.wait()
}

fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> {
    match cargo_metadata::metadata(manifest_path) {
        Ok(metadata) => Ok(metadata),
        Err(..) => Err(io::Error::new(
            io::ErrorKind::Other,
            "`cargo manifest` failed.",
        )),
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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 client::HttpRequest as ClientRequest;
use client::HttpStream as ClientStream;

use server::HttpRequest as ServerRequest;

use rand::{self, Rng};

use std::collections::HashMap;
use std::io::prelude::*;
use std::{io, iter};

#[derive(Debug)]
struct TestFields {
    texts: HashMap<String, String>,
    files: HashMap<String, Vec<u8>>,
}

#[test]
fn local_test() {
    let _ = ::env_logger::init();

    let test_fields = gen_test_fields();

    let buf = test_client(&test_fields);

    trace!(
        "\n--Test Buffer Begin--\n{}\n--Test Buffer End--",
        String::from_utf8_lossy(&buf.buf)
    );

    test_server(buf, test_fields);
}

fn gen_test_fields() -> TestFields {
    const MIN_FIELDS: usize = 1;
    const MAX_FIELDS: usize = 3;

    let mut rng = rand::weak_rng();

    let texts_count = rng.gen_range(MIN_FIELDS, MAX_FIELDS);
    let files_count = rng.gen_range(MIN_FIELDS, MAX_FIELDS);

    TestFields {
        texts: (0..texts_count).map(|_| (gen_string(), gen_string())).collect(),
        files: (0..files_count).map(|_| (gen_string(), gen_bytes())).collect(),
    }
}

fn gen_string() -> String {
    const MIN_LEN: usize = 3;
    const MAX_LEN: usize = 8;
    const MAX_DASHES: usize = 3;

    let mut rng_1 = rand::weak_rng();
    let mut rng_2 = rand::weak_rng();

    let str_len_1 = rng_1.gen_range(MIN_LEN, MAX_LEN + 1);
    let str_len_2 = rng_2.gen_range(MIN_LEN, MAX_LEN + 1);
    let num_dashes = rng_1.gen_range(0, MAX_DASHES + 1);

    rng_1.gen_ascii_chars().take(str_len_1)
        .chain(iter::repeat('-').take(num_dashes))
        .chain(rng_2.gen_ascii_chars().take(str_len_2))
        .collect()
}

fn gen_bytes() -> Vec<u8> {
    gen_string().into_bytes()
}

fn test_client(test_fields: &TestFields) -> HttpBuffer {
    use client::Multipart;

    let request = MockClientRequest::default();

    let mut test_files = test_fields.files.iter();

    let mut multipart = Multipart::from_request(request).unwrap();

    // Intersperse file fields amongst text fields
    for (name, text) in &test_fields.texts {
        if let Some((file_name, file)) = test_files.next() {
            multipart.write_stream(file_name, &mut &**file, Some(file_name), None).unwrap();
        }

        multipart.write_text(name, text).unwrap();
    }

    // Write remaining files
    for (file_name, file) in test_files {
       multipart.write_stream(file_name, &mut &**file, None, None).unwrap();
    }

    multipart.send().unwrap()
}

fn test_server(buf: HttpBuffer, mut fields: TestFields) {
    use server::{Multipart, MultipartData};

    let mut multipart = Multipart::from_request(buf.for_server())
        .unwrap_or_else(|_| panic!("Buffer should be multipart!"));

    trace!("Fields for server test: {:?}", fields);

    while let Ok(Some(mut field)) = multipart.read_entry() {
        match field.data {
            MultipartData::Text(text) => {
                let test_text = fields.texts.remove(&field.name);

                assert!(
                    test_text.is_some(),
                    "Got text field that wasn't in original dataset: {:?} : {:?} ",
                    field.name, text
                );

                let test_text = test_text.unwrap();

                assert!(
                    text == test_text,
                    "Unexpected data for field {:?}: Expected {:?}, got {:?}",
                    field.name, test_text, text
                );

            },
            MultipartData::File(ref mut file) => {
                let test_bytes = fields.files.remove(&field.name).unwrap();

                let mut bytes = Vec::with_capacity(test_bytes.len());
                file.read_to_end(&mut bytes).unwrap();

                assert!(bytes == test_bytes, "Unexpected data for file {:?}: Expected {:?}, Got {:?}",
                        field.name, String::from_utf8_lossy(&test_bytes), String::from_utf8_lossy(&bytes)
                );
            },
        }
    }

    assert!(fields.texts.is_empty(), "Text fields were not exhausted! Text fields: {:?}", fields.texts);
    assert!(fields.files.is_empty(), "File fields were not exhausted! File fields: {:?}", fields.files);
}

#[derive(Default, Debug)]
pub struct MockClientRequest {
    boundary: Option<String>,
    content_len: Option<u64>,
}

impl ClientRequest for MockClientRequest {
    type Stream = HttpBuffer;
    type Error = io::Error;

    fn apply_headers(&mut self, boundary: &str, content_len: Option<u64>) -> bool {
        self.boundary = Some(boundary.into());
        self.content_len = content_len;
        true
    }

    fn open_stream(self) -> Result<HttpBuffer, io::Error> {
        debug!("MockClientRequest::open_stream called! {:?}", self);
        let boundary = self.boundary.expect("HttpRequest::set_headers() was not called!");

        Ok(HttpBuffer { buf: Vec::new(), boundary: boundary, content_len: self.content_len })
    }
}

#[derive(Debug)]
pub struct HttpBuffer {
    buf: Vec<u8>,
    boundary: String,
    content_len: Option<u64>,
}

impl HttpBuffer {
    pub fn for_server(&self) -> ServerBuffer {
        ServerBuffer {
            data: &self.buf,
            boundary: &self.boundary,
            content_len: self.content_len,
        }
    }
}

impl Write for HttpBuffer {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        self.buf.write(data)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.buf.flush()
    }
}

impl Read for HttpBuffer {
    fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
        unimplemented!()
    }
}

impl ClientStream for HttpBuffer {
    type Request = MockClientRequest;
    type Response = HttpBuffer;
    type Error = io::Error;

    fn finish(self) -> Result<Self, io::Error> { Ok(self) }
}

#[derive(Debug)]
pub struct ServerBuffer<'a> {
    data: &'a [u8],
    boundary: &'a str,
    content_len: Option<u64>,
}

impl<'a> Read for ServerBuffer<'a> {
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        self.data.read(out)
    }
}

impl<'a> ServerRequest for ServerBuffer<'a> {
    type Body = Self;

    fn multipart_boundary(&self) -> Option<&str> { Some(&self.boundary) }

    fn body(self) -> Self::Body {
        self
    }
}

<commit_msg>Shorten names in local_test, add some RNG to reading from the server<commit_after>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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 client::HttpRequest as ClientRequest;
use client::HttpStream as ClientStream;

use server::HttpRequest as ServerRequest;

use rand::{self, Rng, ThreadRng};

use std::collections::HashMap;
use std::io::prelude::*;
use std::{io, iter};

#[derive(Debug)]
struct TestFields {
    texts: HashMap<String, String>,
    files: HashMap<String, Vec<u8>>,
}

#[test]
fn local_test() {
    let _ = ::env_logger::init();

    let test_fields = gen_test_fields();

    let buf = test_client(&test_fields);

    trace!(
        "\n--Test Buffer Begin--\n{}\n--Test Buffer End--",
        String::from_utf8_lossy(&buf.buf)
    );

    test_server(buf, test_fields);
}

fn gen_test_fields() -> TestFields {
    const MIN_FIELDS: usize = 1;
    const MAX_FIELDS: usize = 3;

    let mut rng = rand::weak_rng();

    let texts_count = rng.gen_range(MIN_FIELDS, MAX_FIELDS);
    let files_count = rng.gen_range(MIN_FIELDS, MAX_FIELDS);

    TestFields {
        texts: (0..texts_count).map(|_| (gen_string(), gen_string())).collect(),
        files: (0..files_count).map(|_| (gen_string(), gen_bytes())).collect(),
    }
}

fn gen_string() -> String {
    const MIN_LEN: usize = 2;
    const MAX_LEN: usize = 5;
    const MAX_DASHES: usize = 2;

    let mut rng_1 = rand::thread_rng();
    let mut rng_2 = rand::thread_rng();

    let str_len_1 = rng_1.gen_range(MIN_LEN, MAX_LEN + 1);
    let str_len_2 = rng_2.gen_range(MIN_LEN, MAX_LEN + 1);
    let num_dashes = rng_1.gen_range(0, MAX_DASHES + 1);

    rng_1.gen_ascii_chars().take(str_len_1)
        .chain(iter::repeat('-').take(num_dashes))
        .chain(rng_2.gen_ascii_chars().take(str_len_2))
        .collect()
}

fn gen_bytes() -> Vec<u8> {
    gen_string().into_bytes()
}

fn test_client(test_fields: &TestFields) -> HttpBuffer {
    use client::Multipart;

    let request = MockClientRequest::default();

    let mut test_files = test_fields.files.iter();

    let mut multipart = Multipart::from_request(request).unwrap();

    // Intersperse file fields amongst text fields
    for (name, text) in &test_fields.texts {
        if let Some((file_name, file)) = test_files.next() {
            multipart.write_stream(file_name, &mut &**file, Some(file_name), None).unwrap();
        }

        multipart.write_text(name, text).unwrap();
    }

    // Write remaining files
    for (file_name, file) in test_files {
       multipart.write_stream(file_name, &mut &**file, None, None).unwrap();
    }

    multipart.send().unwrap()
}

fn test_server(buf: HttpBuffer, mut fields: TestFields) {
    use server::{Multipart, MultipartData};

    let mut multipart = Multipart::from_request(buf.for_server())
        .unwrap_or_else(|_| panic!("Buffer should be multipart!"));

    trace!("Fields for server test: {:?}", fields);

    while let Ok(Some(mut field)) = multipart.read_entry() {
        match field.data {
            MultipartData::Text(text) => {
                let test_text = fields.texts.remove(&field.name);

                assert!(
                    test_text.is_some(),
                    "Got text field that wasn't in original dataset: {:?} : {:?} ",
                    field.name, text
                );

                let test_text = test_text.unwrap();

                assert!(
                    text == test_text,
                    "Unexpected data for field {:?}: Expected {:?}, got {:?}",
                    field.name, test_text, text
                );

            },
            MultipartData::File(ref mut file) => {
                let test_bytes = fields.files.remove(&field.name).unwrap();

                let mut bytes = Vec::with_capacity(test_bytes.len());
                file.read_to_end(&mut bytes).unwrap();

                assert!(bytes == test_bytes, "Unexpected data for file {:?}: Expected {:?}, Got {:?}",
                        field.name, String::from_utf8_lossy(&test_bytes), String::from_utf8_lossy(&bytes)
                );
            },
        }
    }

    assert!(fields.texts.is_empty(), "Text fields were not exhausted! Text fields: {:?}", fields.texts);
    assert!(fields.files.is_empty(), "File fields were not exhausted! File fields: {:?}", fields.files);
}

#[derive(Default, Debug)]
pub struct MockClientRequest {
    boundary: Option<String>,
    content_len: Option<u64>,
}

impl ClientRequest for MockClientRequest {
    type Stream = HttpBuffer;
    type Error = io::Error;

    fn apply_headers(&mut self, boundary: &str, content_len: Option<u64>) -> bool {
        self.boundary = Some(boundary.into());
        self.content_len = content_len;
        true
    }

    fn open_stream(self) -> Result<HttpBuffer, io::Error> {
        debug!("MockClientRequest::open_stream called! {:?}", self);
        let boundary = self.boundary.expect("HttpRequest::set_headers() was not called!");

        Ok(HttpBuffer { buf: Vec::new(), boundary: boundary, content_len: self.content_len })
    }
}

#[derive(Debug)]
pub struct HttpBuffer {
    buf: Vec<u8>,
    boundary: String,
    content_len: Option<u64>,
}

impl HttpBuffer {
    pub fn for_server(&self) -> ServerBuffer {
        ServerBuffer {
            data: &self.buf,
            boundary: &self.boundary,
            content_len: self.content_len,
            rng: rand::thread_rng(),
        }
    }
}

impl Write for HttpBuffer {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        self.buf.write(data)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.buf.flush()
    }
}

impl Read for HttpBuffer {
    fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
        unimplemented!()
    }
}

impl ClientStream for HttpBuffer {
    type Request = MockClientRequest;
    type Response = HttpBuffer;
    type Error = io::Error;

    fn finish(self) -> Result<Self, io::Error> { Ok(self) }
}

pub struct ServerBuffer<'a> {
    data: &'a [u8],
    boundary: &'a str,
    content_len: Option<u64>,
    rng: ThreadRng,
}

impl<'a> Read for ServerBuffer<'a> {
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        // Simulate the randomness of a network connection by not always reading everything
        let len = self.rng.gen_range(1, out.len());
        self.data.read(&mut out[..len])
    }
}

impl<'a> ServerRequest for ServerBuffer<'a> {
    type Body = Self;

    fn multipart_boundary(&self) -> Option<&str> { Some(&self.boundary) }

    fn body(self) -> Self::Body {
        self
    }
}

<|endoftext|>


<commit_before>use std::ptr;
use std::ffi::CStr;
use std::os::raw::c_char;
use std::io::Cursor;
use llvm::prelude::*;
use llvm::core::*;
use llvm::execution_engine::*;
use compileerror::{ErrorCode, err, CompileResult, Pos};
use parser::{parse_module};
use codegen::{codegen, cstr};
use passes::{mark_tail_calls, infer_and_check_types};
use ast::{TreePrinter};

fn run(prog: &str, dump: bool) -> CompileResult<i64>
{
    let mut cursor = Cursor::new(prog);
    let mut md = try!(parse_module(&mut cursor, "test"));
    if dump {
        md.print(0);
    }

    try!(infer_and_check_types(&mut md));
    try!(mark_tail_calls(&mut md));

    let mut ctx = try!(codegen(&md));

    unsafe {
        LLVMLinkInInterpreter();

        let mut ee: LLVMExecutionEngineRef = ptr::null_mut();
        let mut error_message: *mut c_char = ptr::null_mut();
        if LLVMCreateInterpreterForModule(&mut ee, ctx.take_module_ref(), &mut error_message) != 0 {
            let msg = CStr::from_ptr(error_message).to_str().expect("Invalid C string");
            let e = format!("Unable to create interpreter: {}", msg);
            LLVMDisposeMessage(error_message);
            return err(Pos::zero(), ErrorCode::CodegenError, e);
        }

        let mut func: LLVMValueRef = ptr::null_mut();
        if LLVMFindFunction(ee, cstr("main"), &mut func) == 0 {
            let val = LLVMRunFunction(ee, func, 0, ptr::null_mut());
            let result = LLVMGenericValueToInt(val, 0) as i64;
            LLVMDisposeGenericValue(val);
            LLVMDisposeExecutionEngine(ee);
            println!("result {}", result);
            Ok(result)
        } else {
            LLVMDisposeExecutionEngine(ee);
            err(Pos::zero(), ErrorCode::CodegenError, "No main function found".into())
        }
    }
}

#[test]
fn test_number()
{
    assert!(run(r#"
main() -> int = 5
    "#, false) == Ok(5));
}

#[test]
fn test_unary_sub()
{
    assert!(run(r#"
main() -> int = -5
    "#, false) == Ok(-5));
}

#[test]
fn test_unary_not()
{
    assert!(run(r#"
main() -> bool = !true
    "#, false) == Ok(0));
}

#[test]
fn test_binary_operators()
{
    assert!(run("main() -> int = 4 + 5 * 7 - 9 / 3 + 5 % 4", false) == Ok(4 + 35 - 3 + 1));
    assert!(run("main() -> bool = 4 < 5 * 7 && 9 / 3 > 5 % 4", false) == Ok(1));
}

#[test]
fn test_call()
{
    assert!(run(r#"
add(a: int, b: int) -> int = a + b
main() -> int = add(6, 7)
    "#, false) == Ok(13));
}

#[test]
fn test_match_int()
{
    assert!(run(r#"
foo(a: int) -> int =
    match a
        0 => 100,
        1 => 299,
        _ => 0

main() -> int = foo(1)
    "#, false) == Ok(299));
}

#[test]
fn test_match_bool()
{
    assert!(run(r#"
foo(a: bool) -> int =
    match a
        true => 100,
        false => 299

main() -> int = foo(true)
    "#, false) == Ok(100));
}

#[test]
fn test_let()
{
    assert!(run(r#"
foo(a: int, b: int, c: int) -> int =
    let x = a * b, y = b * c in
        x + y

main() -> int = foo(2, 3, 4)
    "#, false) == Ok(18));
}

#[test]
fn test_array()
{
    let r = run(r#"
main() -> int =
    let x = [2, 3, 4] in 5
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(5));
}

#[test]
fn test_array_argument()
{
    let r = run(r#"
foo(v: [int; 3]) -> int = 5

main() -> int =
    let x = [2, 3, 4] in foo(x)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(5));
}

#[test]
fn test_slice_argument()
{
    let r = run(r#"
foo(v: [int]) -> int = 5

main() -> int =
    let x = [2, 3, 4] in foo(x)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(5));
}

#[test]
fn test_array_iteration()
{
    let r = run(r#"
sum(v: [int]) -> int =
    match v
        [] => 0,
        [head | tail] => head + sum(tail)

main() -> int =
    let x = [2, 3, 4] in sum(x)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(9));
}

#[test]
fn test_array_iteration2()
{
    let r = run(r#"
sum(v: [int]) -> int =
    match v
        [] => 0,
        [head | tail] => head + sum(tail)

main() -> int =
    let y = 7, x = [y; 7] in sum(x)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(49));
}

#[test]
fn test_generic()
{
    let r = run(r#"
add(x: $a, y: $a) -> $a = x + y

mul(x: $a, y: $a) -> $a = x * y

combine(x: $a, y: $a) -> $a =
    add(x, y) + mul(x, y)

main() -> int = combine(3, 2)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(11));
}

#[test]
fn test_lambda()
{
    let r = run(r#"
apply(x: int, fn: (int) -> int) -> int =
    fn(x)

main() -> int = apply(5, @(x) -> x * 2)
    "#, true);
    println!("r: {:?}", r);
    assert!(r == Ok(10));
}

#[test]
fn test_lambda_var()
{
    let r = run(r#"
apply(x: int, fn: (int) -> int) -> int =
    fn(x)

main() -> int =
    let triple =  @(x) -> x * 3 in apply(5, triple)
    "#, true);
    println!("r: {:?}", r);
    assert!(r == Ok(15));
}
<commit_msg>Add test for function bindings<commit_after>use std::ptr;
use std::ffi::CStr;
use std::os::raw::c_char;
use std::io::Cursor;
use llvm::prelude::*;
use llvm::core::*;
use llvm::execution_engine::*;
use compileerror::{ErrorCode, err, CompileResult, Pos};
use parser::{parse_module};
use codegen::{codegen, cstr};
use passes::{mark_tail_calls, infer_and_check_types};
use ast::{TreePrinter};

fn run(prog: &str, dump: bool) -> CompileResult<i64>
{
    let mut cursor = Cursor::new(prog);
    let mut md = try!(parse_module(&mut cursor, "test"));
    if dump {
        md.print(0);
    }

    try!(infer_and_check_types(&mut md));
    try!(mark_tail_calls(&mut md));

    let mut ctx = try!(codegen(&md));

    unsafe {
        LLVMLinkInInterpreter();

        let mut ee: LLVMExecutionEngineRef = ptr::null_mut();
        let mut error_message: *mut c_char = ptr::null_mut();
        if LLVMCreateInterpreterForModule(&mut ee, ctx.take_module_ref(), &mut error_message) != 0 {
            let msg = CStr::from_ptr(error_message).to_str().expect("Invalid C string");
            let e = format!("Unable to create interpreter: {}", msg);
            LLVMDisposeMessage(error_message);
            return err(Pos::zero(), ErrorCode::CodegenError, e);
        }

        let mut func: LLVMValueRef = ptr::null_mut();
        if LLVMFindFunction(ee, cstr("main"), &mut func) == 0 {
            let val = LLVMRunFunction(ee, func, 0, ptr::null_mut());
            let result = LLVMGenericValueToInt(val, 0) as i64;
            LLVMDisposeGenericValue(val);
            LLVMDisposeExecutionEngine(ee);
            println!("result {}", result);
            Ok(result)
        } else {
            LLVMDisposeExecutionEngine(ee);
            err(Pos::zero(), ErrorCode::CodegenError, "No main function found".into())
        }
    }
}

#[test]
fn test_number()
{
    assert!(run(r#"
main() -> int = 5
    "#, false) == Ok(5));
}

#[test]
fn test_unary_sub()
{
    assert!(run(r#"
main() -> int = -5
    "#, false) == Ok(-5));
}

#[test]
fn test_unary_not()
{
    assert!(run(r#"
main() -> bool = !true
    "#, false) == Ok(0));
}

#[test]
fn test_binary_operators()
{
    assert!(run("main() -> int = 4 + 5 * 7 - 9 / 3 + 5 % 4", false) == Ok(4 + 35 - 3 + 1));
    assert!(run("main() -> bool = 4 < 5 * 7 && 9 / 3 > 5 % 4", false) == Ok(1));
}

#[test]
fn test_call()
{
    assert!(run(r#"
add(a: int, b: int) -> int = a + b
main() -> int = add(6, 7)
    "#, false) == Ok(13));
}

#[test]
fn test_match_int()
{
    assert!(run(r#"
foo(a: int) -> int =
    match a
        0 => 100,
        1 => 299,
        _ => 0

main() -> int = foo(1)
    "#, false) == Ok(299));
}

#[test]
fn test_match_bool()
{
    assert!(run(r#"
foo(a: bool) -> int =
    match a
        true => 100,
        false => 299

main() -> int = foo(true)
    "#, false) == Ok(100));
}

#[test]
fn test_let()
{
    assert!(run(r#"
foo(a: int, b: int, c: int) -> int =
    let x = a * b, y = b * c in
        x + y

main() -> int = foo(2, 3, 4)
    "#, false) == Ok(18));
}

#[test]
fn test_array()
{
    let r = run(r#"
main() -> int =
    let x = [2, 3, 4] in 5
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(5));
}

#[test]
fn test_array_argument()
{
    let r = run(r#"
foo(v: [int; 3]) -> int = 5

main() -> int =
    let x = [2, 3, 4] in foo(x)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(5));
}

#[test]
fn test_slice_argument()
{
    let r = run(r#"
foo(v: [int]) -> int = 5

main() -> int =
    let x = [2, 3, 4] in foo(x)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(5));
}

#[test]
fn test_array_iteration()
{
    let r = run(r#"
sum(v: [int]) -> int =
    match v
        [] => 0,
        [head | tail] => head + sum(tail)

main() -> int =
    let x = [2, 3, 4] in sum(x)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(9));
}

#[test]
fn test_array_iteration2()
{
    let r = run(r#"
sum(v: [int]) -> int =
    match v
        [] => 0,
        [head | tail] => head + sum(tail)

main() -> int =
    let y = 7, x = [y; 7] in sum(x)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(49));
}

#[test]
fn test_generic()
{
    let r = run(r#"
add(x: $a, y: $a) -> $a = x + y

mul(x: $a, y: $a) -> $a = x * y

combine(x: $a, y: $a) -> $a =
    add(x, y) + mul(x, y)

main() -> int = combine(3, 2)
    "#, false);
    println!("r: {:?}", r);
    assert!(r == Ok(11));
}

#[test]
fn test_lambda()
{
    let r = run(r#"
apply(x: int, fn: (int) -> int) -> int =
    fn(x)

main() -> int = apply(5, @(x) -> x * 2)
    "#, true);
    println!("r: {:?}", r);
    assert!(r == Ok(10));
}

#[test]
fn test_lambda_var()
{
    let r = run(r#"
apply(x: int, fn: (int) -> int) -> int =
    fn(x)

main() -> int =
    let triple = @(x) -> x * 3 in apply(5, triple)
    "#, true);
    println!("r: {:?}", r);
    assert!(r == Ok(15));
}

#[test]
fn test_func_var()
{
    let r = run(r#"
triple(x: int) -> int = x * 3

main() -> int =
    let f = triple in f(5)
    "#, true);
    println!("r: {:?}", r);
    assert!(r == Ok(15));
}
<|endoftext|>


<commit_before>extern crate toml;

use std::io::Read;
use std::env::var;
use std::path;
use std::fs::File;

pub struct Icons {
    pub occupied_focused: String,
    pub occupied_unfocused: String,
    pub free_focused: String,
    pub free_unfocused: String,
    pub urgent_focused: String,
    pub urgent_unfocused: String,
}

fn get_config_path() -> Option<String> {
    if let Ok(value) = var("XDG_CONFIG_HOME") {
        let path = value + &path::MAIN_SEPARATOR.to_string() + "rustlebar.toml";
        if File::open(&path).is_ok() {
            Some(path)
        } else {
            None
        }
    } else if let Ok(value) = var("HOME") {
        let path = value + &path::MAIN_SEPARATOR.to_string() + ".config" + &path::MAIN_SEPARATOR.to_string() + "rustlebar.toml";
        if File::open(&path).is_ok() {
            Some(path)
        } else {
            None
        }
    } else {
        None
    }
}

fn get_value(toml: &toml::Value, default: &str, value: &str) -> String {
    if let Some(item) = toml.lookup(value) {
        match item.as_str() {
            Some(string) => string.to_owned(),
            None => default.to_owned()
        }
    } else {
        default.to_owned()
    }
}

pub fn get_icons() -> Icons {
    let mut occupied_focused = "".to_owned();
    let mut occupied_unfocused = "".to_owned();
    let mut free_focused = "".to_owned();
    let mut free_unfocused = "".to_owned();
    let mut urgent_focused = "".to_owned();
    let mut urgent_unfocused = "".to_owned();

    let mut buffer = String::new();

    if let Some(path) = get_config_path() {
        let mut file = File::open(&path).unwrap();
        let _ = file.read_to_string(&mut buffer);
        let configuration: toml::Value = buffer.parse().unwrap();

        occupied_focused = get_value(&configuration, &occupied_focused, "icons.occupied_focused");
        occupied_unfocused = get_value(&configuration, &occupied_unfocused, "icons.occupied_unfocused");
        free_focused = get_value(&configuration, &free_focused, "icons.free_focused");
        free_unfocused = get_value(&configuration, &free_unfocused, "icons.free_unfocused");
        urgent_focused = get_value(&configuration, &urgent_focused, "icons.urgent_focused");
        urgent_unfocused = get_value(&configuration, &urgent_unfocused, "icons.urgent_unfocused");

    }

    Icons {
        occupied_focused: occupied_focused,
        occupied_unfocused: occupied_unfocused,
        free_focused: free_focused,
        free_unfocused: free_unfocused,
        urgent_focused: urgent_focused,
        urgent_unfocused: urgent_unfocused,
    }
}
<commit_msg>Minor change to file read<commit_after>extern crate toml;

use std::io::Read;
use std::env::var;
use std::path;
use std::fs::File;

pub struct Icons {
    pub occupied_focused: String,
    pub occupied_unfocused: String,
    pub free_focused: String,
    pub free_unfocused: String,
    pub urgent_focused: String,
    pub urgent_unfocused: String,
}

fn get_config_path() -> Option<String> {
    if let Ok(value) = var("XDG_CONFIG_HOME") {
        Some(value + &path::MAIN_SEPARATOR.to_string() + "rustlebar.toml")
    } else if let Ok(value) = var("HOME") {
        Some(value + &path::MAIN_SEPARATOR.to_string() + ".config" + &path::MAIN_SEPARATOR.to_string() + "rustlebar.toml")
    } else {
        None
    }
}

fn get_value(toml: &toml::Value, default: &str, value: &str) -> String {
    if let Some(item) = toml.lookup(value) {
        match item.as_str() {
            Some(string) => string.to_owned(),
            None => default.to_owned()
        }
    } else {
        default.to_owned()
    }
}

pub fn get_icons() -> Icons {
    let mut occupied_focused = "".to_owned();
    let mut occupied_unfocused = "".to_owned();
    let mut free_focused = "".to_owned();
    let mut free_unfocused = "".to_owned();
    let mut urgent_focused = "".to_owned();
    let mut urgent_unfocused = "".to_owned();

    let mut buffer = String::new();

    if let Some(path) = get_config_path() {
        if let Ok(mut file) = File::open(&path) {
            let _ = file.read_to_string(&mut buffer);
            let configuration: toml::Value = buffer.parse().unwrap();

            occupied_focused = get_value(&configuration, &occupied_focused, "icons.occupied_focused");
            occupied_unfocused = get_value(&configuration, &occupied_unfocused, "icons.occupied_unfocused");
            free_focused = get_value(&configuration, &free_focused, "icons.free_focused");
            free_unfocused = get_value(&configuration, &free_unfocused, "icons.free_unfocused");
            urgent_focused = get_value(&configuration, &urgent_focused, "icons.urgent_focused");
            urgent_unfocused = get_value(&configuration, &urgent_unfocused, "icons.urgent_unfocused");
        }
    }

    Icons {
        occupied_focused: occupied_focused,
        occupied_unfocused: occupied_unfocused,
        free_focused: free_focused,
        free_unfocused: free_unfocused,
        urgent_focused: urgent_focused,
        urgent_unfocused: urgent_unfocused,
    }
}
<|endoftext|>


<commit_before>extern crate serde_json;

use std::path::Path;
use std::fs::File;
use std::{env,process};
use std::io::{stderr,BufReader,Write};

pub fn load() -> serde_json::Value {
    let home_dir_path_buffer = match env::home_dir() {
        Some(path) => path,
        None => {
            println!("Couldn't find home directory.");
            process::exit(1);
        }
    };

    let home_dir_path = home_dir_path_buffer.to_str().unwrap();
    let config_file_path = format!("{}/.config/osxnotifysounds/config.json", home_dir_path);

    if !Path::new(&config_file_path).exists() {
        writeln!(
            stderr(),
            "You don't have a configuration set at {}.\n\
            Make sure that's in place first, so I know which sounds to use for which notification.",
            config_file_path
        ).unwrap();
        process::exit(1);
    }

    let file = File::open(config_file_path).expect("Json file not found.");

    let file_reader = BufReader::new(file);
    serde_json::from_reader(file_reader)
        .expect("Couldn't parse json file.  Validate with json linter to confirm.")
}<commit_msg>write to stderr for load() on failure<commit_after>extern crate serde_json;

use std::path::Path;
use std::fs::File;
use std::{env,process};
use std::io::{stderr,BufReader,Write};

pub fn load() -> serde_json::Value {
    let home_dir_path_buffer = match env::home_dir() {
        Some(path) => path,
        None => {
            writeln!(
                stderr(),
                "Couldn't find home directory."
            ).unwrap();
            process::exit(1);
        }
    };

    let home_dir_path = home_dir_path_buffer.to_str().unwrap();
    let config_file_path = format!("{}/.config/osxnotifysounds/config.json", home_dir_path);

    if !Path::new(&config_file_path).exists() {
        writeln!(
            stderr(),
            "You don't have a configuration set at {}.\n\
            Make sure that's in place first, so I know which sounds to use for which notification.",
            config_file_path
        ).unwrap();
        process::exit(1);
    }

    let file = File::open(config_file_path).expect("Json file not found.");

    let file_reader = BufReader::new(file);
    serde_json::from_reader(file_reader)
        .expect("Couldn't parse json file.  Validate with json linter to confirm.")
}<|endoftext|>


<commit_before>//! The [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap) table

use font_types::Tag;

/// 'cmap'
pub const TAG: Tag = Tag::new(b"cmap");

include!("../../generated/generated_cmap.rs");

impl<'a> Cmap<'a> {
    /// Maps a codepoint to a nominal glyph identifier using the first
    /// available subtable that provides a valid mapping.
    pub fn map_codepoint(&self, codepoint: u32) -> Option<GlyphId> {
        for record in self.encoding_records() {
            if let Ok(subtable) = record.subtable(self.offset_data()) {
                if let Some(gid) = match subtable {
                    CmapSubtable::Format4(format4) => format4.map_codepoint(codepoint),
                    CmapSubtable::Format12(format12) => format12.map_codepoint(codepoint),
                    _ => None,
                } {
                    return Some(gid);
                }
            }
        }
        None
    }
}

impl<'a> Cmap4<'a> {
    /// Maps a codepoint to a nominal glyph identifier.
    pub fn map_codepoint(&self, codepoint: u32) -> Option<GlyphId> {
        if codepoint >= 65535 {
            return None;
        }
        let codepoint = codepoint as u16;
        let mut lo = 0;
        let mut hi = self.seg_count_x2() as usize / 2;
        let start_codes = self.start_code();
        let end_codes = self.end_code();
        while lo < hi {
            let i = (lo + hi) / 2;
            let start_code = start_codes.get(i)?.get();
            if codepoint < start_code {
                hi = i;
            } else if codepoint > end_codes.get(i)?.get() {
                lo = i + 1;
            } else {
                let deltas = self.id_delta();
                let range_offsets = self.id_range_offsets();
                let delta = deltas.get(i)?.get() as i32;
                let range_offset = range_offsets.get(i)?.get() as usize;
                if range_offset == 0 {
                    return Some(GlyphId::new((codepoint as i32 + delta) as u16));
                }
                // sigh
                let mut offset = range_offset / 2 + (codepoint - start_code) as usize;
                offset = offset.saturating_sub(range_offsets.len() - i);
                let gid = self.glyph_id_array().get(offset)?.get();
                if gid != 0 {
                    return Some(GlyphId::new((gid as i32 + delta) as u16));
                } else {
                    return None;
                }
            }
        }
        None
    }
}

impl<'a> Cmap12<'a> {
    /// Maps a codepoint to a nominal glyph identifier.
    pub fn map_codepoint(&self, codepoint: u32) -> Option<GlyphId> {
        let groups = self.groups();
        let mut lo = 0;
        let mut hi = groups.len();
        while lo < hi {
            let i = (lo + hi) / 2;
            let group = groups.get(i)?;
            if codepoint < group.start_char_code() {
                hi = i;
            } else if codepoint > group.end_char_code() {
                lo = i + 1;
            } else {
                return Some(GlyphId::new(
                    (group
                        .start_glyph_id()
                        .wrapping_add(codepoint.wrapping_sub(group.start_char_code())))
                        as u16,
                ));
            }
        }
        None
    }
}
<commit_msg>add some cmap tests<commit_after>//! The [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap) table

use font_types::Tag;

/// 'cmap'
pub const TAG: Tag = Tag::new(b"cmap");

include!("../../generated/generated_cmap.rs");

impl<'a> Cmap<'a> {
    /// Maps a codepoint to a nominal glyph identifier using the first
    /// available subtable that provides a valid mapping.
    pub fn map_codepoint(&self, codepoint: impl Into<u32>) -> Option<GlyphId> {
        let codepoint = codepoint.into();
        for record in self.encoding_records() {
            if let Ok(subtable) = record.subtable(self.offset_data()) {
                if let Some(gid) = match subtable {
                    CmapSubtable::Format4(format4) => format4.map_codepoint(codepoint),
                    CmapSubtable::Format12(format12) => format12.map_codepoint(codepoint),
                    _ => None,
                } {
                    return Some(gid);
                }
            }
        }
        None
    }
}

impl<'a> Cmap4<'a> {
    /// Maps a codepoint to a nominal glyph identifier.
    pub fn map_codepoint(&self, codepoint: impl Into<u32>) -> Option<GlyphId> {
        let codepoint = codepoint.into();
        if codepoint > 0xFFFF {
            return None;
        }
        let codepoint = codepoint as u16;
        let mut lo = 0;
        let mut hi = self.seg_count_x2() as usize / 2;
        let start_codes = self.start_code();
        let end_codes = self.end_code();
        while lo < hi {
            let i = (lo + hi) / 2;
            let start_code = start_codes.get(i)?.get();
            if codepoint < start_code {
                hi = i;
            } else if codepoint > end_codes.get(i)?.get() {
                lo = i + 1;
            } else {
                let deltas = self.id_delta();
                let range_offsets = self.id_range_offsets();
                let delta = deltas.get(i)?.get() as i32;
                let range_offset = range_offsets.get(i)?.get() as usize;
                if range_offset == 0 {
                    return Some(GlyphId::new((codepoint as i32 + delta) as u16));
                }
                // sigh
                let mut offset = range_offset / 2 + (codepoint - start_code) as usize;
                offset = offset.saturating_sub(range_offsets.len() - i);
                let gid = self.glyph_id_array().get(offset)?.get();
                if gid != 0 {
                    return Some(GlyphId::new((gid as i32 + delta) as u16));
                } else {
                    return None;
                }
            }
        }
        None
    }
}

impl<'a> Cmap12<'a> {
    /// Maps a codepoint to a nominal glyph identifier.
    pub fn map_codepoint(&self, codepoint: impl Into<u32>) -> Option<GlyphId> {
        let codepoint = codepoint.into();
        let groups = self.groups();
        let mut lo = 0;
        let mut hi = groups.len();
        while lo < hi {
            let i = (lo + hi) / 2;
            let group = groups.get(i)?;
            if codepoint < group.start_char_code() {
                hi = i;
            } else if codepoint > group.end_char_code() {
                lo = i + 1;
            } else {
                return Some(GlyphId::new(
                    (group
                        .start_glyph_id()
                        .wrapping_add(codepoint.wrapping_sub(group.start_char_code())))
                        as u16,
                ));
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use crate::test_data;
    use crate::{FontRef, GlyphId, TableProvider};

    #[test]
    fn map_codepoints() {
        let font = FontRef::new(test_data::test_fonts::VAZIRMATN_VAR).unwrap();
        let cmap = font.cmap().unwrap();
        assert_eq!(cmap.map_codepoint('A'), Some(GlyphId::new(1)));
        assert_eq!(cmap.map_codepoint('À'), Some(GlyphId::new(2)));
        assert_eq!(cmap.map_codepoint('`'), Some(GlyphId::new(3)));
        assert_eq!(cmap.map_codepoint('B'), None);

        let font = FontRef::new(test_data::test_fonts::SIMPLE_GLYF).unwrap();
        let cmap = font.cmap().unwrap();
        assert_eq!(cmap.map_codepoint(' '), Some(GlyphId::new(1)));
        assert_eq!(cmap.map_codepoint(0xE_u32), Some(GlyphId::new(2)));
        assert_eq!(cmap.map_codepoint('B'), None);
    }
}
<|endoftext|>