<commit_before>use rustc::ty::{self, Ty};
use syntax::ast::{FloatTy, IntTy, UintTy};

use error::{EvalResult, EvalError};
use eval_context::EvalContext;
use value::PrimVal;

impl<'a, 'tcx> EvalContext<'a, 'tcx> {
    pub(super) fn cast_primval(
        &self,
        val: PrimVal,
        src_ty: Ty<'tcx>,
        dest_ty: Ty<'tcx>
    ) -> EvalResult<'tcx, PrimVal> {
        let src_kind = self.ty_to_primval_kind(src_ty)?;

        use value::PrimValKind::*;
        match src_kind {
            F32 => self.cast_float(val.to_f32()? as f64, dest_ty),
            F64 => self.cast_float(val.to_f64()?, dest_ty),

            I8 | I16 | I32 | I64 | I128 => {
                if val.is_ptr() {
                    self.cast_ptr(val, dest_ty)
                } else {
                    self.cast_signed_int(val.to_i128()?, dest_ty)
                }
            },

            Bool | Char | U8 | U16 | U32 | U64 | U128 => {
                if val.is_ptr() {
                    self.cast_ptr(val, dest_ty)
                } else {
                    self.cast_int(val.to_u128()?, dest_ty, false)
                }
            },

            FnPtr | Ptr => self.cast_ptr(val, dest_ty),
        }
    }

    fn cast_signed_int(&self, val: i128, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
        self.cast_int(val as u128, ty, val < 0)
    }

    fn cast_int(&self, v: u128, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> {
        use rustc::ty::TypeVariants::*;
        match ty.sty {
            // Casts to bool are not permitted by rustc, no need to handle them here.

            TyInt(IntTy::I8)  => Ok(PrimVal::Bytes(v as i128 as i8  as u128)),
            TyInt(IntTy::I16) => Ok(PrimVal::Bytes(v as i128 as i16 as u128)),
            TyInt(IntTy::I32) => Ok(PrimVal::Bytes(v as i128 as i32 as u128)),
            TyInt(IntTy::I64) => Ok(PrimVal::Bytes(v as i128 as i64 as u128)),
            TyInt(IntTy::I128) => Ok(PrimVal::Bytes(v as u128)),

            TyUint(UintTy::U8)  => Ok(PrimVal::Bytes(v as u8  as u128)),
            TyUint(UintTy::U16) => Ok(PrimVal::Bytes(v as u16 as u128)),
            TyUint(UintTy::U32) => Ok(PrimVal::Bytes(v as u32 as u128)),
            TyUint(UintTy::U64) => Ok(PrimVal::Bytes(v as u64 as u128)),
            TyUint(UintTy::U128) => Ok(PrimVal::Bytes(v)),

            TyInt(IntTy::Is) => {
                let int_ty = self.tcx.sess.target.int_type;
                let ty = self.tcx.mk_mach_int(int_ty);
                self.cast_int(v, ty, negative)
            }

            TyUint(UintTy::Us) => {
                let uint_ty = self.tcx.sess.target.uint_type;
                let ty = self.tcx.mk_mach_uint(uint_ty);
                self.cast_int(v, ty, negative)
            }

            TyFloat(FloatTy::F64) if negative => Ok(PrimVal::from_f64(v as i128 as f64)),
            TyFloat(FloatTy::F64)             => Ok(PrimVal::from_f64(v as f64)),
            TyFloat(FloatTy::F32) if negative => Ok(PrimVal::from_f32(v as i128 as f32)),
            TyFloat(FloatTy::F32)             => Ok(PrimVal::from_f32(v as f32)),

            TyChar if v as u8 as u128 == v => Ok(PrimVal::Bytes(v)),
            TyChar => Err(EvalError::InvalidChar(v)),

            // No alignment check needed for raw pointers
            TyRawPtr(_) => Ok(PrimVal::Bytes(v % (1 << (self.memory.pointer_size()*8)))),

            _ => Err(EvalError::Unimplemented(format!("int to {:?} cast", ty))),
        }
    }

    fn cast_float(&self, val: f64, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
        use rustc::ty::TypeVariants::*;
        match ty.sty {
            // Casting negative floats to unsigned integers yields zero.
            TyUint(_) if val < 0.0 => self.cast_int(0, ty, false),
            TyInt(_)  if val < 0.0 => self.cast_int(val as i128 as u128, ty, true),

            TyInt(_) | ty::TyUint(_) => self.cast_int(val as u128, ty, false),

            TyFloat(FloatTy::F64) => Ok(PrimVal::from_f64(val)),
            TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(val as f32)),
            _ => Err(EvalError::Unimplemented(format!("float to {:?} cast", ty))),
        }
    }

    fn cast_ptr(&self, ptr: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
        use rustc::ty::TypeVariants::*;
        match ty.sty {
            // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
            TyRawPtr(_) | TyInt(IntTy::Is) | TyUint(UintTy::Us) =>
                Ok(ptr),
            TyInt(_) | TyUint(_) => Err(EvalError::ReadPointerAsBytes),
            _ => Err(EvalError::Unimplemented(format!("ptr to {:?} cast", ty))),
        }
    }
}
<commit_msg>refactor casting code to more clearly handle pointers<commit_after>use rustc::ty::{self, Ty};
use syntax::ast::{FloatTy, IntTy, UintTy};

use error::{EvalResult, EvalError};
use eval_context::EvalContext;
use value::PrimVal;
use memory::MemoryPointer;

impl<'a, 'tcx> EvalContext<'a, 'tcx> {
    pub(super) fn cast_primval(
        &self,
        val: PrimVal,
        src_ty: Ty<'tcx>,
        dest_ty: Ty<'tcx>
    ) -> EvalResult<'tcx, PrimVal> {
        let src_kind = self.ty_to_primval_kind(src_ty)?;

        match val {
            PrimVal::Undef => Ok(PrimVal::Undef),
            PrimVal::Ptr(ptr) => self.cast_from_ptr(ptr, dest_ty),
            val @ PrimVal::Bytes(_) => {
                use value::PrimValKind::*;
                match src_kind {
                    F32 => self.cast_from_float(val.to_f32()? as f64, dest_ty),
                    F64 => self.cast_from_float(val.to_f64()?, dest_ty),

                    I8 | I16 | I32 | I64 | I128 => {
                        self.cast_from_signed_int(val.to_i128()?, dest_ty)
                    },

                    Bool | Char | U8 | U16 | U32 | U64 | U128 | FnPtr | Ptr => {
                        self.cast_from_int(val.to_u128()?, dest_ty, false)
                    },
                }
            }
        }
    }

    fn cast_from_signed_int(&self, val: i128, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
        self.cast_from_int(val as u128, ty, val < 0)
    }

    fn cast_from_int(&self, v: u128, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> {
        use rustc::ty::TypeVariants::*;
        match ty.sty {
            // Casts to bool are not permitted by rustc, no need to handle them here.

            TyInt(IntTy::I8)  => Ok(PrimVal::Bytes(v as i128 as i8  as u128)),
            TyInt(IntTy::I16) => Ok(PrimVal::Bytes(v as i128 as i16 as u128)),
            TyInt(IntTy::I32) => Ok(PrimVal::Bytes(v as i128 as i32 as u128)),
            TyInt(IntTy::I64) => Ok(PrimVal::Bytes(v as i128 as i64 as u128)),
            TyInt(IntTy::I128) => Ok(PrimVal::Bytes(v as u128)),

            TyUint(UintTy::U8)  => Ok(PrimVal::Bytes(v as u8  as u128)),
            TyUint(UintTy::U16) => Ok(PrimVal::Bytes(v as u16 as u128)),
            TyUint(UintTy::U32) => Ok(PrimVal::Bytes(v as u32 as u128)),
            TyUint(UintTy::U64) => Ok(PrimVal::Bytes(v as u64 as u128)),
            TyUint(UintTy::U128) => Ok(PrimVal::Bytes(v)),

            TyInt(IntTy::Is) => {
                let int_ty = self.tcx.sess.target.int_type;
                let ty = self.tcx.mk_mach_int(int_ty);
                self.cast_from_int(v, ty, negative)
            }

            TyUint(UintTy::Us) => {
                let uint_ty = self.tcx.sess.target.uint_type;
                let ty = self.tcx.mk_mach_uint(uint_ty);
                self.cast_from_int(v, ty, negative)
            }

            TyFloat(FloatTy::F64) if negative => Ok(PrimVal::from_f64(v as i128 as f64)),
            TyFloat(FloatTy::F64)             => Ok(PrimVal::from_f64(v as f64)),
            TyFloat(FloatTy::F32) if negative => Ok(PrimVal::from_f32(v as i128 as f32)),
            TyFloat(FloatTy::F32)             => Ok(PrimVal::from_f32(v as f32)),

            TyChar if v as u8 as u128 == v => Ok(PrimVal::Bytes(v)),
            TyChar => Err(EvalError::InvalidChar(v)),

            // No alignment check needed for raw pointers
            TyRawPtr(_) => Ok(PrimVal::Bytes(v % (1 << (self.memory.pointer_size()*8)))),

            _ => Err(EvalError::Unimplemented(format!("int to {:?} cast", ty))),
        }
    }

    fn cast_from_float(&self, val: f64, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
        use rustc::ty::TypeVariants::*;
        match ty.sty {
            // Casting negative floats to unsigned integers yields zero.
            TyUint(_) if val < 0.0 => self.cast_from_int(0, ty, false),
            TyInt(_)  if val < 0.0 => self.cast_from_int(val as i128 as u128, ty, true),

            TyInt(_) | ty::TyUint(_) => self.cast_from_int(val as u128, ty, false),

            TyFloat(FloatTy::F64) => Ok(PrimVal::from_f64(val)),
            TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(val as f32)),
            _ => Err(EvalError::Unimplemented(format!("float to {:?} cast", ty))),
        }
    }

    fn cast_from_ptr(&self, ptr: MemoryPointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
        use rustc::ty::TypeVariants::*;
        match ty.sty {
            // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
            TyRawPtr(_) | TyInt(IntTy::Is) | TyUint(UintTy::Us) =>
                Ok(PrimVal::Ptr(ptr)),
            TyInt(_) | TyUint(_) => Err(EvalError::ReadPointerAsBytes),
            _ => Err(EvalError::Unimplemented(format!("ptr to {:?} cast", ty))),
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Adding a benchmark for the new message passing code<commit_after>// This test creates a bunch of tasks that simultaneously send to each
// other in a ring. The messages should all be basically
// independent. It's designed to hammer the global kernel lock, so
// that things will look really good once we get that lock out of the
// message path.

import newcomm::*;
import future::future;

use std;
import std::time;

fn thread_ring(i: uint,
               count: uint,
               num_chan: chan<uint>,
               num_port: port<uint>) {
    // Send/Receive lots of messages.
    for uint::range(0u, count) {|j|
        num_chan.send(i * j);
        num_port.recv();
    };
}

fn main(args: [str]) {
    let args = if os::getenv("RUST_BENCH").is_some() {
        ["", "100", "10000"]
    } else if args.len() <= 1u {
        ["", "100", "1000"]
    } else {
        args
    };

    let num_tasks = option::get(uint::from_str(args[1]));
    let msg_per_task = option::get(uint::from_str(args[2]));

    let num_port = port();
    let mut num_chan = chan(num_port);

    let start = time::precise_time_s();

    // create the ring
    let mut futures = [];

    for uint::range(1u, num_tasks) {|i|
        let get_chan = port();
        let get_chan_chan = chan(get_chan);
        {
            let num_chan = num_chan.clone();
            futures += [future::spawn {|move num_chan, move get_chan_chan|
                let p = port();
                get_chan_chan.send(chan(p));
                thread_ring(i, msg_per_task, num_chan,  p)
            }];
        }

        num_chan = get_chan.recv();
    };

    // do our iteration
    thread_ring(0u, msg_per_task, num_chan, num_port);

    // synchronize
    for futures.each {|f| f.get() };

    let stop = time::precise_time_s();

    // all done, report stats.
    let num_msgs = num_tasks * msg_per_task;
    let elapsed = (stop - start);
    let rate = (num_msgs as float) / elapsed;

    io::println(#fmt("Sent %? messages in %? seconds",
                     num_msgs, elapsed));
    io::println(#fmt("  %? messages / second", rate));
    io::println(#fmt("  %? μs / message", 1000000. / rate));
}
<|endoftext|>


<commit_before><commit_msg>test too big slice<commit_after>use std::mem;
use std::usize;

fn main() { unsafe {
    let ptr = Box::into_raw(Box::new(0u8));
    let _x: &[u8] = mem::transmute((ptr, usize::MAX)); //~ ERROR: invalid slice: total size is bigger than largest supported object
} }
<|endoftext|>


<commit_before><commit_msg>update<commit_after><|endoftext|>


<commit_before><commit_msg>Add meh solution for problem 19<commit_after>#[macro_use] extern crate libeuler;

// You are given the following information, but you may prefer to do some research for yourself.
//
//  1 Jan 1900 was a Monday.
//
//  Thirty days has September,
//  April, June and November.
//  All the rest have thirty-one,
//  Saving February alone,
//  Which has twenty-eight, rain or shine.
//  And on leap years, twenty-nine.
//
//  A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
//
// How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

fn main() {
    solutions! {
        inputs: (start_year: u16 = 1900, end_year: u16 = 2000)

        sol naive {
            let start_month = Month::new(0, start_year);

            let mut days = 0u32;
            let mut sundays = 0u32;

            for month in start_month.iter().take_while(|ref m| m.year <= end_year) {
                if days % 7 == 6 {
                    sundays += 1;
                }

                days += month.days();
            }

            sundays
        }
    }
}

#[derive(Clone, Debug)]
struct Month {
    month: u8,
    year: u16
}

impl Month {
    fn new(month: u8, year: u16) -> Month {
        Month {
            month: month,
            year: year
        }
    }

    fn iter(&self) -> MonthIterator {
        MonthIterator {
            current_month: self.clone()
        }
    }

    fn days(&self) -> u32 {
        match self.month {
            3 | 5 | 8 | 10 => 30,
            1 => if self.year % 4 == 0 && self.year % 400 != 0 {
                29
            } else {
                28
            },
            _ => 31
        }
    }
}

struct MonthIterator {
    current_month: Month
}

impl Iterator for MonthIterator {
    type Item = Month;

    fn next(&mut self) -> Option<Month> {
        let retval = self.current_month.clone();

        self.current_month.month += 1;
        self.current_month.month %= 12;
        if self.current_month.month == 0 {
            self.current_month.year += 1;
        }

        return Some(retval);
    }
}
<|endoftext|>


<commit_before><commit_msg>euler 5<commit_after>// 2520 is the smallest number that can be divided by each of the numbers from
// 1 to 10 without any remainder.
// What is the smallest positive number that is evenly divisible by all of the
// numbers from 1 to 20?

fn is_divisible(number: u64) -> bool {
	for n in (1..21) {
		if number % n != 0 { return false; }
	}
	true
}

fn main() {
	for n in (1u64..) {
		if is_divisible(n) {
			println!("{}", n);
			return;
		}
	}
}<|endoftext|>


<commit_before><commit_msg>practice<commit_after>fn main() {
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// ```
#[allow(dead_code)]
fn foo() {}
}
<|endoftext|>


<commit_before><commit_msg>lexer: remove unused lexeme<commit_after><|endoftext|>


<commit_before><commit_msg>Derive Clone, Copy, and Hash<commit_after><|endoftext|>


<commit_before><commit_msg>Finally get store replacement working with mem::replace<commit_after><|endoftext|>


<commit_before><commit_msg>Create metric aggregation struct.<commit_after><|endoftext|>


<commit_before><commit_msg> #12 Fixed compilation error in release mode<commit_after><|endoftext|>


<commit_before><commit_msg>associated functions added<commit_after><|endoftext|>


<commit_before>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
extern crate ansi_term;

use std::os;

use file::File;
use dir::Dir;
use options::Options;
use unix::Unix;

use ansi_term::{Plain, strip_formatting};

pub mod column;
pub mod dir;
pub mod format;
pub mod file;
pub mod filetype;
pub mod unix;
pub mod options;
pub mod sort;

fn main() {
    let args = os::args();

    match Options::getopts(args) {
        Err(err) => println!("Invalid options:\n{}", err),
        Ok(opts) => {
            if opts.dirs.is_empty() {
                exa(&opts, false, ".".to_string())
            }
            else {
                let mut first = true;
                let print_header = opts.dirs.len() > 1;
                for dir in opts.dirs.clone().move_iter() {
                    if first {
                        first = false;
                    }
                    else {
                        print!("\n");
                    }
                    exa(&opts, print_header, dir)
                }
            }
        }
    };
}

fn exa(options: &Options, print_header: bool, string: String) {
    let path = Path::new(string.clone());

    let dir = match Dir::readdir(path) {
        Ok(dir) => dir,
        Err(e) => {
            println!("{}: {}", string, e);
            return;
        }
    };

    // Print header *after* readdir must have succeeded
    if print_header {
        println!("{}:", string);
    }

    let unsorted_files = dir.files();
    let files: Vec<&File> = options.transform_files(&unsorted_files);

    // The output gets formatted into columns, which looks nicer. To
    // do this, we have to write the results into a table, instead of
    // displaying each file immediately, then calculating the maximum
    // width of each column based on the length of the results and
    // padding the fields during output.

    let mut cache = Unix::empty_cache();

    let mut table: Vec<Vec<String>> = files.iter()
        .map(|f| options.columns.iter().map(|c| f.display(c, &mut cache)).collect())
        .collect();

    if options.header {
        table.unshift(options.columns.iter().map(|c| Plain.underline().paint(c.header())).collect());
    }

    // Each column needs to have its invisible colour-formatting
    // characters stripped before it has its width calculated, or the
    // width will be incorrect and the columns won't line up properly.
    // This is fairly expensive to do (it uses a regex), so the
    // results are cached.

    let lengths: Vec<Vec<uint>> = table.iter()
        .map(|row| row.iter().map(|col| strip_formatting(col.clone()).len()).collect())
        .collect();

    let column_widths: Vec<uint> = range(0, options.columns.len())
        .map(|n| lengths.iter().map(|row| *row.get(n)).max().unwrap())
        .collect();

    for (field_widths, row) in lengths.iter().zip(table.iter()) {
        for (num, column) in options.columns.iter().enumerate() {
            if num != 0 {
                print!(" ");
            }

            if num == options.columns.len() - 1 {
                print!("{}", row.get(num));
            }
            else {
                let padding = *column_widths.get(num) - *field_widths.get(num);
                print!("{}", column.alignment().pad_string(row.get(num), padding));
            }
        }
        print!("\n");
    }
}
<commit_msg>Rename variable<commit_after>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
extern crate ansi_term;

use std::os;

use file::File;
use dir::Dir;
use options::Options;
use unix::Unix;

use ansi_term::{Plain, strip_formatting};

pub mod column;
pub mod dir;
pub mod format;
pub mod file;
pub mod filetype;
pub mod unix;
pub mod options;
pub mod sort;

fn main() {
    let args = os::args();

    match Options::getopts(args) {
        Err(err) => println!("Invalid options:\n{}", err),
        Ok(opts) => {
            if opts.dirs.is_empty() {
                exa(&opts, false, ".".to_string())
            }
            else {
                let mut first = true;
                let print_dir_names = opts.dirs.len() > 1;
                for dir in opts.dirs.clone().move_iter() {
                    if first {
                        first = false;
                    }
                    else {
                        print!("\n");
                    }
                    exa(&opts, print_dir_names, dir)
                }
            }
        }
    };
}

fn exa(options: &Options, print_dir_names: bool, string: String) {
    let path = Path::new(string.clone());

    let dir = match Dir::readdir(path) {
        Ok(dir) => dir,
        Err(e) => {
            println!("{}: {}", string, e);
            return;
        }
    };

    // Print header *after* readdir must have succeeded
    if print_dir_names {
        println!("{}:", string);
    }

    let unsorted_files = dir.files();
    let files: Vec<&File> = options.transform_files(&unsorted_files);

    // The output gets formatted into columns, which looks nicer. To
    // do this, we have to write the results into a table, instead of
    // displaying each file immediately, then calculating the maximum
    // width of each column based on the length of the results and
    // padding the fields during output.

    let mut cache = Unix::empty_cache();

    let mut table: Vec<Vec<String>> = files.iter()
        .map(|f| options.columns.iter().map(|c| f.display(c, &mut cache)).collect())
        .collect();

    if options.header {
        table.unshift(options.columns.iter().map(|c| Plain.underline().paint(c.header())).collect());
    }

    // Each column needs to have its invisible colour-formatting
    // characters stripped before it has its width calculated, or the
    // width will be incorrect and the columns won't line up properly.
    // This is fairly expensive to do (it uses a regex), so the
    // results are cached.

    let lengths: Vec<Vec<uint>> = table.iter()
        .map(|row| row.iter().map(|col| strip_formatting(col.clone()).len()).collect())
        .collect();

    let column_widths: Vec<uint> = range(0, options.columns.len())
        .map(|n| lengths.iter().map(|row| *row.get(n)).max().unwrap())
        .collect();

    for (field_widths, row) in lengths.iter().zip(table.iter()) {
        for (num, column) in options.columns.iter().enumerate() {
            if num != 0 {
                print!(" ");
            }

            if num == options.columns.len() - 1 {
                print!("{}", row.get(num));
            }
            else {
                let padding = *column_widths.get(num) - *field_widths.get(num);
                print!("{}", column.alignment().pad_string(row.get(num), padding));
            }
        }
        print!("\n");
    }
}
<|endoftext|>


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

// Detecting language items.
//
// Language items are items that represent concepts intrinsic to the language
// itself. Examples are:
//
// * Traits that specify "kinds"; e.g. "Sync", "Send".
//
// * Traits that represent operators; e.g. "Add", "Sub", "Index".
//
// * Functions called by the compiler itself.

pub use self::LangItem::*;

use hir::def_id::DefId;
use ty::{self, TyCtxt};
use middle::weak_lang_items;
use util::nodemap::FxHashMap;

use syntax::ast;
use syntax::symbol::Symbol;
use hir::itemlikevisit::ItemLikeVisitor;
use hir;

// The actual lang items defined come at the end of this file in one handy table.
// So you probably just want to nip down to the end.
macro_rules! language_item_table {
    (
        $( $variant:ident, $name:expr, $method:ident; )*
    ) => {

enum_from_u32! {
    #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
    pub enum LangItem {
        $($variant,)*
    }
}

impl LangItem {
    fn name(self) -> &'static str {
        match self {
            $( $variant => $name, )*
        }
    }
}

pub struct LanguageItems {
    pub items: Vec<Option<DefId>>,
    pub missing: Vec<LangItem>,
}

impl LanguageItems {
    pub fn new() -> LanguageItems {
        fn foo(_: LangItem) -> Option<DefId> { None }

        LanguageItems {
            items: vec![$(foo($variant)),*],
            missing: Vec::new(),
        }
    }

    pub fn items(&self) -> &[Option<DefId>] {
        &*self.items
    }

    pub fn require(&self, it: LangItem) -> Result<DefId, String> {
        self.items[it as usize].ok_or(format!("requires `{}` lang_item", it.name()))
    }

    pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
        let def_id_kinds = [
            (self.fn_trait(), ty::ClosureKind::Fn),
            (self.fn_mut_trait(), ty::ClosureKind::FnMut),
            (self.fn_once_trait(), ty::ClosureKind::FnOnce),
            ];

        for &(opt_def_id, kind) in &def_id_kinds {
            if Some(id) == opt_def_id {
                return Some(kind);
            }
        }

        None
    }

    $(
        #[allow(dead_code)]
        pub fn $method(&self) -> Option<DefId> {
            self.items[$variant as usize]
        }
    )*
}

struct LanguageItemCollector<'a, 'tcx: 'a> {
    items: LanguageItems,

    tcx: TyCtxt<'a, 'tcx, 'tcx>,

    item_refs: FxHashMap<&'static str, usize>,
}

impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
    fn visit_item(&mut self, item: &hir::Item) {
        if let Some(value) = extract(&item.attrs) {
            let item_index = self.item_refs.get(&*value.as_str()).cloned();

            if let Some(item_index) = item_index {
                let def_id = self.tcx.hir.local_def_id(item.id);
                self.collect_item(item_index, def_id);
            } else {
                let span = self.tcx.hir.span(item.id);
                span_err!(self.tcx.sess, span, E0522,
                          "definition of an unknown language item: `{}`.",
                          value);
            }
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
        // at present, lang items are always items, not trait items
    }

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
        // at present, lang items are always items, not impl items
    }
}

impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItemCollector<'a, 'tcx> {
        let mut item_refs = FxHashMap();

        $( item_refs.insert($name, $variant as usize); )*

        LanguageItemCollector {
            tcx,
            items: LanguageItems::new(),
            item_refs,
        }
    }

    fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
        // Check for duplicates.
        match self.items.items[item_index] {
            Some(original_def_id) if original_def_id != item_def_id => {
                let name = LangItem::from_u32(item_index as u32).unwrap().name();
                let mut err = match self.tcx.hir.span_if_local(item_def_id) {
                    Some(span) => struct_span_err!(
                        self.tcx.sess,
                        span,
                        E0152,
                        "duplicate lang item found: `{}`.",
                        name),
                    None => self.tcx.sess.struct_err(&format!(
                            "duplicate lang item in crate `{}`: `{}`.",
                            self.tcx.crate_name(item_def_id.krate),
                            name)),
                };
                if let Some(span) = self.tcx.hir.span_if_local(original_def_id) {
                    span_note!(&mut err, span,
                               "first defined here.");
                } else {
                    err.note(&format!("first defined in crate `{}`.",
                                      self.tcx.crate_name(original_def_id.krate)));
                }
                err.emit();
            }
            _ => {
                // OK.
            }
        }

        // Matched.
        self.items.items[item_index] = Some(item_def_id);
    }
}

pub fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
    for attribute in attrs {
        if attribute.check_name("lang") {
            if let Some(value) = attribute.value_str() {
                return Some(value)
            }
        }
    }

    return None;
}

pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
    let mut collector = LanguageItemCollector::new(tcx);
    for &cnum in tcx.crates().iter() {
        for &(index, item_index) in tcx.defined_lang_items(cnum).iter() {
            let def_id = DefId { krate: cnum, index: index };
            collector.collect_item(item_index, def_id);
        }
    }
    tcx.hir.krate().visit_all_item_likes(&mut collector);
    let LanguageItemCollector { mut items, .. } = collector;
    weak_lang_items::check_crate(tcx, &mut items);
    items
}

// End of the macro
    }
}

language_item_table! {
//  Variant name,                    Name,                      Method name;
    CharImplItem,                    "char",                    char_impl;
    StrImplItem,                     "str",                     str_impl;
    SliceImplItem,                   "slice",                   slice_impl;
    ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
    MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
    I8ImplItem,                      "i8",                      i8_impl;
    I16ImplItem,                     "i16",                     i16_impl;
    I32ImplItem,                     "i32",                     i32_impl;
    I64ImplItem,                     "i64",                     i64_impl;
    I128ImplItem,                     "i128",                   i128_impl;
    IsizeImplItem,                   "isize",                   isize_impl;
    U8ImplItem,                      "u8",                      u8_impl;
    U16ImplItem,                     "u16",                     u16_impl;
    U32ImplItem,                     "u32",                     u32_impl;
    U64ImplItem,                     "u64",                     u64_impl;
    U128ImplItem,                    "u128",                    u128_impl;
    UsizeImplItem,                   "usize",                   usize_impl;
    F32ImplItem,                     "f32",                     f32_impl;
    F64ImplItem,                     "f64",                     f64_impl;

    SendTraitLangItem,               "send",                    send_trait;
    SizedTraitLangItem,              "sized",                   sized_trait;
    UnsizeTraitLangItem,             "unsize",                  unsize_trait;
    CopyTraitLangItem,               "copy",                    copy_trait;
    CloneTraitLangItem,              "clone",                   clone_trait;
    SyncTraitLangItem,               "sync",                    sync_trait;
    FreezeTraitLangItem,             "freeze",                  freeze_trait;

    DropTraitLangItem,               "drop",                    drop_trait;

    CoerceUnsizedTraitLangItem,      "coerce_unsized",          coerce_unsized_trait;

    AddTraitLangItem,                "add",                     add_trait;
    SubTraitLangItem,                "sub",                     sub_trait;
    MulTraitLangItem,                "mul",                     mul_trait;
    DivTraitLangItem,                "div",                     div_trait;
    RemTraitLangItem,                "rem",                     rem_trait;
    NegTraitLangItem,                "neg",                     neg_trait;
    NotTraitLangItem,                "not",                     not_trait;
    BitXorTraitLangItem,             "bitxor",                  bitxor_trait;
    BitAndTraitLangItem,             "bitand",                  bitand_trait;
    BitOrTraitLangItem,              "bitor",                   bitor_trait;
    ShlTraitLangItem,                "shl",                     shl_trait;
    ShrTraitLangItem,                "shr",                     shr_trait;
    AddAssignTraitLangItem,          "add_assign",              add_assign_trait;
    SubAssignTraitLangItem,          "sub_assign",              sub_assign_trait;
    MulAssignTraitLangItem,          "mul_assign",              mul_assign_trait;
    DivAssignTraitLangItem,          "div_assign",              div_assign_trait;
    RemAssignTraitLangItem,          "rem_assign",              rem_assign_trait;
    BitXorAssignTraitLangItem,       "bitxor_assign",           bitxor_assign_trait;
    BitAndAssignTraitLangItem,       "bitand_assign",           bitand_assign_trait;
    BitOrAssignTraitLangItem,        "bitor_assign",            bitor_assign_trait;
    ShlAssignTraitLangItem,          "shl_assign",              shl_assign_trait;
    ShrAssignTraitLangItem,          "shr_assign",              shr_assign_trait;
    IndexTraitLangItem,              "index",                   index_trait;
    IndexMutTraitLangItem,           "index_mut",               index_mut_trait;

    UnsafeCellTypeLangItem,          "unsafe_cell",             unsafe_cell_type;

    DerefTraitLangItem,              "deref",                   deref_trait;
    DerefMutTraitLangItem,           "deref_mut",               deref_mut_trait;

    FnTraitLangItem,                 "fn",                      fn_trait;
    FnMutTraitLangItem,              "fn_mut",                  fn_mut_trait;
    FnOnceTraitLangItem,             "fn_once",                 fn_once_trait;

    GeneratorStateLangItem,          "generator_state",         gen_state;
    GeneratorTraitLangItem,          "generator",               gen_trait;

    EqTraitLangItem,                 "eq",                      eq_trait;
    OrdTraitLangItem,                "ord",                     ord_trait;

    StrEqFnLangItem,                 "str_eq",                  str_eq_fn;

    // A number of panic-related lang items. The `panic` item corresponds to
    // divide-by-zero and various panic cases with `match`. The
    // `panic_bounds_check` item is for indexing arrays.
    //
    // The `begin_unwind` lang item has a predefined symbol name and is sort of
    // a "weak lang item" in the sense that a crate is not required to have it
    // defined to use it, but a final product is required to define it
    // somewhere. Additionally, there are restrictions on crates that use a weak
    // lang item, but do not have it defined.
    PanicFnLangItem,                 "panic",                   panic_fn;
    PanicBoundsCheckFnLangItem,      "panic_bounds_check",      panic_bounds_check_fn;
    PanicFmtLangItem,                "panic_fmt",               panic_fmt;

    ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
    BoxFreeFnLangItem,               "box_free",                box_free_fn;
    DropInPlaceFnLangItem,             "drop_in_place",           drop_in_place_fn;

    StartFnLangItem,                 "start",                   start_fn;

    EhPersonalityLangItem,           "eh_personality",          eh_personality;
    EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
    MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;

    OwnedBoxLangItem,                "owned_box",               owned_box;

    PhantomDataItem,                 "phantom_data",            phantom_data;

    NonZeroItem,                     "non_zero",                non_zero;

    DebugTraitLangItem,              "debug_trait",             debug_trait;
}

impl<'a, 'tcx, 'gcx> ty::TyCtxt<'a, 'tcx, 'gcx> {
    pub fn require_lang_item(&self, lang_item: LangItem) -> DefId {
        self.lang_items().require(lang_item).unwrap_or_else(|msg| {
            self.sess.fatal(&msg)
        })
    }
}
<commit_msg>Refactor fn_trait_kind<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Detecting language items.
//
// Language items are items that represent concepts intrinsic to the language
// itself. Examples are:
//
// * Traits that specify "kinds"; e.g. "Sync", "Send".
//
// * Traits that represent operators; e.g. "Add", "Sub", "Index".
//
// * Functions called by the compiler itself.

pub use self::LangItem::*;

use hir::def_id::DefId;
use ty::{self, TyCtxt};
use middle::weak_lang_items;
use util::nodemap::FxHashMap;

use syntax::ast;
use syntax::symbol::Symbol;
use hir::itemlikevisit::ItemLikeVisitor;
use hir;

// The actual lang items defined come at the end of this file in one handy table.
// So you probably just want to nip down to the end.
macro_rules! language_item_table {
    (
        $( $variant:ident, $name:expr, $method:ident; )*
    ) => {

enum_from_u32! {
    #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
    pub enum LangItem {
        $($variant,)*
    }
}

impl LangItem {
    fn name(self) -> &'static str {
        match self {
            $( $variant => $name, )*
        }
    }
}

pub struct LanguageItems {
    pub items: Vec<Option<DefId>>,
    pub missing: Vec<LangItem>,
}

impl LanguageItems {
    pub fn new() -> LanguageItems {
        fn foo(_: LangItem) -> Option<DefId> { None }

        LanguageItems {
            items: vec![$(foo($variant)),*],
            missing: Vec::new(),
        }
    }

    pub fn items(&self) -> &[Option<DefId>] {
        &*self.items
    }

    pub fn require(&self, it: LangItem) -> Result<DefId, String> {
        self.items[it as usize].ok_or(format!("requires `{}` lang_item", it.name()))
    }

    pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
        match Some(id) {
            x if x == self.fn_trait() => Some(ty::ClosureKind::Fn),
            x if x == self.fn_mut_trait() => Some(ty::ClosureKind::FnMut),
            x if x == self.fn_once_trait() =>  Some(ty::ClosureKind::FnOnce),
            _ => None
        }
    }

    $(
        #[allow(dead_code)]
        pub fn $method(&self) -> Option<DefId> {
            self.items[$variant as usize]
        }
    )*
}

struct LanguageItemCollector<'a, 'tcx: 'a> {
    items: LanguageItems,

    tcx: TyCtxt<'a, 'tcx, 'tcx>,

    item_refs: FxHashMap<&'static str, usize>,
}

impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
    fn visit_item(&mut self, item: &hir::Item) {
        if let Some(value) = extract(&item.attrs) {
            let item_index = self.item_refs.get(&*value.as_str()).cloned();

            if let Some(item_index) = item_index {
                let def_id = self.tcx.hir.local_def_id(item.id);
                self.collect_item(item_index, def_id);
            } else {
                let span = self.tcx.hir.span(item.id);
                span_err!(self.tcx.sess, span, E0522,
                          "definition of an unknown language item: `{}`.",
                          value);
            }
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
        // at present, lang items are always items, not trait items
    }

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
        // at present, lang items are always items, not impl items
    }
}

impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItemCollector<'a, 'tcx> {
        let mut item_refs = FxHashMap();

        $( item_refs.insert($name, $variant as usize); )*

        LanguageItemCollector {
            tcx,
            items: LanguageItems::new(),
            item_refs,
        }
    }

    fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
        // Check for duplicates.
        match self.items.items[item_index] {
            Some(original_def_id) if original_def_id != item_def_id => {
                let name = LangItem::from_u32(item_index as u32).unwrap().name();
                let mut err = match self.tcx.hir.span_if_local(item_def_id) {
                    Some(span) => struct_span_err!(
                        self.tcx.sess,
                        span,
                        E0152,
                        "duplicate lang item found: `{}`.",
                        name),
                    None => self.tcx.sess.struct_err(&format!(
                            "duplicate lang item in crate `{}`: `{}`.",
                            self.tcx.crate_name(item_def_id.krate),
                            name)),
                };
                if let Some(span) = self.tcx.hir.span_if_local(original_def_id) {
                    span_note!(&mut err, span,
                               "first defined here.");
                } else {
                    err.note(&format!("first defined in crate `{}`.",
                                      self.tcx.crate_name(original_def_id.krate)));
                }
                err.emit();
            }
            _ => {
                // OK.
            }
        }

        // Matched.
        self.items.items[item_index] = Some(item_def_id);
    }
}

pub fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
    for attribute in attrs {
        if attribute.check_name("lang") {
            if let Some(value) = attribute.value_str() {
                return Some(value)
            }
        }
    }

    return None;
}

pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
    let mut collector = LanguageItemCollector::new(tcx);
    for &cnum in tcx.crates().iter() {
        for &(index, item_index) in tcx.defined_lang_items(cnum).iter() {
            let def_id = DefId { krate: cnum, index: index };
            collector.collect_item(item_index, def_id);
        }
    }
    tcx.hir.krate().visit_all_item_likes(&mut collector);
    let LanguageItemCollector { mut items, .. } = collector;
    weak_lang_items::check_crate(tcx, &mut items);
    items
}

// End of the macro
    }
}

language_item_table! {
//  Variant name,                    Name,                      Method name;
    CharImplItem,                    "char",                    char_impl;
    StrImplItem,                     "str",                     str_impl;
    SliceImplItem,                   "slice",                   slice_impl;
    ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
    MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
    I8ImplItem,                      "i8",                      i8_impl;
    I16ImplItem,                     "i16",                     i16_impl;
    I32ImplItem,                     "i32",                     i32_impl;
    I64ImplItem,                     "i64",                     i64_impl;
    I128ImplItem,                     "i128",                   i128_impl;
    IsizeImplItem,                   "isize",                   isize_impl;
    U8ImplItem,                      "u8",                      u8_impl;
    U16ImplItem,                     "u16",                     u16_impl;
    U32ImplItem,                     "u32",                     u32_impl;
    U64ImplItem,                     "u64",                     u64_impl;
    U128ImplItem,                    "u128",                    u128_impl;
    UsizeImplItem,                   "usize",                   usize_impl;
    F32ImplItem,                     "f32",                     f32_impl;
    F64ImplItem,                     "f64",                     f64_impl;

    SendTraitLangItem,               "send",                    send_trait;
    SizedTraitLangItem,              "sized",                   sized_trait;
    UnsizeTraitLangItem,             "unsize",                  unsize_trait;
    CopyTraitLangItem,               "copy",                    copy_trait;
    CloneTraitLangItem,              "clone",                   clone_trait;
    SyncTraitLangItem,               "sync",                    sync_trait;
    FreezeTraitLangItem,             "freeze",                  freeze_trait;

    DropTraitLangItem,               "drop",                    drop_trait;

    CoerceUnsizedTraitLangItem,      "coerce_unsized",          coerce_unsized_trait;

    AddTraitLangItem,                "add",                     add_trait;
    SubTraitLangItem,                "sub",                     sub_trait;
    MulTraitLangItem,                "mul",                     mul_trait;
    DivTraitLangItem,                "div",                     div_trait;
    RemTraitLangItem,                "rem",                     rem_trait;
    NegTraitLangItem,                "neg",                     neg_trait;
    NotTraitLangItem,                "not",                     not_trait;
    BitXorTraitLangItem,             "bitxor",                  bitxor_trait;
    BitAndTraitLangItem,             "bitand",                  bitand_trait;
    BitOrTraitLangItem,              "bitor",                   bitor_trait;
    ShlTraitLangItem,                "shl",                     shl_trait;
    ShrTraitLangItem,                "shr",                     shr_trait;
    AddAssignTraitLangItem,          "add_assign",              add_assign_trait;
    SubAssignTraitLangItem,          "sub_assign",              sub_assign_trait;
    MulAssignTraitLangItem,          "mul_assign",              mul_assign_trait;
    DivAssignTraitLangItem,          "div_assign",              div_assign_trait;
    RemAssignTraitLangItem,          "rem_assign",              rem_assign_trait;
    BitXorAssignTraitLangItem,       "bitxor_assign",           bitxor_assign_trait;
    BitAndAssignTraitLangItem,       "bitand_assign",           bitand_assign_trait;
    BitOrAssignTraitLangItem,        "bitor_assign",            bitor_assign_trait;
    ShlAssignTraitLangItem,          "shl_assign",              shl_assign_trait;
    ShrAssignTraitLangItem,          "shr_assign",              shr_assign_trait;
    IndexTraitLangItem,              "index",                   index_trait;
    IndexMutTraitLangItem,           "index_mut",               index_mut_trait;

    UnsafeCellTypeLangItem,          "unsafe_cell",             unsafe_cell_type;

    DerefTraitLangItem,              "deref",                   deref_trait;
    DerefMutTraitLangItem,           "deref_mut",               deref_mut_trait;

    FnTraitLangItem,                 "fn",                      fn_trait;
    FnMutTraitLangItem,              "fn_mut",                  fn_mut_trait;
    FnOnceTraitLangItem,             "fn_once",                 fn_once_trait;

    GeneratorStateLangItem,          "generator_state",         gen_state;
    GeneratorTraitLangItem,          "generator",               gen_trait;

    EqTraitLangItem,                 "eq",                      eq_trait;
    OrdTraitLangItem,                "ord",                     ord_trait;

    StrEqFnLangItem,                 "str_eq",                  str_eq_fn;

    // A number of panic-related lang items. The `panic` item corresponds to
    // divide-by-zero and various panic cases with `match`. The
    // `panic_bounds_check` item is for indexing arrays.
    //
    // The `begin_unwind` lang item has a predefined symbol name and is sort of
    // a "weak lang item" in the sense that a crate is not required to have it
    // defined to use it, but a final product is required to define it
    // somewhere. Additionally, there are restrictions on crates that use a weak
    // lang item, but do not have it defined.
    PanicFnLangItem,                 "panic",                   panic_fn;
    PanicBoundsCheckFnLangItem,      "panic_bounds_check",      panic_bounds_check_fn;
    PanicFmtLangItem,                "panic_fmt",               panic_fmt;

    ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
    BoxFreeFnLangItem,               "box_free",                box_free_fn;
    DropInPlaceFnLangItem,             "drop_in_place",           drop_in_place_fn;

    StartFnLangItem,                 "start",                   start_fn;

    EhPersonalityLangItem,           "eh_personality",          eh_personality;
    EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
    MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;

    OwnedBoxLangItem,                "owned_box",               owned_box;

    PhantomDataItem,                 "phantom_data",            phantom_data;

    NonZeroItem,                     "non_zero",                non_zero;

    DebugTraitLangItem,              "debug_trait",             debug_trait;
}

impl<'a, 'tcx, 'gcx> ty::TyCtxt<'a, 'tcx, 'gcx> {
    pub fn require_lang_item(&self, lang_item: LangItem) -> DefId {
        self.lang_items().require(lang_item).unwrap_or_else(|msg| {
            self.sess.fatal(&msg)
        })
    }
}
<|endoftext|>


<commit_before><commit_msg>Repair constants<commit_after><|endoftext|>


<commit_before><commit_msg>Implement Eq for Hex<commit_after><|endoftext|>


<commit_before>use std::env;
use std::fmt;
use std::fs::{self, PathExt};
use std::io::Read;
use std::path::{Path, PathBuf};
use std::process;
use std::str::FromStr;
use std::sync::atomic;

use csv;

use Csv;

static XSV_INTEGRATION_TEST_DIR: &'static str = "xit";

static NEXT_ID: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;

pub struct Workdir {
    root: PathBuf,
    dir: PathBuf,
    flexible: bool,
}

impl Workdir {
    pub fn new(name: &str) -> Workdir {
        let id = NEXT_ID.fetch_add(1, atomic::Ordering::SeqCst);
        let root = env::current_exe().unwrap()
                       .parent()
                       .expect("executable's directory")
                       .to_path_buf();
        let dir = root.join(XSV_INTEGRATION_TEST_DIR)
                      .join(name)
                      .join(&format!("test-{}", id));
        if fs::metadata(&dir).map(|md| md.is_dir()).unwrap_or(false) {
            if let Err(err) = fs::remove_dir_all(&dir) {
                panic!("{}", err);
            }
        }
        // Explicitly ignoring an error here seems wrong, but for whatever
        // reason, this appears to fail non-deterministically in Travis because
        // the "path already exists." Does that mean `NEXT_ID` isn't really
        // atomic? Really? Very strange and baffling. ---AG
        let _ = fs::create_dir_all(&dir);
        Workdir { root: root, dir: dir, flexible: false }
    }

    pub fn flexible(mut self, yes: bool) -> Workdir {
        self.flexible = yes;
        self
    }

    pub fn create<T: Csv>(&self, name: &str, rows: T) {
        let mut wtr = match csv::Writer::from_file(&self.path(name)) {
            Ok(wtr) => wtr.flexible(self.flexible),
            Err(err) => panic!("Could not open '{:?}': {}",
                                self.path(name), err),
        };
        for row in rows.to_vecs().into_iter() {
            wtr.write(row.iter()).unwrap();
        }
        wtr.flush().unwrap();
    }

    pub fn create_indexed<T: Csv>(&self, name: &str, rows: T) {
        self.create(name, rows);

        let mut cmd = self.command("index");
        cmd.arg(name);
        self.run(&mut cmd);
    }

    pub fn read_stdout<T: Csv>(&self, cmd: &mut process::Command) -> T {
        let mut rdr = csv::Reader::from_string(self.stdout::<String>(cmd))
                                  .has_headers(false);
        Csv::from_vecs(rdr.records().collect::<Result<_, _>>().unwrap())
    }

    pub fn command(&self, sub_command: &str) -> process::Command {
        let mut cmd = process::Command::new(&self.xsv_bin());
        cmd.current_dir(&self.dir).arg(sub_command);
        cmd
    }

    pub fn output(&self, cmd: &mut process::Command) -> process::Output {
        debug!("[{}]: {:?}", self.dir.display(), cmd);
        let o = cmd.output().unwrap();
        if !o.status.success() {
            panic!("\n\n===== {:?} =====\n\
                    command failed but expected success!\
                    \n\ncwd: {}\
                    \n\nstatus: {}\
                    \n\nstdout: {}\n\nstderr: {}\
                    \n\n=====\n",
                   cmd, self.dir.display(), o.status,
                   String::from_utf8_lossy(&o.stdout),
                   String::from_utf8_lossy(&o.stderr))
        }
        o
    }

    pub fn run(&self, cmd: &mut process::Command) {
        self.output(cmd);
    }

    pub fn stdout<T: FromStr>(&self, cmd: &mut process::Command) -> T {
        let o = self.output(cmd);
        let stdout = String::from_utf8_lossy(&o.stdout);
        stdout.trim().parse().ok().expect(
            &format!("Could not convert from string: '{}'", stdout))
    }

    pub fn assert_err(&self, cmd: &mut process::Command) {
        let o = cmd.output().unwrap();
        if o.status.success() {
            panic!("\n\n===== {:?} =====\n\
                    command succeeded but expected failure!\
                    \n\ncwd: {}\
                    \n\nstatus: {}\
                    \n\nstdout: {}\n\nstderr: {}\
                    \n\n=====\n",
                   cmd, self.dir.display(), o.status,
                   String::from_utf8_lossy(&o.stdout),
                   String::from_utf8_lossy(&o.stderr));
        }
    }

    pub fn from_str<T: FromStr>(&self, name: &Path) -> T {
        let mut o = String::new();
        fs::File::open(name).unwrap().read_to_string(&mut o).unwrap();
        o.parse().ok().expect("fromstr")
    }

    pub fn path(&self, name: &str) -> PathBuf {
        self.dir.join(name)
    }

    pub fn xsv_bin(&self) -> PathBuf {
        self.root.join("xsv")
    }
}

impl fmt::Debug for Workdir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "path={}", self.dir.display())
    }
}
<commit_msg>More debugging.<commit_after>use std::env;
use std::fmt;
use std::fs::{self, PathExt};
use std::io::Read;
use std::path::{Path, PathBuf};
use std::process;
use std::str::FromStr;
use std::sync::atomic;

use csv;

use Csv;

static XSV_INTEGRATION_TEST_DIR: &'static str = "xit";

static NEXT_ID: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;

pub struct Workdir {
    root: PathBuf,
    dir: PathBuf,
    flexible: bool,
}

impl Workdir {
    pub fn new(name: &str) -> Workdir {
        let id = NEXT_ID.fetch_add(1, atomic::Ordering::SeqCst);
        let root = env::current_exe().unwrap()
                       .parent()
                       .expect("executable's directory")
                       .to_path_buf();
        let dir = root.join(XSV_INTEGRATION_TEST_DIR)
                      .join(name)
                      .join(&format!("test-{}", id));
        if fs::metadata(&dir).map(|md| md.is_dir()).unwrap_or(false) {
            if let Err(err) = fs::remove_dir_all(&dir) {
                panic!("Could not remove '{:?}': {}", dir, err);
            }
        }
        // Explicitly ignoring an error here seems wrong, but for whatever
        // reason, this appears to fail non-deterministically in Travis because
        // the "path already exists." Does that mean `NEXT_ID` isn't really
        // atomic? Really? Very strange and baffling. ---AG
        if let Err(err) = fs::create_dir_all(&dir) {
            panic!("Could not create '{:?}': {}", dir, err);
        }
        Workdir { root: root, dir: dir, flexible: false }
    }

    pub fn flexible(mut self, yes: bool) -> Workdir {
        self.flexible = yes;
        self
    }

    pub fn create<T: Csv>(&self, name: &str, rows: T) {
        let mut wtr = match csv::Writer::from_file(&self.path(name)) {
            Ok(wtr) => wtr.flexible(self.flexible),
            Err(err) => panic!("Could not open '{:?}': {}",
                                self.path(name), err),
        };
        for row in rows.to_vecs().into_iter() {
            wtr.write(row.iter()).unwrap();
        }
        wtr.flush().unwrap();
    }

    pub fn create_indexed<T: Csv>(&self, name: &str, rows: T) {
        self.create(name, rows);

        let mut cmd = self.command("index");
        cmd.arg(name);
        self.run(&mut cmd);
    }

    pub fn read_stdout<T: Csv>(&self, cmd: &mut process::Command) -> T {
        let mut rdr = csv::Reader::from_string(self.stdout::<String>(cmd))
                                  .has_headers(false);
        Csv::from_vecs(rdr.records().collect::<Result<_, _>>().unwrap())
    }

    pub fn command(&self, sub_command: &str) -> process::Command {
        let mut cmd = process::Command::new(&self.xsv_bin());
        cmd.current_dir(&self.dir).arg(sub_command);
        cmd
    }

    pub fn output(&self, cmd: &mut process::Command) -> process::Output {
        debug!("[{}]: {:?}", self.dir.display(), cmd);
        let o = cmd.output().unwrap();
        if !o.status.success() {
            panic!("\n\n===== {:?} =====\n\
                    command failed but expected success!\
                    \n\ncwd: {}\
                    \n\nstatus: {}\
                    \n\nstdout: {}\n\nstderr: {}\
                    \n\n=====\n",
                   cmd, self.dir.display(), o.status,
                   String::from_utf8_lossy(&o.stdout),
                   String::from_utf8_lossy(&o.stderr))
        }
        o
    }

    pub fn run(&self, cmd: &mut process::Command) {
        self.output(cmd);
    }

    pub fn stdout<T: FromStr>(&self, cmd: &mut process::Command) -> T {
        let o = self.output(cmd);
        let stdout = String::from_utf8_lossy(&o.stdout);
        stdout.trim().parse().ok().expect(
            &format!("Could not convert from string: '{}'", stdout))
    }

    pub fn assert_err(&self, cmd: &mut process::Command) {
        let o = cmd.output().unwrap();
        if o.status.success() {
            panic!("\n\n===== {:?} =====\n\
                    command succeeded but expected failure!\
                    \n\ncwd: {}\
                    \n\nstatus: {}\
                    \n\nstdout: {}\n\nstderr: {}\
                    \n\n=====\n",
                   cmd, self.dir.display(), o.status,
                   String::from_utf8_lossy(&o.stdout),
                   String::from_utf8_lossy(&o.stderr));
        }
    }

    pub fn from_str<T: FromStr>(&self, name: &Path) -> T {
        let mut o = String::new();
        fs::File::open(name).unwrap().read_to_string(&mut o).unwrap();
        o.parse().ok().expect("fromstr")
    }

    pub fn path(&self, name: &str) -> PathBuf {
        self.dir.join(name)
    }

    pub fn xsv_bin(&self) -> PathBuf {
        self.root.join("xsv")
    }
}

impl fmt::Debug for Workdir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "path={}", self.dir.display())
    }
}
<|endoftext|>


<commit_before><commit_msg>Get the DbPage data vector from MemoryMap<commit_after><|endoftext|>


<commit_before><commit_msg>Corrected test_client_cookies to be effective.<commit_after><|endoftext|>


<commit_before><commit_msg>Made default events public<commit_after><|endoftext|>


<commit_before><commit_msg>Upgraded to latest piston-window<commit_after><|endoftext|>


<commit_before><commit_msg>Added support for deps install<commit_after><|endoftext|>


<commit_before><commit_msg>Small reogranization. Group type definitions with their impls.<commit_after><|endoftext|>


<commit_before><commit_msg>Add placeholder library source<commit_after>mod test {
	#[test]
	fn test() {}
}
<|endoftext|>


<commit_before><commit_msg>fix npc name width<commit_after><|endoftext|>


<commit_before>//! Agent policy module.
//!
//! This module contains [fixed](fixed/index.html) and
//! [parameterised](parameterised/index.html) policies for reinforcement
//! learning control problems. A policy is considered to be either deterministic
//! or stochastic, for which we have the following definitions, respectively: 1)
//! _π(X) -> U_; 2) _π(X, U) -> R_, or equivalently, _π(x) -> Ω(U)_;
//!
//! where _X_ and _U_ are the state and action spaces, respectively; _R_ is the
//! set of real values; and _Ω(U)_ is the set of probability measures on the
//! action set _U_. In general, deterministic policies may be considered a
//! special case of stochastic policies in which all probability mass
//! is placed on a single action _u'_ for any given state _x_. For continuous
//! policies, this can be seen as a dirac delta distribution, _δ(u' - u)_.
use crate::{core::*, domains::Transition, fa::Parameterised};
use rand::{seq::SliceRandom, thread_rng, Rng};

#[allow(dead_code)]
#[inline]
pub(self) fn sample_probs(probabilities: &[f64]) -> usize {
    sample_probs_with_rng(&mut thread_rng(), probabilities)
}

#[inline]
pub(self) fn sample_probs_with_rng(rng: &mut impl Rng, probabilities: &[f64]) -> usize {
    let r = rng.gen::<f64>();

    match probabilities
        .into_iter()
        .scan(0.0, |state, &p| {
            *state = *state + p;

            Some(*state)
        })
        .position(|p| p > r)
    {
        Some(index) => index,
        None => probabilities.len() - 1,
    }
}

/// Policy trait for functions that define a probability distribution over
/// actions.
pub trait Policy<S>: Algorithm {
    type Action;

    /// Sample the (possibly stochastic) policy distribution for a given input.
    fn sample(&mut self, input: &S) -> Self::Action { self.mpa(input) }

    /// Return the "most probable action" according to the policy distribution,
    /// if well-defined.
    fn mpa(&mut self, _: &S) -> Self::Action { unimplemented!() }

    /// Return the probability of selecting an action for a given input.
    fn probability(&mut self, input: &S, a: Self::Action) -> f64;
}

/// Trait for policies that are defined on a finite action space.
pub trait FinitePolicy<S>: Policy<S, Action = usize> {
    fn n_actions(&self) -> usize;

    /// Return the probability of selecting each action for a given input.
    fn probabilities(&mut self, input: &S) -> Vector<f64>;
}

/// Trait for policies that have a differentiable representation.
pub trait DifferentiablePolicy<S>: Policy<S> {
    /// Compute the derivative of the log probability for a single action.
    fn grad_log(&self, input: &S, a: Self::Action) -> Matrix<f64>;
}

/// Trait for policies that are parameterised by a vector of weights.
pub trait ParameterisedPolicy<S>: Policy<S> + Parameterised {
    /// Update the weights in the direction of an error for a given state and
    /// action.
    fn update(&mut self, input: &S, a: Self::Action, error: f64);

    /// Update the weights directly using an update matrix.
    fn update_raw(&mut self, errors: Matrix<f64>);
}

pub mod fixed;
pub mod parameterised;

import_all!(perturbation);
<commit_msg>feat(core): implement Policy types for Shared<T><commit_after>//! Agent policy module.
//!
//! This module contains [fixed](fixed/index.html) and
//! [parameterised](parameterised/index.html) policies for reinforcement
//! learning control problems. A policy is considered to be either deterministic
//! or stochastic, for which we have the following definitions, respectively: 1)
//! _π(X) -> U_; 2) _π(X, U) -> R_, or equivalently, _π(x) -> Ω(U)_;
//!
//! where _X_ and _U_ are the state and action spaces, respectively; _R_ is the
//! set of real values; and _Ω(U)_ is the set of probability measures on the
//! action set _U_. In general, deterministic policies may be considered a
//! special case of stochastic policies in which all probability mass
//! is placed on a single action _u'_ for any given state _x_. For continuous
//! policies, this can be seen as a dirac delta distribution, _δ(u' - u)_.
use crate::{core::*, domains::Transition, fa::Parameterised};
use rand::{seq::SliceRandom, thread_rng, Rng};

#[allow(dead_code)]
#[inline]
pub(self) fn sample_probs(probabilities: &[f64]) -> usize {
    sample_probs_with_rng(&mut thread_rng(), probabilities)
}

#[inline]
pub(self) fn sample_probs_with_rng(rng: &mut impl Rng, probabilities: &[f64]) -> usize {
    let r = rng.gen::<f64>();

    match probabilities
        .into_iter()
        .scan(0.0, |state, &p| {
            *state = *state + p;

            Some(*state)
        })
        .position(|p| p > r)
    {
        Some(index) => index,
        None => probabilities.len() - 1,
    }
}

/// Policy trait for functions that define a probability distribution over
/// actions.
pub trait Policy<S>: Algorithm {
    type Action;

    /// Sample the (possibly stochastic) policy distribution for a given input.
    fn sample(&mut self, input: &S) -> Self::Action { self.mpa(input) }

    /// Return the "most probable action" according to the policy distribution,
    /// if well-defined.
    fn mpa(&mut self, _: &S) -> Self::Action { unimplemented!() }

    /// Return the probability of selecting an action for a given input.
    fn probability(&mut self, input: &S, a: Self::Action) -> f64;
}

/// Trait for policies that are defined on a finite action space.
pub trait FinitePolicy<S>: Policy<S, Action = usize> {
    fn n_actions(&self) -> usize;

    /// Return the probability of selecting each action for a given input.
    fn probabilities(&mut self, input: &S) -> Vector<f64>;
}

/// Trait for policies that have a differentiable representation.
pub trait DifferentiablePolicy<S>: Policy<S> {
    /// Compute the derivative of the log probability for a single action.
    fn grad_log(&self, input: &S, a: Self::Action) -> Matrix<f64>;
}

/// Trait for policies that are parameterised by a vector of weights.
pub trait ParameterisedPolicy<S>: Policy<S> + Parameterised {
    /// Update the weights in the direction of an error for a given state and
    /// action.
    fn update(&mut self, input: &S, a: Self::Action, error: f64);

    /// Update the weights directly using an update matrix.
    fn update_raw(&mut self, errors: Matrix<f64>);
}

pub mod fixed;
pub mod parameterised;

import_all!(perturbation);

// Shared<T> impls:
impl<S, T: Policy<S>> Policy<S> for Shared<T> {
    type Action = T::Action;

    fn sample(&mut self, input: &S) -> Self::Action {
        self.borrow_mut().sample(input)
    }

    fn mpa(&mut self, s: &S) -> Self::Action {
        self.borrow_mut().mpa(s)
    }

    fn probability(&mut self, input: &S, a: Self::Action) -> f64 {
        self.borrow_mut().probability(input, a)
    }
}

impl<S, T: FinitePolicy<S>> FinitePolicy<S> for Shared<T> {
    fn n_actions(&self) -> usize {
        self.borrow().n_actions()
    }

    fn probabilities(&mut self, input: &S) -> Vector<f64> {
        self.borrow_mut().probabilities(input)
    }
}

impl<S, T: DifferentiablePolicy<S>> DifferentiablePolicy<S> for Shared<T> {
    fn grad_log(&self, input: &S, a: Self::Action) -> Matrix<f64> {
        self.borrow().grad_log(input, a)
    }
}

impl<S, T: ParameterisedPolicy<S>> ParameterisedPolicy<S> for Shared<T> {
    fn update(&mut self, input: &S, a: Self::Action, error: f64) {
        self.borrow_mut().update(input, a, error)
    }

    fn update_raw(&mut self, errors: Matrix<f64>) {
        self.borrow_mut().update_raw(errors)
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix Issues<commit_after><|endoftext|>


<commit_before><commit_msg>av sync checking<commit_after>extern crate flv_toolbox_rs;

use flv_toolbox_rs::lib::{ FLVTagRead, FLVTag, FLVTagType, FLVTagWrite, format_seconds_ms };

use std::fs::File;
use std::io::Read;
use std::slice;
use std::collections::BTreeMap;

#[derive(Debug, Clone)]
pub struct FlvTimeInfo {
    pub ref_video_frame_duration: u64,
    pub ref_audio_frame_duration: u64,
    pub real_video_frame_duration: i64,
    pub real_audio_frame_duration: i64,
    pub timestamps: Vec<TagTimestamp>,
}

#[derive(Debug, Clone)]
pub enum TagTimestamp {
    Video(i64, i64),
    Audio(i64, i64),
}

fn get_info(path: &str) -> FlvTimeInfo {

    let mut file = File::open(path).unwrap();
    let file_info = file.metadata().unwrap();
    let file_len = file_info.len();
    let mut parser = FLVTagRead::new(&mut file);

    let mut ref_video_frame_duration: u64 = 0;
    let mut ref_audio_frame_duration: u64 = 0;
    let mut real_video_frame_duration: i64 = 0;
    let mut real_audio_frame_duration: i64 = 0;

    let mut last_video_tag: Option<FLVTag> = None;
    let mut video_duration_map: BTreeMap<i64, u64> = BTreeMap::new();

    let mut last_audio_tag: Option<FLVTag> = None;
    let mut audio_duration_map: BTreeMap<i64, u64> = BTreeMap::new();

    let mut timestamps: Vec<TagTimestamp> = vec![];

    loop {
        let position = parser.get_position();
        print!("progress: {: >3.0}%\r", position as f64 / file_len as f64 * 100.);
        let nxt: Option<FLVTag> = parser.next();
        if nxt.is_none() {
            break;
        }
        let tag: FLVTag = nxt.unwrap();

        match tag.get_tag_type() {
            FLVTagType::TAG_TYPE_VIDEO => {

                let mut time_delta = 0;
                if last_video_tag.is_some() {
                    time_delta = tag.get_timestamp() as i64 - last_video_tag.as_ref().unwrap().get_timestamp() as i64;
                    *(video_duration_map.entry(time_delta).or_insert(0)) += 1;
                }

                match tag.get_frame_type() {
                    1 => {
                        match tag.get_avc_packet_type() {
                            0 => { // AVC_PACKET_TYPE_SEQUENCE_HEADER

                            },
                            _ => { // normal keyframes
                                timestamps.push(TagTimestamp::Video(tag.get_timestamp() as i64, time_delta));
                                last_video_tag = Some(tag);
                            }
                        };
                    }
                    _ => { // normal frames
                        timestamps.push(TagTimestamp::Video(tag.get_timestamp() as i64, time_delta));
                        last_video_tag = Some(tag);
                    }
                };
            },
            FLVTagType::TAG_TYPE_AUDIO => {

                let mut time_delta = 0;
                if last_audio_tag.is_some() {
                    time_delta = tag.get_timestamp() as i64 - last_audio_tag.as_ref().unwrap().get_timestamp() as i64;
                    *(audio_duration_map.entry(time_delta).or_insert(0)) += 1;
                }

                if tag.is_acc_sequence_header() { // acc sequence header

                } else { // normal frames
                    timestamps.push(TagTimestamp::Audio(tag.get_timestamp() as i64, time_delta));
                    last_audio_tag = Some(tag);
                }
            },
            FLVTagType::TAG_TYPE_SCRIPTDATAOBJECT => {

            }
        };
    }
    println!("complete!\r");

    real_video_frame_duration = top_duration(&video_duration_map);
    real_audio_frame_duration = top_duration(&audio_duration_map);

    return FlvTimeInfo {
        ref_video_frame_duration  ,
        ref_audio_frame_duration  ,
        real_video_frame_duration ,
        real_audio_frame_duration ,
        timestamps                ,
    };
}

fn top_duration(pairs: &BTreeMap<i64, u64>) -> i64 {
    let mut list: Vec<(&i64, &u64)> = pairs.iter().collect();
    match list.len() {
        0 => 0,
        1 => *(list[0].0),
        _ => {
            list.as_mut_slice().sort_by_key(|&(_, &count)| count );
            *(list.last().unwrap().0)
        },
    }
}

fn check_offset(info: &FlvTimeInfo) {
    let &FlvTimeInfo {
        ref ref_video_frame_duration  ,
        ref ref_audio_frame_duration  ,
        ref real_video_frame_duration ,
        ref real_audio_frame_duration ,
        ref timestamps                ,
    } = info;

    let mut video_time: i64 = 0;
    let mut audio_time: i64 = 0;

    for tm in timestamps.iter() {
        let mut changed = false;
        let mut current_time = 0;
        match tm {
            &TagTimestamp::Video(ref time, ref duration) => {
                current_time = *time;
                if (*duration - *real_video_frame_duration).abs() > 1 {
                    // println!("v offset {}", video_time - *time);
                    changed = true;
                    video_time += *real_video_frame_duration;
                } else {
                    video_time += *duration;
                }
            }
            &TagTimestamp::Audio(ref time, ref duration) => {
                current_time = *time;
                if (*duration - *real_audio_frame_duration).abs() > 1 {
                    // println!("a offset {}", audio_time - *time);
                    changed = true;
                    audio_time += *real_audio_frame_duration;
                } else {
                    audio_time += *duration;
                }
            }
        };
        if changed {
            println!("{}: av offset: {}", format_seconds_ms(current_time as u64), audio_time - video_time);
        }
    }
}

fn main() {
    let path = std::env::args().nth(1).unwrap();
    println!("checking flv: {}", path);
    let info = get_info(&path);
    // println!("{:?}", info);
    check_offset(&info);
}<|endoftext|>


<commit_before><commit_msg>Fix skiplist out of bounds<commit_after><|endoftext|>


<commit_before><commit_msg>Do not use version crate in build script<commit_after><|endoftext|>


<commit_before><commit_msg>Tune down route match logs.<commit_after><|endoftext|>


<commit_before>// TODO: Doc the rest

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

use super::paging::{Page, PAGE_END};

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

use system::error::{Result, Error, ENOMEM};

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

impl<T> Memory<T> {
    /// Allocate memory
    pub fn new(length: usize) -> Result<Self> {
        let alloc = unsafe { alloc(length * mem::size_of::<T>()) };
        if alloc > 0 {
            Ok(Memory {
                ptr: alloc as *mut T,
                length: length,
            })
        } else {
            Err(Error::new(ENOMEM))
        }
    }

    /// Allocate memory, aligned
    pub fn new_aligned(length: usize, align: usize) -> Result<Self> {
        let alloc = unsafe { alloc_aligned(length * mem::size_of::<T>(), align) };
        if alloc > 0 {
            Ok(Memory {
                ptr: alloc as *mut T,
                length: length,
            })
        } else {
            Err(Error::new(ENOMEM))
        }
    }

    /// Reallocate the memory
    pub fn renew(mut self, length: usize) -> Result<Self> {
        let alloc = unsafe { realloc(self.ptr as usize, length * mem::size_of::<T>()) };
        self.ptr = 0 as *mut T;
        if alloc > 0 {
            Ok(Memory {
                ptr: alloc as *mut T,
                length: length,
            })
        } else {
            Err(Error::new(ENOMEM))
        }
    }

    /// Reallocate the memory, aligned
    pub fn renew_aligned(mut self, length: usize, align: usize) -> Result<Self> {
        let alloc = unsafe { realloc_aligned(self.ptr as usize, length * mem::size_of::<T>(), align) };
        self.ptr = 0 as *mut T;
        if alloc > 0 {
            Ok(Memory {
                ptr: alloc as *mut T,
                length: length,
            })
        } else {
            Err(Error::new(ENOMEM))
        }
    }

    /// Get the length in T elements
    pub fn len(&self) -> usize {
        self.length
    }

    #[inline(always)]
    fn check_index(&self, i: usize) {
        if i >= self.length {
            panic!("Memory: {} >= {}", i, self.length);
        }
    }

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

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

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

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

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

    /// Borrow as a slice
    pub fn as_slice(&self) -> &[T] {
        unsafe { slice::from_raw_parts(self.ptr, self.length) }
    }

    /// Borrow as a mutable slice
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        unsafe { slice::from_raw_parts_mut(self.ptr, self.length) }
    }

    /// Borrow as a raw pointer
    pub unsafe fn as_ptr(&self) -> *const T {
        self.ptr as *const T
    }

    /// Borrow as a mutable raw pointer
    pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
        self.ptr as *mut T
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

/// Allocate memory
pub unsafe fn alloc(size: usize) -> usize {
    alloc_aligned(size, 1)
}

/// Allocate memory, aligned
pub unsafe fn alloc_aligned(size: usize, align: usize) -> usize {
    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 && (count > 0 || cluster_to_address(i) % align == 0) {
                if count == 0 {
                    number = i;
                }

                count += 1;

                if count * CLUSTER_SIZE >= size {
                    break;
                }
            } else {
                count = 0;
            }
        }

        if count * CLUSTER_SIZE >= size {
            let address = cluster_to_address(number);

            for i in number..number + count {
                set_cluster(i, address);

                let cluster_address = cluster_to_address(i);

                let mut page = Page::new(cluster_address);
                let old = page.entry_data();
                page.map_kernel_write(address);

                ::memset(cluster_address as *mut u8, 0, CLUSTER_SIZE);

                page.set_entry_data(old);
                page.flush();
            }

            return address;
        }
    }

    0
}

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

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

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

    size
}

pub unsafe fn unalloc(ptr: usize) {
    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            } else {
                break;
            }
        }
    }
}

pub unsafe fn unalloc_type<T>(ptr: *mut T) {
    unalloc(ptr as usize);
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    realloc_aligned(ptr, size, 1)
}

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

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

                    let read_cluster = address_to_cluster(ptr);
                    let write_cluster = address_to_cluster(ret);

                    for i in 0..(copy_size + CLUSTER_SIZE - 1)/CLUSTER_SIZE {
                        let read_address = cluster_to_address(read_cluster + i);
                        let write_address = cluster_to_address(write_cluster + i);

                        let mut read_page = Page::new(read_address);
                        let read_old = read_page.entry_data();
                        read_page.map_kernel_read(read_address);

                        let mut write_page = Page::new(write_address);
                        let write_old = write_page.entry_data();
                        write_page.map_kernel_write(write_address);

                        ::memmove(write_address as *mut u8, read_address as *const u8, CLUSTER_SIZE);

                        write_page.set_entry_data(write_old);
                        write_page.flush();

                        read_page.set_entry_data(read_old);
                        read_page.flush();
                    }
                }
                unalloc(ptr);
            }
        }
    }

    ret
}

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

pub fn memory_used() -> usize {
    let mut ret = 0;

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

    ret
}

pub fn memory_free() -> usize {
    let mut ret = 0;

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

    ret
}
<commit_msg>Fix mapping issue in alloc<commit_after>// TODO: Doc the rest

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

use super::paging::{Page, PAGE_END};

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

use system::error::{Result, Error, ENOMEM};

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

impl<T> Memory<T> {
    /// Allocate memory
    pub fn new(length: usize) -> Result<Self> {
        let alloc = unsafe { alloc(length * mem::size_of::<T>()) };
        if alloc > 0 {
            Ok(Memory {
                ptr: alloc as *mut T,
                length: length,
            })
        } else {
            Err(Error::new(ENOMEM))
        }
    }

    /// Allocate memory, aligned
    pub fn new_aligned(length: usize, align: usize) -> Result<Self> {
        let alloc = unsafe { alloc_aligned(length * mem::size_of::<T>(), align) };
        if alloc > 0 {
            Ok(Memory {
                ptr: alloc as *mut T,
                length: length,
            })
        } else {
            Err(Error::new(ENOMEM))
        }
    }

    /// Reallocate the memory
    pub fn renew(mut self, length: usize) -> Result<Self> {
        let alloc = unsafe { realloc(self.ptr as usize, length * mem::size_of::<T>()) };
        self.ptr = 0 as *mut T;
        if alloc > 0 {
            Ok(Memory {
                ptr: alloc as *mut T,
                length: length,
            })
        } else {
            Err(Error::new(ENOMEM))
        }
    }

    /// Reallocate the memory, aligned
    pub fn renew_aligned(mut self, length: usize, align: usize) -> Result<Self> {
        let alloc = unsafe { realloc_aligned(self.ptr as usize, length * mem::size_of::<T>(), align) };
        self.ptr = 0 as *mut T;
        if alloc > 0 {
            Ok(Memory {
                ptr: alloc as *mut T,
                length: length,
            })
        } else {
            Err(Error::new(ENOMEM))
        }
    }

    /// Get the length in T elements
    pub fn len(&self) -> usize {
        self.length
    }

    #[inline(always)]
    fn check_index(&self, i: usize) {
        if i >= self.length {
            panic!("Memory: {} >= {}", i, self.length);
        }
    }

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

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

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

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

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

    /// Borrow as a slice
    pub fn as_slice(&self) -> &[T] {
        unsafe { slice::from_raw_parts(self.ptr, self.length) }
    }

    /// Borrow as a mutable slice
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        unsafe { slice::from_raw_parts_mut(self.ptr, self.length) }
    }

    /// Borrow as a raw pointer
    pub unsafe fn as_ptr(&self) -> *const T {
        self.ptr as *const T
    }

    /// Borrow as a mutable raw pointer
    pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
        self.ptr as *mut T
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

/// Allocate memory
pub unsafe fn alloc(size: usize) -> usize {
    alloc_aligned(size, 1)
}

/// Allocate memory, aligned
pub unsafe fn alloc_aligned(size: usize, align: usize) -> usize {
    if size > 0 {
        let mut number = 0;
        let mut count = 0;

        for i in 0..CLUSTER_COUNT {
            if cluster(i) == 0 && (count > 0 || cluster_to_address(i) % align == 0) {
                if count == 0 {
                    number = i;
                }

                count += 1;

                if count * CLUSTER_SIZE >= size {
                    break;
                }
            } else {
                count = 0;
            }
        }

        if count * CLUSTER_SIZE >= size {
            let address = cluster_to_address(number);

            for i in number..number + count {
                set_cluster(i, address);

                let cluster_address = cluster_to_address(i);

                let mut page = Page::new(cluster_address);
                let old = page.entry_data();
                page.map_kernel_write(cluster_address);

                ::memset(cluster_address as *mut u8, 0, CLUSTER_SIZE);

                page.set_entry_data(old);
                page.flush();
            }

            return address;
        }
    }

    0
}

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

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

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

    size
}

pub unsafe fn unalloc(ptr: usize) {
    if ptr > 0 {
        for i in address_to_cluster(ptr)..CLUSTER_COUNT {
            if cluster(i) == ptr {
                set_cluster(i, 0);
            } else {
                break;
            }
        }
    }
}

pub unsafe fn unalloc_type<T>(ptr: *mut T) {
    unalloc(ptr as usize);
}

pub unsafe fn realloc(ptr: usize, size: usize) -> usize {
    realloc_aligned(ptr, size, 1)
}

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

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

                    let read_cluster = address_to_cluster(ptr);
                    let write_cluster = address_to_cluster(ret);

                    for i in 0..(copy_size + CLUSTER_SIZE - 1)/CLUSTER_SIZE {
                        let read_address = cluster_to_address(read_cluster + i);
                        let write_address = cluster_to_address(write_cluster + i);

                        let mut read_page = Page::new(read_address);
                        let read_old = read_page.entry_data();
                        read_page.map_kernel_read(read_address);

                        let mut write_page = Page::new(write_address);
                        let write_old = write_page.entry_data();
                        write_page.map_kernel_write(write_address);

                        ::memmove(write_address as *mut u8, read_address as *const u8, CLUSTER_SIZE);

                        write_page.set_entry_data(write_old);
                        write_page.flush();

                        read_page.set_entry_data(read_old);
                        read_page.flush();
                    }
                }
                unalloc(ptr);
            }
        }
    }

    ret
}

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

pub fn memory_used() -> usize {
    let mut ret = 0;

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

    ret
}

pub fn memory_free() -> usize {
    let mut ret = 0;

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

    ret
}
<|endoftext|>