<commit_before>//! This module contains the `EvalContext` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.

use std::cell::Ref;

use rustc::hir::def_id::DefId;
use rustc::hir;
use rustc::mir::visit::{Visitor, LvalueContext};
use rustc::mir;
use rustc::ty::layout::Layout;
use rustc::ty::{subst, self};

use error::{EvalResult, EvalError};
use eval_context::{EvalContext, StackPopCleanup, MirRef};
use lvalue::{Global, GlobalId, Lvalue};
use syntax::codemap::Span;

impl<'a, 'tcx> EvalContext<'a, 'tcx> {
    pub fn inc_step_counter_and_check_limit(&mut self, n: u64) -> EvalResult<'tcx, ()> {
        self.steps_remaining = self.steps_remaining.saturating_sub(n);
        if self.steps_remaining > 0 {
            Ok(())
        } else {
            Err(EvalError::ExecutionTimeLimitReached)
        }
    }

    /// Returns true as long as there are more things to do.
    pub fn step(&mut self) -> EvalResult<'tcx, bool> {
        self.memory.clear_packed();
        self.inc_step_counter_and_check_limit(1)?;
        if self.stack.is_empty() {
            return Ok(false);
        }

        let block = self.frame().block;
        let stmt_id = self.frame().stmt;
        let mir = self.mir();
        let basic_block = &mir.basic_blocks()[block];

        if let Some(stmt) = basic_block.statements.get(stmt_id) {
            let mut new = Ok(0);
            ConstantExtractor {
                span: stmt.source_info.span,
                substs: self.substs(),
                def_id: self.frame().def_id,
                ecx: self,
                mir: Ref::clone(&mir),
                new_constants: &mut new,
            }.visit_statement(block, stmt, mir::Location { block, statement_index: stmt_id });
            if new? == 0 {
                self.statement(stmt)?;
            }
            // if ConstantExtractor added new frames, we don't execute anything here
            // but await the next call to step
            return Ok(true);
        }

        let terminator = basic_block.terminator();
        let mut new = Ok(0);
        ConstantExtractor {
            span: terminator.source_info.span,
            substs: self.substs(),
            def_id: self.frame().def_id,
            ecx: self,
            mir: Ref::clone(&mir),
            new_constants: &mut new,
        }.visit_terminator(block, terminator, mir::Location { block, statement_index: stmt_id });
        if new? == 0 {
            self.terminator(terminator)?;
        }
        // if ConstantExtractor added new frames, we don't execute anything here
        // but await the next call to step
        Ok(true)
    }

    fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx, ()> {
        trace!("{:?}", stmt);

        use rustc::mir::StatementKind::*;
        match stmt.kind {
            Assign(ref lvalue, ref rvalue) => self.eval_rvalue_into_lvalue(rvalue, lvalue)?,

            SetDiscriminant { ref lvalue, variant_index } => {
                let dest = self.eval_lvalue(lvalue)?;
                let dest_ty = self.lvalue_ty(lvalue);
                let dest_layout = self.type_layout(dest_ty)?;

                match *dest_layout {
                    Layout::General { discr, ref variants, .. } => {
                        let discr_size = discr.size().bytes();
                        let discr_offset = variants[variant_index].offsets[0].bytes();

                        // FIXME(solson)
                        let dest = self.force_allocation(dest)?;
                        let discr_dest = (dest.to_ptr()).offset(discr_offset);

                        self.memory.write_uint(discr_dest, variant_index as u128, discr_size)?;
                    }

                    Layout::RawNullablePointer { nndiscr, .. } => {
                        use value::PrimVal;
                        if variant_index as u64 != nndiscr {
                            self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
                        }
                    }

                    _ => bug!("SetDiscriminant on {} represented as {:#?}", dest_ty, dest_layout),
                }
            }

            // Miri can safely ignore these. Only translation needs it.
            StorageLive(_) |
            StorageDead(_) => {}

            // Defined to do nothing. These are added by optimization passes, to avoid changing the
            // size of MIR constantly.
            Nop => {}
        }

        self.frame_mut().stmt += 1;
        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx, ()> {
        trace!("{:?}", terminator.kind);
        self.eval_terminator(terminator)?;
        if !self.stack.is_empty() {
            trace!("// {:?}", self.frame().block);
        }
        Ok(())
    }
}

// WARNING: make sure that any methods implemented on this type don't ever access ecx.stack
// this includes any method that might access the stack
// basically don't call anything other than `load_mir`, `alloc_ptr`, `push_stack_frame`
// The reason for this is, that `push_stack_frame` modifies the stack out of obvious reasons
struct ConstantExtractor<'a, 'b: 'a, 'tcx: 'b> {
    span: Span,
    ecx: &'a mut EvalContext<'b, 'tcx>,
    mir: MirRef<'tcx>,
    def_id: DefId,
    substs: &'tcx subst::Substs<'tcx>,
    new_constants: &'a mut EvalResult<'tcx, u64>,
}

impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> {
    fn global_item(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span, immutable: bool) {
        let cid = GlobalId { def_id, substs, promoted: None };
        if self.ecx.globals.contains_key(&cid) {
            return;
        }
        self.try(|this| {
            let mir = this.ecx.load_mir(def_id)?;
            this.ecx.globals.insert(cid, Global::uninitialized(mir.return_ty));
            let cleanup = if immutable && !mir.return_ty.type_contents(this.ecx.tcx).interior_unsafe() {
                StackPopCleanup::Freeze
            } else {
                StackPopCleanup::None
            };
            this.ecx.push_stack_frame(def_id, span, mir, substs, Lvalue::Global(cid), cleanup, Vec::new())
        });
    }
    fn try<F: FnOnce(&mut Self) -> EvalResult<'tcx, ()>>(&mut self, f: F) {
        if let Ok(ref mut n) = *self.new_constants {
            *n += 1;
        } else {
            return;
        }
        if let Err(e) = f(self) {
            *self.new_constants = Err(e);
        }
    }
}

impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> {
    fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: mir::Location) {
        self.super_constant(constant, location);
        match constant.literal {
            // already computed by rustc
            mir::Literal::Value { .. } => {}
            mir::Literal::Item { def_id, substs } => {
                if let ty::TyFnDef(..) = constant.ty.sty {
                    // No need to do anything here,
                    // because the type is the actual function, not the signature of the function.
                    // Thus we can simply create a zero sized allocation in `evaluate_operand`
                } else {
                    self.global_item(def_id, substs, constant.span, true);
                }
            },
            mir::Literal::Promoted { index } => {
                let cid = GlobalId {
                    def_id: self.def_id,
                    substs: self.substs,
                    promoted: Some(index),
                };
                if self.ecx.globals.contains_key(&cid) {
                    return;
                }
                let mir = Ref::clone(&self.mir);
                let mir = Ref::map(mir, |mir| &mir.promoted[index]);
                self.try(|this| {
                    let ty = this.ecx.monomorphize(mir.return_ty, this.substs);
                    this.ecx.globals.insert(cid, Global::uninitialized(ty));
                    this.ecx.push_stack_frame(this.def_id,
                                              constant.span,
                                              mir,
                                              this.substs,
                                              Lvalue::Global(cid),
                                              StackPopCleanup::Freeze,
                                              Vec::new())
                });
            }
        }
    }

    fn visit_lvalue(
        &mut self,
        lvalue: &mir::Lvalue<'tcx>,
        context: LvalueContext<'tcx>,
        location: mir::Location
    ) {
        self.super_lvalue(lvalue, context, location);
        if let mir::Lvalue::Static(def_id) = *lvalue {
            let substs = self.ecx.tcx.intern_substs(&[]);
            let span = self.span;
            if let Some(node_item) = self.ecx.tcx.map.get_if_local(def_id) {
                if let hir::map::Node::NodeItem(&hir::Item { ref node, .. }) = node_item {
                    if let hir::ItemStatic(_, m, _) = *node {
                        self.global_item(def_id, substs, span, m == hir::MutImmutable);
                        return;
                    } else {
                        bug!("static def id doesn't point to static");
                    }
                } else {
                    bug!("static def id doesn't point to item");
                }
            } else {
                let def = self.ecx.tcx.sess.cstore.describe_def(def_id).expect("static not found");
                if let hir::def::Def::Static(_, mutable) = def {
                    self.global_item(def_id, substs, span, !mutable);
                } else {
                    bug!("static found but isn't a static: {:?}", def);
                }
            }
        }
    }
}
<commit_msg>more documentation of unintuitive packed struct solution<commit_after>//! This module contains the `EvalContext` methods for executing a single step of the interpreter.
//!
//! The main entry point is the `step` method.

use std::cell::Ref;

use rustc::hir::def_id::DefId;
use rustc::hir;
use rustc::mir::visit::{Visitor, LvalueContext};
use rustc::mir;
use rustc::ty::layout::Layout;
use rustc::ty::{subst, self};

use error::{EvalResult, EvalError};
use eval_context::{EvalContext, StackPopCleanup, MirRef};
use lvalue::{Global, GlobalId, Lvalue};
use syntax::codemap::Span;

impl<'a, 'tcx> EvalContext<'a, 'tcx> {
    pub fn inc_step_counter_and_check_limit(&mut self, n: u64) -> EvalResult<'tcx, ()> {
        self.steps_remaining = self.steps_remaining.saturating_sub(n);
        if self.steps_remaining > 0 {
            Ok(())
        } else {
            Err(EvalError::ExecutionTimeLimitReached)
        }
    }

    /// Returns true as long as there are more things to do.
    pub fn step(&mut self) -> EvalResult<'tcx, bool> {
        // see docs on the `Memory::packed` field for why we do this
        self.memory.clear_packed();
        self.inc_step_counter_and_check_limit(1)?;
        if self.stack.is_empty() {
            return Ok(false);
        }

        let block = self.frame().block;
        let stmt_id = self.frame().stmt;
        let mir = self.mir();
        let basic_block = &mir.basic_blocks()[block];

        if let Some(stmt) = basic_block.statements.get(stmt_id) {
            let mut new = Ok(0);
            ConstantExtractor {
                span: stmt.source_info.span,
                substs: self.substs(),
                def_id: self.frame().def_id,
                ecx: self,
                mir: Ref::clone(&mir),
                new_constants: &mut new,
            }.visit_statement(block, stmt, mir::Location { block, statement_index: stmt_id });
            if new? == 0 {
                self.statement(stmt)?;
            }
            // if ConstantExtractor added new frames, we don't execute anything here
            // but await the next call to step
            return Ok(true);
        }

        let terminator = basic_block.terminator();
        let mut new = Ok(0);
        ConstantExtractor {
            span: terminator.source_info.span,
            substs: self.substs(),
            def_id: self.frame().def_id,
            ecx: self,
            mir: Ref::clone(&mir),
            new_constants: &mut new,
        }.visit_terminator(block, terminator, mir::Location { block, statement_index: stmt_id });
        if new? == 0 {
            self.terminator(terminator)?;
        }
        // if ConstantExtractor added new frames, we don't execute anything here
        // but await the next call to step
        Ok(true)
    }

    fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx, ()> {
        trace!("{:?}", stmt);

        use rustc::mir::StatementKind::*;
        match stmt.kind {
            Assign(ref lvalue, ref rvalue) => self.eval_rvalue_into_lvalue(rvalue, lvalue)?,

            SetDiscriminant { ref lvalue, variant_index } => {
                let dest = self.eval_lvalue(lvalue)?;
                let dest_ty = self.lvalue_ty(lvalue);
                let dest_layout = self.type_layout(dest_ty)?;

                match *dest_layout {
                    Layout::General { discr, ref variants, .. } => {
                        let discr_size = discr.size().bytes();
                        let discr_offset = variants[variant_index].offsets[0].bytes();

                        // FIXME(solson)
                        let dest = self.force_allocation(dest)?;
                        let discr_dest = (dest.to_ptr()).offset(discr_offset);

                        self.memory.write_uint(discr_dest, variant_index as u128, discr_size)?;
                    }

                    Layout::RawNullablePointer { nndiscr, .. } => {
                        use value::PrimVal;
                        if variant_index as u64 != nndiscr {
                            self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
                        }
                    }

                    _ => bug!("SetDiscriminant on {} represented as {:#?}", dest_ty, dest_layout),
                }
            }

            // Miri can safely ignore these. Only translation needs it.
            StorageLive(_) |
            StorageDead(_) => {}

            // Defined to do nothing. These are added by optimization passes, to avoid changing the
            // size of MIR constantly.
            Nop => {}
        }

        self.frame_mut().stmt += 1;
        Ok(())
    }

    fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx, ()> {
        trace!("{:?}", terminator.kind);
        self.eval_terminator(terminator)?;
        if !self.stack.is_empty() {
            trace!("// {:?}", self.frame().block);
        }
        Ok(())
    }
}

// WARNING: make sure that any methods implemented on this type don't ever access ecx.stack
// this includes any method that might access the stack
// basically don't call anything other than `load_mir`, `alloc_ptr`, `push_stack_frame`
// The reason for this is, that `push_stack_frame` modifies the stack out of obvious reasons
struct ConstantExtractor<'a, 'b: 'a, 'tcx: 'b> {
    span: Span,
    ecx: &'a mut EvalContext<'b, 'tcx>,
    mir: MirRef<'tcx>,
    def_id: DefId,
    substs: &'tcx subst::Substs<'tcx>,
    new_constants: &'a mut EvalResult<'tcx, u64>,
}

impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> {
    fn global_item(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span, immutable: bool) {
        let cid = GlobalId { def_id, substs, promoted: None };
        if self.ecx.globals.contains_key(&cid) {
            return;
        }
        self.try(|this| {
            let mir = this.ecx.load_mir(def_id)?;
            this.ecx.globals.insert(cid, Global::uninitialized(mir.return_ty));
            let cleanup = if immutable && !mir.return_ty.type_contents(this.ecx.tcx).interior_unsafe() {
                StackPopCleanup::Freeze
            } else {
                StackPopCleanup::None
            };
            this.ecx.push_stack_frame(def_id, span, mir, substs, Lvalue::Global(cid), cleanup, Vec::new())
        });
    }
    fn try<F: FnOnce(&mut Self) -> EvalResult<'tcx, ()>>(&mut self, f: F) {
        if let Ok(ref mut n) = *self.new_constants {
            *n += 1;
        } else {
            return;
        }
        if let Err(e) = f(self) {
            *self.new_constants = Err(e);
        }
    }
}

impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> {
    fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: mir::Location) {
        self.super_constant(constant, location);
        match constant.literal {
            // already computed by rustc
            mir::Literal::Value { .. } => {}
            mir::Literal::Item { def_id, substs } => {
                if let ty::TyFnDef(..) = constant.ty.sty {
                    // No need to do anything here,
                    // because the type is the actual function, not the signature of the function.
                    // Thus we can simply create a zero sized allocation in `evaluate_operand`
                } else {
                    self.global_item(def_id, substs, constant.span, true);
                }
            },
            mir::Literal::Promoted { index } => {
                let cid = GlobalId {
                    def_id: self.def_id,
                    substs: self.substs,
                    promoted: Some(index),
                };
                if self.ecx.globals.contains_key(&cid) {
                    return;
                }
                let mir = Ref::clone(&self.mir);
                let mir = Ref::map(mir, |mir| &mir.promoted[index]);
                self.try(|this| {
                    let ty = this.ecx.monomorphize(mir.return_ty, this.substs);
                    this.ecx.globals.insert(cid, Global::uninitialized(ty));
                    this.ecx.push_stack_frame(this.def_id,
                                              constant.span,
                                              mir,
                                              this.substs,
                                              Lvalue::Global(cid),
                                              StackPopCleanup::Freeze,
                                              Vec::new())
                });
            }
        }
    }

    fn visit_lvalue(
        &mut self,
        lvalue: &mir::Lvalue<'tcx>,
        context: LvalueContext<'tcx>,
        location: mir::Location
    ) {
        self.super_lvalue(lvalue, context, location);
        if let mir::Lvalue::Static(def_id) = *lvalue {
            let substs = self.ecx.tcx.intern_substs(&[]);
            let span = self.span;
            if let Some(node_item) = self.ecx.tcx.map.get_if_local(def_id) {
                if let hir::map::Node::NodeItem(&hir::Item { ref node, .. }) = node_item {
                    if let hir::ItemStatic(_, m, _) = *node {
                        self.global_item(def_id, substs, span, m == hir::MutImmutable);
                        return;
                    } else {
                        bug!("static def id doesn't point to static");
                    }
                } else {
                    bug!("static def id doesn't point to item");
                }
            } else {
                let def = self.ecx.tcx.sess.cstore.describe_def(def_id).expect("static not found");
                if let hir::def::Def::Static(_, mutable) = def {
                    self.global_item(def_id, substs, span, !mutable);
                } else {
                    bug!("static found but isn't a static: {:?}", def);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::time::{SystemTime, UNIX_EPOCH};
use chrono::{Local, TimeZone};
use chrono::Duration;

use nom::IResult::Done;
use nom;

/* For running git and html-tidy */
use std::process::Command;

use std::env;

/* For from::utf8 */
use std::str;

pub fn get_seconds() -> u64 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs()
}

pub fn ts_to_date(timestamp: u64) -> String {
    Local
        .timestamp(timestamp as i64, 0)
        .format("%Y-%m-%d, %H:%M")
        .to_string()
}

pub fn sec_to_hms_string(seconds: u64) -> String {
    let hours = seconds / 3600;
    let minutes = (seconds - hours * 3600) / 60;
    let seconds = seconds - minutes * 60 - hours * 3600;
    match (hours, minutes, seconds) {
        (0, 0, 1) => format!("1 second"),
        (0, 0, s) => format!("{} seconds", s),
        (0, 1, _) => format!("1 minute"),
        (0, m, _) => format!("{} minutes", m),
        /* Range matching: slightly dubious feature here */
        (1, 0...4, _)   => format!("1 hour"),
        (h, 0...4, _)   => format!("{} hours", h),
        (h, 56...59, _) => format!("{} hours", h + 1),
        (h, m, _)       => format!("{} hours and {} minutes", h, m),
    }
}

/* For parsing time in HH:MM format. */
named!(duration_hhmm(&[u8]) -> Duration,
    do_parse!(
        hour: map_res!(map_res!(nom::digit, str::from_utf8), |s: &str| s.parse::<i64>()) >>
        tag!(":") >>
        min:  map_res!(map_res!(nom::digit, str::from_utf8), |s: &str| s.parse::<i64>()) >>
        /*tag!(":") >>
        sec: map_res!(map_res!(nom::digit, str::from_utf8), |s: &str| s.parse::<i64>()) >>*/
        (Duration::minutes(hour * 60 + min))
    )
);

pub fn parse_hhmm_to_seconds(timestr: &str) -> Option<u64> {
    match duration_hhmm(timestr.as_bytes()) {
        Done(_, out) => Some(out.num_seconds() as u64),
        _ => None,
    }
}

pub fn set_to_trk_dir() -> bool {
    let mut p = env::current_dir().unwrap();
    loop {
        p.push(".trk");
        if p.exists() {
            p.pop();
            env::set_current_dir(&p).is_ok();
            return true;
        } else {
            p.pop();
            if !p.pop() {
                println!("Fatal: not a .trk directory (or subdirectory of one).");
                return false;
            }
        }
    }
}

pub fn git_init_trk() -> bool {
    if !set_to_trk_dir() {
        println!("Could not initialise trk internal git repo!\
                 (couldn't find upper level .trk dir).");
        return false;
    }

    let mut p = env::current_dir().unwrap();
    p.push(".trk");
    if p.exists() {
        env::set_current_dir(&p).is_ok();
    } else {
        println!("Couldn't access .trk sub directory to initialise trk internal git repo.");
        return false;
    }
    let output = Command::new("git")
           .arg("init")
           .output();
    match output {
        Ok(_) => {},
        Err(_) => {
            println!("Could not run git init!");
            return false;
        }
    }
    let output = Command::new("git")
           .arg("add")
           .arg("timesheet.json")
           .output();
    match output {
        Ok(_) => {},
        Err(_) => {
            println!("Could not run git init!");
            return false;
        }
    }

    /* Reset current_dir to previous value */
    p.pop();
    env::set_current_dir(&p).is_ok();
    true
}

pub fn git_commit_trk(message: &str) -> bool {
    if !set_to_trk_dir() {
        println!("Could not commit to trk internal git repo!\
                 (couldn't find upper level .trk dir).");
        return false;
    }

    let mut p = env::current_dir().unwrap();
    p.push(".trk");
    if p.exists() {
        env::set_current_dir(&p).is_ok();
    } else {
        println!("Couldn't access .trk sub directory to initialise trk internal git repo.");
        return false;
    }
    let output = Command::new("git")
           .arg("commit")
           .arg("timesheet.json")
           .arg("-m")
           .arg(message)
           .output();
    match output {
        Ok(_) => {},
        Err(_) => {
            println!("Could not run git commit!");
            return false;
        }
    }

    /* Reset current_dir to previous value */
    p.pop();
    env::set_current_dir(&p).is_ok();
    true
}
pub fn git_author() -> Option<String> {
    if let Ok(output) = Command::new("git")
           .arg("config")
           .arg("user.name")
           .output() {
        if output.status.success() {
            let output = String::from_utf8_lossy(&output.stdout);
            /* Remove trailing newline character */
            let mut output = output.to_string();
            output
                .pop()
                .expect("Empty name in git config? Not even a newline?!?");
            Some(output)
        } else {
            let output = String::from_utf8_lossy(&output.stderr);
            println!("git config user.name failed. {}", output);
            None
        }
    } else {
        None
    }
}

pub fn git_commit_message(hash: &str) -> Option<String> {
    if let Ok(output) = Command::new("git")
           .arg("log")
           .arg("--format=%B")
           .arg("-n")
           .arg("1")
           .arg(hash)
           .output() {
        if output.status.success() {
            let output = String::from_utf8_lossy(&output.stdout);
            Some(output.to_string())
        } else {
            let output = String::from_utf8_lossy(&output.stderr);
            println!("git log --format=%B -n 1 <hash> failed. {}", output);
            None
        }
    } else {
        None
    }
}

pub fn format_file(filename: &str) {
    if let Ok(_) = Command::new("tidy")
           .arg("--tidy-mark")
           .arg("no")
           .arg("-i")
           .arg("-m")
           .arg(filename)
           .output() {
    } else {
        println!("tidy-html not found!");
    }
}
<commit_msg>rename p to path<commit_after>use std::time::{SystemTime, UNIX_EPOCH};
use chrono::{Local, TimeZone};
use chrono::Duration;

use nom::IResult::Done;
use nom;

/* For running git and html-tidy */
use std::process::Command;

use std::env;

/* For from::utf8 */
use std::str;

pub fn get_seconds() -> u64 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs()
}

pub fn ts_to_date(timestamp: u64) -> String {
    Local
        .timestamp(timestamp as i64, 0)
        .format("%Y-%m-%d, %H:%M")
        .to_string()
}

pub fn sec_to_hms_string(seconds: u64) -> String {
    let hours = seconds / 3600;
    let minutes = (seconds - hours * 3600) / 60;
    let seconds = seconds - minutes * 60 - hours * 3600;
    match (hours, minutes, seconds) {
        (0, 0, 1) => format!("1 second"),
        (0, 0, s) => format!("{} seconds", s),
        (0, 1, _) => format!("1 minute"),
        (0, m, _) => format!("{} minutes", m),
        /* Range matching: slightly dubious feature here */
        (1, 0...4, _)   => format!("1 hour"),
        (h, 0...4, _)   => format!("{} hours", h),
        (h, 56...59, _) => format!("{} hours", h + 1),
        (h, m, _)       => format!("{} hours and {} minutes", h, m),
    }
}

/* For parsing time in HH:MM format. */
named!(duration_hhmm(&[u8]) -> Duration,
    do_parse!(
        hour: map_res!(map_res!(nom::digit, str::from_utf8), |s: &str| s.parse::<i64>()) >>
        tag!(":") >>
        min:  map_res!(map_res!(nom::digit, str::from_utf8), |s: &str| s.parse::<i64>()) >>
        /*tag!(":") >>
        sec: map_res!(map_res!(nom::digit, str::from_utf8), |s: &str| s.parse::<i64>()) >>*/
        (Duration::minutes(hour * 60 + min))
    )
);

pub fn parse_hhmm_to_seconds(timestr: &str) -> Option<u64> {
    match duration_hhmm(timestr.as_bytes()) {
        Done(_, out) => Some(out.num_seconds() as u64),
        _ => None,
    }
}

pub fn set_to_trk_dir() -> bool {
    let mut path = env::current_dir().unwrap();
    loop {
        path.push(".trk");
        if path.exists() {
            path.pop();
            env::set_current_dir(&path).is_ok();
            return true;
        } else {
            path.pop();
            if !path.pop() {
                println!("Fatal: not a .trk directory (or subdirectory of one).");
                return false;
            }
        }
    }
}

pub fn git_init_trk() -> bool {
    if !set_to_trk_dir() {
        println!("Could not initialise trk internal git repo!\
                 (couldn't find upper level .trk dir).");
        return false;
    }

    let mut path = env::current_dir().unwrap();
    path.push(".trk");
    if path.exists() {
        env::set_current_dir(&path).is_ok();
    } else {
        println!("Couldn't access .trk sub directory to initialise trk internal git repo.");
        return false;
    }
    let output = Command::new("git")
           .arg("init")
           .output();
    match output {
        Ok(_) => {},
        Err(_) => {
            println!("Could not run git init!");
            return false;
        }
    }
    let output = Command::new("git")
           .arg("add")
           .arg("timesheet.json")
           .output();
    match output {
        Ok(_) => {},
        Err(_) => {
            println!("Could not run git init!");
            return false;
        }
    }

    /* Reset current_dir to previous value */
    path.pop();
    env::set_current_dir(&path).is_ok();
    true
}

pub fn git_commit_trk(message: &str) -> bool {
    if !set_to_trk_dir() {
        println!("Could not commit to trk internal git repo!\
                 (couldn't find upper level .trk dir).");
        return false;
    }

    let mut p = env::current_dir().unwrap();
    p.push(".trk");
    if p.exists() {
        env::set_current_dir(&p).is_ok();
    } else {
        println!("Couldn't access .trk sub directory to initialise trk internal git repo.");
        return false;
    }
    let output = Command::new("git")
           .arg("commit")
           .arg("timesheet.json")
           .arg("-m")
           .arg(message)
           .output();
    match output {
        Ok(_) => {},
        Err(_) => {
            println!("Could not run git commit!");
            return false;
        }
    }

    /* Reset current_dir to previous value */
    p.pop();
    env::set_current_dir(&p).is_ok();
    true
}
pub fn git_author() -> Option<String> {
    if let Ok(output) = Command::new("git")
           .arg("config")
           .arg("user.name")
           .output() {
        if output.status.success() {
            let output = String::from_utf8_lossy(&output.stdout);
            /* Remove trailing newline character */
            let mut output = output.to_string();
            output
                .pop()
                .expect("Empty name in git config? Not even a newline?!?");
            Some(output)
        } else {
            let output = String::from_utf8_lossy(&output.stderr);
            println!("git config user.name failed. {}", output);
            None
        }
    } else {
        None
    }
}

pub fn git_commit_message(hash: &str) -> Option<String> {
    if let Ok(output) = Command::new("git")
           .arg("log")
           .arg("--format=%B")
           .arg("-n")
           .arg("1")
           .arg(hash)
           .output() {
        if output.status.success() {
            let output = String::from_utf8_lossy(&output.stdout);
            Some(output.to_string())
        } else {
            let output = String::from_utf8_lossy(&output.stderr);
            println!("git log --format=%B -n 1 <hash> failed. {}", output);
            None
        }
    } else {
        None
    }
}

pub fn format_file(filename: &str) {
    if let Ok(_) = Command::new("tidy")
           .arg("--tidy-mark")
           .arg("no")
           .arg("-i")
           .arg("-m")
           .arg(filename)
           .output() {
    } else {
        println!("tidy-html not found!");
    }
}
<|endoftext|>


<commit_before>extern crate native_tls;<commit_msg>Pub mod native_tls:**; for tests<commit_after>extern crate native_tls;

pub use native_tls::*;
<|endoftext|>


<commit_before>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &Path) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot.to_str().expect("non utf8 path"));
    for_all_targets(&sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn miri_pass(path: &str, target: &str, host: &str) {
    let mut config = compiletest::default_config();
    config.mode = "mir-opt".parse().expect("Invalid mode");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.rustc_path = PathBuf::from("target/debug/miri");
    // don't actually execute the final binary, it might be for other targets and we only care
    // about running miri, not the binary.
    config.runtool = Some("echo \"\" || ".to_owned());
    if target == host {
        std::env::set_var("MIRI_HOST_TARGET", "yes");
    }
    compiletest::run_tests(&config);
    std::env::set_var("MIRI_HOST_TARGET", "");
}

fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    path.metadata().map(|m| m.is_dir()).unwrap_or(false)
}

fn for_all_targets<F: FnMut(String)>(sysroot: &Path, mut f: F) {
    let target_dir = sysroot.join("lib").join("rustlib");
    println!("target dir: {}", target_dir.to_str().unwrap());
    for entry in std::fs::read_dir(target_dir).expect("invalid sysroot") {
        let entry = entry.unwrap();
        if !is_target_dir(entry.path()) { continue; }
        let target = entry.file_name().into_string().unwrap();
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    let sysroot = std::process::Command::new("rustc")
        .arg("--print")
        .arg("sysroot")
        .output()
        .expect("rustc not found")
        .stdout;
    let sysroot = std::str::from_utf8(&sysroot).expect("sysroot is not utf8").trim();
    let sysroot = &Path::new(&sysroot);
    let host = std::process::Command::new("rustc")
        .arg("-vV")
        .output()
        .expect("rustc not found for -vV")
        .stdout;
    let host = std::str::from_utf8(&host).expect("sysroot is not utf8");
    let host = host.split("\nhost: ").skip(1).next().expect("no host: part in rustc -vV");
    let host = host.split("\n").next().expect("no \n after host");
    run_pass();
    for_all_targets(&sysroot, |target| {
        miri_pass("tests/run-pass", &target, host);
        if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
            miri_pass(&path, &target, host);
        }
    });
    compile_fail(&sysroot);
}
<commit_msg>aux tests only run if the host is set<commit_after>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &Path) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot.to_str().expect("non utf8 path"));
    for_all_targets(&sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn miri_pass(path: &str, target: &str, host: &str) {
    let mut config = compiletest::default_config();
    config.mode = "mir-opt".parse().expect("Invalid mode");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.host = host.to_owned();
    config.rustc_path = PathBuf::from("target/debug/miri");
    // don't actually execute the final binary, it might be for other targets and we only care
    // about running miri, not the binary.
    config.runtool = Some("echo \"\" || ".to_owned());
    if target == host {
        std::env::set_var("MIRI_HOST_TARGET", "yes");
    }
    compiletest::run_tests(&config);
    std::env::set_var("MIRI_HOST_TARGET", "");
}

fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    path.metadata().map(|m| m.is_dir()).unwrap_or(false)
}

fn for_all_targets<F: FnMut(String)>(sysroot: &Path, mut f: F) {
    let target_dir = sysroot.join("lib").join("rustlib");
    println!("target dir: {}", target_dir.to_str().unwrap());
    for entry in std::fs::read_dir(target_dir).expect("invalid sysroot") {
        let entry = entry.unwrap();
        if !is_target_dir(entry.path()) { continue; }
        let target = entry.file_name().into_string().unwrap();
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    let sysroot = std::process::Command::new("rustc")
        .arg("--print")
        .arg("sysroot")
        .output()
        .expect("rustc not found")
        .stdout;
    let sysroot = std::str::from_utf8(&sysroot).expect("sysroot is not utf8").trim();
    let sysroot = &Path::new(&sysroot);
    let host = std::process::Command::new("rustc")
        .arg("-vV")
        .output()
        .expect("rustc not found for -vV")
        .stdout;
    let host = std::str::from_utf8(&host).expect("sysroot is not utf8");
    let host = host.split("\nhost: ").skip(1).next().expect("no host: part in rustc -vV");
    let host = host.split("\n").next().expect("no \n after host");
    run_pass();
    for_all_targets(&sysroot, |target| {
        miri_pass("tests/run-pass", &target, host);
        if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
            miri_pass(&path, &target, host);
        }
    });
    compile_fail(&sysroot);
}
<|endoftext|>


<commit_before>use std::str;

extern crate bytes;
extern crate httpbis;
extern crate futures;
extern crate native_tls;
extern crate tokio_core;
extern crate tokio_tls;
#[macro_use]
extern crate log;
extern crate env_logger;

use bytes::Bytes;

use futures::Future;

mod test_misc;

use httpbis::solicit::header::*;
use httpbis::solicit::HttpError;

use test_misc::*;
use httpbis::for_test::*;
use httpbis::solicit::ErrorCode;

#[test]
fn stream_count() {
    env_logger::init().ok();

    let server = HttpServerTester::new();

    let client: HttpClient =
        HttpClient::new("::1", server.port(), false, Default::default()).expect("connect");

    let mut server_tester = server.accept();
    server_tester.recv_preface();
    server_tester.settings_xchg();

    let state: ConnectionStateSnapshot = client.dump_state().wait().expect("state");
    assert_eq!(0, state.streams.len());

    let req = client.start_post("/foobar", "localhost", Bytes::from(&b"xxyy"[..])).collect();

    let headers = server_tester.recv_frame_headers_check(1, false);
    assert_eq!("POST", headers.get(":method"));
    assert_eq!("/foobar", headers.get(":path"));

    let data = server_tester.recv_frame_data_check(1, false);
    assert_eq!(b"xxyy", &data[..]);

    server_tester.recv_frame_data_check_empty_end(1);

    let mut resp_headers = Headers::new();
    resp_headers.add(":status", "200");
    server_tester.send_headers(1, resp_headers, false);

    server_tester.send_data(1, b"aabb", true);

    let message = req.wait().expect("r");
    assert_eq!((b"aabb"[..]).to_owned(), message.body);

    let state: ConnectionStateSnapshot = client.dump_state().wait().expect("state");
    assert_eq!(0, state.streams.len(), "{:?}", state);
}

#[test]
fn rst_is_error() {
    env_logger::init().ok();

    let server = HttpServerTester::new();

    let client: HttpClient =
        HttpClient::new("::1", server.port(), false, Default::default()).expect("connect");

    let mut server_tester = server.accept();
    server_tester.recv_preface();
    server_tester.settings_xchg();

    let req = client.start_get("/fgfg", "localhost").collect();

    let get = server_tester.recv_message(1);
    assert_eq!("GET", get.headers.method());

    server_tester.send_headers(1, Headers::ok_200(), false);
    server_tester.send_rst(1, ErrorCode::InadequateSecurity);

    match req.wait() {
        Ok(..) => panic!("expected error"),
        Err(HttpError::CodeError(ErrorCode::InadequateSecurity)) => {},
        Err(e) => panic!("wrong error: {:?}", e),
    }

    let state: ConnectionStateSnapshot = client.dump_state().wait().expect("state");
    assert_eq!(0, state.streams.len(), "{:?}", state);
}

#[test]
fn client_call_dropped() {
    env_logger::init().ok();

    let server = HttpServerTester::new();

    let client: HttpClient =
        HttpClient::new("::1", server.port(), false, Default::default()).expect("connect");

    let mut server_tester = server.accept();
    server_tester.recv_preface();
    server_tester.settings_xchg();

    {
        let req = client.start_get("/fgfg", "localhost");

        server_tester.recv_message(1);

        drop(req);

        server_tester.send_headers(1, Headers::ok_200(), true);
    }

    {
        let req = client.start_get("/fgfg", "localhost").collect();
        server_tester.recv_message(3);
        server_tester.send_headers(3, Headers::ok_200(), true);
        let resp = req.wait().expect("OK");
        assert_eq!(200, resp.headers.status());
    }

}
<commit_msg>Better test<commit_after>use std::str;

extern crate bytes;
extern crate httpbis;
extern crate futures;
extern crate native_tls;
extern crate tokio_core;
extern crate tokio_tls;
#[macro_use]
extern crate log;
extern crate env_logger;

use bytes::Bytes;

use futures::Future;

mod test_misc;

use httpbis::solicit::header::*;
use httpbis::solicit::HttpError;

use test_misc::*;
use httpbis::for_test::*;
use httpbis::solicit::ErrorCode;

#[test]
fn stream_count() {
    env_logger::init().ok();

    let server = HttpServerTester::new();

    let client: HttpClient =
        HttpClient::new("::1", server.port(), false, Default::default()).expect("connect");

    let mut server_tester = server.accept();
    server_tester.recv_preface();
    server_tester.settings_xchg();

    let state: ConnectionStateSnapshot = client.dump_state().wait().expect("state");
    assert_eq!(0, state.streams.len());

    let req = client.start_post("/foobar", "localhost", Bytes::from(&b"xxyy"[..])).collect();

    let headers = server_tester.recv_frame_headers_check(1, false);
    assert_eq!("POST", headers.get(":method"));
    assert_eq!("/foobar", headers.get(":path"));

    let data = server_tester.recv_frame_data_check(1, false);
    assert_eq!(b"xxyy", &data[..]);

    server_tester.recv_frame_data_check_empty_end(1);

    let mut resp_headers = Headers::new();
    resp_headers.add(":status", "200");
    server_tester.send_headers(1, resp_headers, false);

    server_tester.send_data(1, b"aabb", true);

    let message = req.wait().expect("r");
    assert_eq!((b"aabb"[..]).to_owned(), message.body);

    let state: ConnectionStateSnapshot = client.dump_state().wait().expect("state");
    assert_eq!(0, state.streams.len(), "{:?}", state);
}

#[test]
fn rst_is_error() {
    env_logger::init().ok();

    let server = HttpServerTester::new();

    let client: HttpClient =
        HttpClient::new("::1", server.port(), false, Default::default()).expect("connect");

    let mut server_tester = server.accept();
    server_tester.recv_preface();
    server_tester.settings_xchg();

    let req = client.start_get("/fgfg", "localhost").collect();

    let get = server_tester.recv_message(1);
    assert_eq!("GET", get.headers.method());

    server_tester.send_headers(1, Headers::ok_200(), false);
    server_tester.send_rst(1, ErrorCode::InadequateSecurity);

    match req.wait() {
        Ok(..) => panic!("expected error"),
        Err(HttpError::CodeError(ErrorCode::InadequateSecurity)) => {},
        Err(e) => panic!("wrong error: {:?}", e),
    }

    let state: ConnectionStateSnapshot = client.dump_state().wait().expect("state");
    assert_eq!(0, state.streams.len(), "{:?}", state);
}

#[test]
fn client_call_dropped() {
    env_logger::init().ok();

    let server = HttpServerTester::new();

    let client: HttpClient =
        HttpClient::new("::1", server.port(), false, Default::default()).expect("connect");

    let mut server_tester = server.accept();
    server_tester.recv_preface();
    server_tester.settings_xchg();

    {
        let req = client.start_get("/fgfg", "localhost");

        server_tester.recv_message(1);

        drop(req);

        server_tester.send_headers(1, Headers::ok_200(), true);
    }

    {
        let req = client.start_get("/fgfg", "localhost").collect();
        server_tester.recv_message(3);
        server_tester.send_headers(3, Headers::ok_200(), true);
        let resp = req.wait().expect("OK");
        assert_eq!(200, resp.headers.status());
    }

    let state: ConnectionStateSnapshot = client.dump_state().wait().expect("state");
    assert_eq!(0, state.streams.len(), "{:?}", state);
}
<|endoftext|>


<commit_before> #[feature(struct_variant)];
extern mod extra;
use extra::getopts;
use std::rand;
use std::fmt;

fn randrange(min : uint, max : uint) -> uint {
    min + rand::random::<uint>() % (max - min)
}

struct ServerID(uint);

#[deriving(Ord)]
struct Term(uint);

#[deriving(Ord)]
struct Index(uint);

#[deriving(Ord)]
struct Time(uint);

struct Environment {
    clock: Time,
    num_servers: uint,
    network: ~[Message],
}

impl Environment {
    fn new(num_servers: uint) -> Environment {
        Environment {
            clock: Time(0),
            num_servers: num_servers,
            network: ~[],
        }
    }
    fn make_time(&self, min: uint, max: uint) -> Time {
        Time(*self.clock + randrange(min, max))
    }
}

struct Message {
    from: ServerID,
    to: ServerID,
    term: Term,
    body: MessageBody,
}

enum MessageBody {
    RequestVoteRequest {
        lastLogTerm: Term,
        lastLogIndex: Index,
    },
    RequestVoteResponse {
        granted: bool,
    },
}

enum ServerState {
    Follower  { timer: Time },
    Candidate { timer: Time, votes: uint },
    Leader,
}

impl fmt::Default for Time {
    fn fmt(time: &Time, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **time)
    }
}

impl fmt::Default for ServerState {
    fn fmt(state: &ServerState, f: &mut fmt::Formatter) {
        match *state {
            Follower{timer} => write!(f.buf, "Follower({})", timer),
            Candidate{timer, votes} => write!(f.buf, "Candidate({}, {})", timer, votes),
            Leader => write!(f.buf, "Leader"),
        }
    }
}

struct LogEntry {
    term: Term,
    // command: ~str,
}

struct Log(~[LogEntry]);

impl Log {
    fn new() -> Log {
        Log(~[])
    }
}

struct Server {
    id: ServerID,
    term: Term,
    state: ServerState,
    log: Log,
}

impl Server {
    fn new(id : ServerID, env: &Environment) -> Server {
        Server {
            id: id,
            term: Term(0),
            state: Follower { timer: env.make_time(150, 300) },
            log: Log::new(),
        }
    }
    /*
    fn reset_timer(&mut self) {
        self.set_timer(Time(*self.env.clock + randrange(150, 300)));
    }
    fn set_timer(&mut self, time: Time) {
        match self.state {
            Follower  {timer : ref mut timer, _} |
            Candidate {timer : ref mut timer, _} =>
                { *timer = time },
            Leader => {},
        }
    }
    */
    fn tick(&mut self, env: &Environment) {
        match self.state {
            Follower  {timer, _} |
            Candidate {timer, _} => {
                if timer <= env.clock {
                    self.term = Term(*self.term + 1);
                    self.state = Candidate {
                        timer: env.make_time(150, 300),
                        votes: 1,
                    };
                }
            },
            Leader => {},
        }
    }
    fn try_become_leader(&mut self, env: &Environment) {
        match self.state {
            Follower {_} => {},
            Candidate {votes, _} => {
                if votes > env.num_servers / 2 {
                    self.state = Leader;
                }
            },
            Leader => {},
        }
    }
    /*
    fn next_event_time(&self) -> Time {
        match self.state {
            Follower  {timer, _} |
            Candidate {timer, _} =>
                timer,
            Leader => Time(!0)
        }
    }
    */
}

impl ToStr for Server {
    fn to_str(&self) -> ~str {
        format!("Server {}: {}", *self.id, self.state)
    }
}

struct Servers(~[Server]);

impl Servers {
    fn new(env: &Environment) -> Servers {
        let mut servers = ~[];
        for i in range(0, env.num_servers) {
            let s = Server::new(ServerID(i + 1), env);
            servers.push(s);
        }
        return Servers(servers);
    }
}

fn main() {
    let args = std::os::args();
    let opts = ~[
        getopts::optflag("h"),
        getopts::optflag("help"),
        getopts::optopt("servers"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m },
        Err(f) => { fail!(f.to_err_msg()) },
    };
    let usage = || {
        println!("Usage: {} [options]", args[0]);
        println("-h, --help   Print this help message");
        println("--servers=N  Simulate cluster with N servers");
    };
    if matches.opt_present("h") || matches.opt_present("help") {
        usage();
        return;
    }
    if !matches.free.is_empty() {
        usage();
        fail!(format!("Extra arguments: {}", matches.free.len()));
    }
    let num_servers : uint = match matches.opt_str("servers") {
        Some(s) => { match std::from_str::from_str(s) {
            Some(i) => { i },
            None => {
                usage();
                fail!(format!("Couldn't parse number of servers from '{}'", s));
            },
        }},
        None => { 5 },
    };
    let env = &mut Environment::new(num_servers);
    let mut servers = Servers::new(env);
    loop {
        for server in servers.iter() {
            println(server.to_str());
        }
        env.clock = Time(*env.clock + 1);
        for server in servers.mut_iter() {
            server.tick(env);
        }
    }

    env.network.push(Message {
        from: ServerID(1),
        to: ServerID(2),
        term: Term(0),
        body: RequestVoteRequest {
            lastLogTerm: Term(0),
            lastLogIndex: Index(0),
        },
    });

    for message in env.network.iter() {
        println(format!("{} to {}", *message.from, *message.to));
    }
}

<commit_msg>Print messages<commit_after> #[feature(struct_variant)];
extern mod extra;
use extra::getopts;
use std::rand;
use std::fmt;

fn randrange(min : uint, max : uint) -> uint {
    min + rand::random::<uint>() % (max - min)
}

#[deriving(Eq)]
struct ServerID(uint);

#[deriving(Ord)]
struct Term(uint);

#[deriving(Ord)]
struct Index(uint);

#[deriving(Ord)]
struct Time(uint);

struct Environment {
    clock: Time,
    num_servers: uint,
    network: ~[Message],
}

impl Environment {
    fn new(num_servers: uint) -> Environment {
        Environment {
            clock: Time(0),
            num_servers: num_servers,
            network: ~[],
        }
    }
    fn make_time(&self, min: uint, max: uint) -> Time {
        Time(*self.clock + randrange(min, max))
    }
}

struct Message {
    from: ServerID,
    to: ServerID,
    term: Term,
    body: MessageBody,
}

enum MessageBody {
    RequestVoteRequest {
        lastLogTerm: Term,
        lastLogIndex: Index,
    },
    RequestVoteResponse {
        granted: bool,
    },
}

impl fmt::Default for Message {
    fn fmt(msg: &Message, f: &mut fmt::Formatter) {
        write!(f.buf, "{} to {} in {}: {}",
               *msg.from,
               *msg.to,
               *msg.term,
               msg.body);
    }
}

impl fmt::Default for MessageBody {
    fn fmt(b: &MessageBody, f: &mut fmt::Formatter) {
        match *b {
            RequestVoteRequest{lastLogTerm, lastLogIndex} =>
                write!(f.buf, "RequestVoteRequest({}, {})",
                       lastLogTerm, lastLogIndex),
            RequestVoteResponse{granted} =>
                write!(f.buf, "RequestVoteResponse({})",
                       granted),
        }
    }
}

enum ServerState {
    Follower  { timer: Time },
    Candidate { timer: Time, votes: uint },
    Leader,
}

impl fmt::Default for Time {
    fn fmt(time: &Time, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **time)
    }
}

impl fmt::Default for Term {
    fn fmt(term: &Term, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **term)
    }
}

impl fmt::Default for Index {
    fn fmt(index: &Index, f: &mut fmt::Formatter) {
        write!(f.buf, "{}", **index)
    }
}

impl fmt::Default for ServerState {
    fn fmt(state: &ServerState, f: &mut fmt::Formatter) {
        match *state {
            Follower{timer} => write!(f.buf, "Follower({})", timer),
            Candidate{timer, votes} => write!(f.buf, "Candidate({}, {})", timer, votes),
            Leader => write!(f.buf, "Leader"),
        }
    }
}

struct LogEntry {
    term: Term,
    // command: ~str,
}

struct Log(~[LogEntry]);

impl Log {
    fn new() -> Log {
        Log(~[])
    }
}

struct Server {
    id: ServerID,
    term: Term,
    state: ServerState,
    log: Log,
}

impl Server {
    fn new(id : ServerID, env: &Environment) -> Server {
        Server {
            id: id,
            term: Term(0),
            state: Follower { timer: env.make_time(150, 300) },
            log: Log::new(),
        }
    }
    /*
    fn reset_timer(&mut self) {
        self.set_timer(Time(*self.env.clock + randrange(150, 300)));
    }
    fn set_timer(&mut self, time: Time) {
        match self.state {
            Follower  {timer : ref mut timer, _} |
            Candidate {timer : ref mut timer, _} =>
                { *timer = time },
            Leader => {},
        }
    }
    */
    fn tick(&mut self, env: &mut Environment) {
        match self.state {
            Follower  {timer, _} |
            Candidate {timer, _} => {
                if timer <= env.clock {
                    self.term = Term(*self.term + 1);
                    self.state = Candidate {
                        timer: env.make_time(150, 300),
                        votes: 1,
                    };
                    for peer in range(1, env.num_servers) {
                        if ServerID(peer) != self.id {
                            env.network.push(Message {
                                from: self.id,
                                to: ServerID(peer),
                                term: self.term,
                                body: RequestVoteRequest {
                                    lastLogTerm: Term(0),
                                    lastLogIndex: Index(0),
                                },
                            });
                        }
                    }
                }
                self.try_become_leader(env);
            },
            Leader => {},
        }
    }
    fn try_become_leader(&mut self, env: &Environment) {
        match self.state {
            Follower {_} => {},
            Candidate {votes, _} => {
                if votes > env.num_servers / 2 {
                    self.state = Leader;
                }
            },
            Leader => {},
        }
    }
    /*
    fn next_event_time(&self) -> Time {
        match self.state {
            Follower  {timer, _} |
            Candidate {timer, _} =>
                timer,
            Leader => Time(!0)
        }
    }
    */
}

impl ToStr for Server {
    fn to_str(&self) -> ~str {
        format!("Server {}: {}", *self.id, self.state)
    }
}

struct Servers(~[Server]);

impl Servers {
    fn new(env: &Environment) -> Servers {
        let mut servers = ~[];
        for i in range(0, env.num_servers) {
            let s = Server::new(ServerID(i + 1), env);
            servers.push(s);
        }
        return Servers(servers);
    }
}

fn main() {
    let args = std::os::args();
    let opts = ~[
        getopts::optflag("h"),
        getopts::optflag("help"),
        getopts::optopt("servers"),
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m },
        Err(f) => { fail!(f.to_err_msg()) },
    };
    let usage = || {
        println!("Usage: {} [options]", args[0]);
        println("-h, --help   Print this help message");
        println("--servers=N  Simulate cluster with N servers");
    };
    if matches.opt_present("h") || matches.opt_present("help") {
        usage();
        return;
    }
    if !matches.free.is_empty() {
        usage();
        fail!(format!("Extra arguments: {}", matches.free.len()));
    }
    let num_servers : uint = match matches.opt_str("servers") {
        Some(s) => { match std::from_str::from_str(s) {
            Some(i) => { i },
            None => {
                usage();
                fail!(format!("Couldn't parse number of servers from '{}'", s));
            },
        }},
        None => { 5 },
    };
    let env = &mut Environment::new(num_servers);
    let mut servers = Servers::new(env);
    loop {
        env.clock = Time(*env.clock + 1);
        for server in servers.mut_iter() {
            server.tick(env);
        }
        for server in servers.iter() {
            println(server.to_str());
        }
        for message in env.network.iter() {
            println!("{}", *message);
        }
        println("");
    }

    env.network.push(Message {
        from: ServerID(1),
        to: ServerID(2),
        term: Term(0),
        body: RequestVoteRequest {
            lastLogTerm: Term(0),
            lastLogIndex: Index(0),
        },
    });

}

<|endoftext|>


<commit_before>extern crate game_state;

use game_state::state::State;
use game_state::Renderer;

use std::sync::Arc;

#[no_mangle]
pub extern "C" fn mod_input_load( state: &mut State ) {
    state.input_state.clear();
}

#[no_mangle]
pub extern "C" fn mod_input_tick( state: &mut State ) {
    // Renderers own the input event loop associated with their
    // internals: i.e. the window manager window
    // - get input events and convert them to our internal format
    // and push them into the input events queue

    // we want to clear that queue each tick, regardless of if we dealt with the events
    state.input_state.pending_input_events.clear();

    // Now we want to
    for i in 0 .. state.renderers.len() {
        let mut events = state.renderers[i].get_input_events();
        if events.len() > 0 {
            println!("Renderer {} -> {:?}", state.renderers[i].identify(), events);
        }
        state.input_state.pending_input_events.append(&mut events);
    }
}

#[no_mangle]
pub extern "C" fn mod_input_unload( state: &mut State ) {
    state.input_state.clear();
}
<commit_msg>only queue events when there are actually events<commit_after>extern crate game_state;

use game_state::state::State;
use game_state::Renderer;

use std::sync::Arc;

#[no_mangle]
pub extern "C" fn mod_input_load( state: &mut State ) {
    state.input_state.clear();
}

#[no_mangle]
pub extern "C" fn mod_input_tick( state: &mut State ) {
    // Renderers own the input event loop associated with their
    // internals: i.e. the window manager window
    // - get input events and convert them to our internal format
    // and push them into the input events queue

    // we want to clear that queue each tick, regardless of if we dealt with the events
    state.input_state.pending_input_events.clear();

    // Now we want to
    for i in 0 .. state.renderers.len() {
        let mut events = state.renderers[i].get_input_events();
        if events.len() > 0 {
            println!("Renderer {} -> {:?}", state.renderers[i].identify(), events);
            state.input_state.pending_input_events.append(&mut events);
        }
    }
}

#[no_mangle]
pub extern "C" fn mod_input_unload( state: &mut State ) {
    state.input_state.clear();
}
<|endoftext|>


<commit_before>extern crate vcdim;

use vcdim::*;
use std::fs;
use std::collections::HashMap;

macro_rules! println_ignore_err {
    ($fmt:expr, $($arg:tt)*) => (
        use std::io::Write;
        match write!(&mut std::io::stdout(), concat!($fmt, "\n"), $($arg)*) {
            Ok(_) => {},
            Err(e) => {
                if e.kind() == std::io::ErrorKind::BrokenPipe {
                    ();
                } else {
                    panic!("{}", e)
                }
            },
        });
}

fn visibility_structure(vcd: &VcDim) -> String {
    let pts = vcd.points();
    let sh = vcd.max_shattered_subset();
    vcd.visible().iter().enumerate().map(|(i,v)| {
        let c = v.iter().enumerate()
            .filter(|&(j, sees_i)| { sh.contains(&pts[j]) && *sees_i })
            .count();
        if sh.contains(&pts[i]) {
            (96 + c as u8) as char // 1 -> 'a', 2 -> 'b', etc.
        } else {
            (48 + c as u8) as char // 0 -> '0', 1 -> '1', etc.
        }
    }).collect::<String>()
}
fn visibility_structure_simplified(vcd: &VcDim) -> String {
    let pts = vcd.points();
    let sh = vcd.max_shattered_subset();
    let mut chars = vcd.visible().iter().enumerate().filter_map(|(i,v)| {
        let c = v.iter().enumerate()
            .filter(|&(j, sees_i)| { sh.contains(&pts[j]) && *sees_i })
            .count();
        if sh.contains(&pts[i]) {
            Some((96 + c as u8) as char) // 1 -> 'a', 2 -> 'b', etc.
        } else {
            None
        }
    }).collect::<Vec<char>>();
    chars.sort();
    chars.into_iter().collect::<String>()
}
/// Normalizes a `String` representing the visibility structure of a (minimum) polygon.
///
/// The result is a cyclic permutation of `str` or of its reverse,
/// starts with a '0' and is the lexicographical smaller one of the two possibilities.
fn normalize(str: &str) -> String {
    let pos_of_0 = str.bytes().position(|c| { c == b'0' })
        .expect("str is representation of a shattered set, so there must be one point seeing 0 points.");
    let (p1, p2) = str.split_at(pos_of_0);
    let str1 = format!("{}{}", p2, p1); // concat p2 and p1
    let (p1, p2) = str.split_at(pos_of_0 + 1);
    let str2 = format!("{}{}", p2, p1).chars().rev().collect::<String>(); // concat p2 and p1 and reverse the String
    std::cmp::min(str1, str2)
}

/// Computes the visibility string of each polygon
/// in an ipe-file in the given directory.
fn main() {
    let mut args = std::env::args().skip(1);
    let mut sort = false;
    let mut show_filenames = false;
    let mut simplified = false;
    let mut in_dir = "in".into();
    while let Some(arg) = args.next() {
        if arg == "--sort" {
            sort = true;
        } else if arg == "--show-filenames" {
            show_filenames = true;
        } else if arg == "--simplified" {
            simplified = true;
        } else {
            in_dir = arg;
        }
    }
    let sort = sort; //make immutable
    let in_dir = in_dir; //make immutable

    let mut ipe_files = Vec::new();
    if let Ok(entries) = fs::read_dir(in_dir) {
        for entry in entries {
            if let Ok(entry) = entry {
            if let Ok(file_type) = entry.file_type() {
            if file_type.is_file() {
                if entry.path().extension() == Some(std::ffi::OsStr::new("ipe")) {
                    ipe_files.push(entry.path());
                }
            }}}
        }
    }
    let mut vis_structures = HashMap::new();
    for path in ipe_files {
        let vcd = VcDim::import_ipe(fs::File::open(path.clone()).expect("file not found"), 1f64).expect("File is malformed!");
        let vis_str = if simplified {
            visibility_structure_simplified(&vcd)
        } else {
            normalize(&visibility_structure(&vcd))
        };
        if !sort {
            if show_filenames {
                println_ignore_err!("{}: {}", path.file_name().unwrap().to_str().unwrap(), vis_str);
            } else {
                println_ignore_err!("{}", vis_str);
            }
        } else {
            let counter = vis_structures.entry(vis_str).or_insert(0);
            *counter += 1;
        }
    }
    if !sort { return; }
    let mut vis_counts: Vec<_> = vis_structures.iter().collect();
    vis_counts.sort_by(|a, b| b.1.cmp(a.1));

    for v in vis_counts {
        println_ignore_err!("{}: {}", v.0, v.1);
    }
}

<commit_msg>Fix visibility structure for cases when a VC-Point is duplicated<commit_after>extern crate vcdim;

use vcdim::*;
use std::fs;
use std::collections::HashMap;

macro_rules! println_ignore_err {
    ($fmt:expr, $($arg:tt)*) => (
        use std::io::Write;
        match write!(&mut std::io::stdout(), concat!($fmt, "\n"), $($arg)*) {
            Ok(_) => {},
            Err(e) => {
                if e.kind() == std::io::ErrorKind::BrokenPipe {
                    ();
                } else {
                    panic!("{}", e)
                }
            },
        });
}

fn visibility_structure(vcd: &VcDim) -> String {
    let sh = vcd.max_shattered_subset();
    let sh_index = sh.iter().map(|v|
            vcd.points().iter()
                .position(|p| p == v)
                .expect("It's a point of the polygon")
        ).collect::<Vec<_>>();
    vcd.visible().iter().enumerate().map(|(i,v)| {
        let c = v.iter().enumerate()
            .filter(|&(j, sees_i)| { sh_index.contains(&j) && *sees_i })
            .count();
        if sh_index.contains(&i) {
            (96 + c as u8) as char // 1 -> 'a', 2 -> 'b', etc.
        } else {
            (48 + c as u8) as char // 0 -> '0', 1 -> '1', etc.
        }
    }).collect::<String>()
}
fn visibility_structure_simplified(vcd: &VcDim) -> String {
    let sh = vcd.max_shattered_subset();
    let sh_index = sh.iter().map(|v|
            vcd.points().iter()
                .position(|p| p == v)
                .expect("It's a point of the polygon")
        ).collect::<Vec<_>>();
    let mut chars = sh_index.iter()
        .map(|&i| {
            let c = sh_index.iter()
                .filter(|&&j| vcd.visible()[i][j])
                .count();
            (96 + c as u8) as char
        }).collect::<Vec<char>>();
    chars.sort();
    chars.into_iter().collect::<String>()
}
/// Normalizes a `String` representing the visibility structure of a (minimum) polygon.
///
/// The result is a cyclic permutation of `str` or of its reverse,
/// starts with a '0' and is the lexicographical smaller one of the two possibilities.
fn normalize(str: &str) -> String {
    let pos_of_0 = str.bytes().position(|c| { c == b'0' })
        .expect("str is representation of a shattered set, so there must be one point seeing 0 points.");
    let (p1, p2) = str.split_at(pos_of_0);
    let str1 = format!("{}{}", p2, p1); // concat p2 and p1
    let (p1, p2) = str.split_at(pos_of_0 + 1);
    let str2 = format!("{}{}", p2, p1).chars().rev().collect::<String>(); // concat p2 and p1 and reverse the String
    std::cmp::min(str1, str2)
}

/// Computes the visibility string of each polygon
/// in an ipe-file in the given directory.
fn main() {
    let mut args = std::env::args().skip(1);
    let mut sort = false;
    let mut show_filenames = false;
    let mut simplified = false;
    let mut in_dir = "in".into();
    while let Some(arg) = args.next() {
        if arg == "--sort" {
            sort = true;
        } else if arg == "--show-filenames" {
            show_filenames = true;
        } else if arg == "--simplified" {
            simplified = true;
        } else {
            in_dir = arg;
        }
    }
    let sort = sort; //make immutable
    let in_dir = in_dir; //make immutable

    let mut ipe_files = Vec::new();
    if let Ok(entries) = fs::read_dir(in_dir) {
        for entry in entries {
            if let Ok(entry) = entry {
            if let Ok(file_type) = entry.file_type() {
            if file_type.is_file() {
                if entry.path().extension() == Some(std::ffi::OsStr::new("ipe")) {
                    ipe_files.push(entry.path());
                }
            }}}
        }
    }
    let mut vis_structures = HashMap::new();
    for path in ipe_files {
        let vcd = VcDim::import_ipe(fs::File::open(path.clone()).expect("file not found"), 1f64).expect("File is malformed!");
        let vis_str = if simplified {
            visibility_structure_simplified(&vcd)
        } else {
            normalize(&visibility_structure(&vcd))
        };
        if !sort {
            if show_filenames {
                println_ignore_err!("{}: {}", path.file_name().unwrap().to_str().unwrap(), vis_str);
            } else {
                println_ignore_err!("{}", vis_str);
            }
        } else {
            let counter = vis_structures.entry(vis_str).or_insert(0);
            *counter += 1;
        }
    }
    if !sort { return; }
    let mut vis_counts: Vec<_> = vis_structures.iter().collect();
    vis_counts.sort_by(|a, b| b.1.cmp(a.1));

    for v in vis_counts {
        println_ignore_err!("{}: {}", v.0, v.1);
    }
}

<|endoftext|>


<commit_before>use std::collections::BTreeMap;

#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidRowCount(usize),
    InvalidColumnCount(usize),
}

pub fn convert(input: &str) -> Result<String, Error> {
    let line_count = input.lines().count();
    if line_count % 4 != 0 {
        return Err(Error::InvalidRowCount(line_count));
    }
    for line in input.lines() {
        let char_count = line.chars().count();
        if char_count % 3 != 0 {
            return Err(Error::InvalidColumnCount(char_count));
        }
    }

    let y = input.lines().collect::<Vec<_>>();

    let mut converted_lines = vec![];

    for char_lines in y.chunks(4) {
        let mut unparsed_characters = BTreeMap::new();

        for line in char_lines {
            let line_chars = line.chars().collect::<Vec<_>>();

            for (char_number, char_chunk) in line_chars.chunks(3).enumerate() {
                let char_chars = unparsed_characters.entry(char_number).or_insert_with(Vec::new);
                for c in char_chunk {
                    char_chars.push(*c);
                }
            }
        }

        let mut parsed_characters = String::new();

        for (_, v) in unparsed_characters {
            parsed_characters.push(convert_character(&v));
        }

        converted_lines.push(parsed_characters.to_string());
    }

    Ok(converted_lines.join(","))
}

fn convert_character(input: &[char]) -> char {
    if &input[..] == [' ', '_', ' ', '|', ' ', '|', '|', '_', '|', ' ', ' ', ' '] {
        '0'
    } else if &input[..] == [' ', ' ', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '1'
    } else if &input[..] == [' ', '_', ' ', ' ', '_', '|', '|', '_', ' ', ' ', ' ', ' '] {
        '2'
    } else if &input[..] == [' ', '_', ' ', ' ', '_', '|', ' ', '_', '|', ' ', ' ', ' '] {
        '3'
    } else if &input[..] == [' ', ' ', ' ', '|', '_', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '4'
    } else if &input[..] == [' ', '_', ' ', '|', '_', ' ', ' ', '_', '|', ' ', ' ', ' '] {
        '5'
    } else if &input[..] == [' ', '_', ' ', '|', '_', ' ', '|', '_', '|', ' ', ' ', ' '] {
        '6'
    } else if &input[..] == [' ', '_', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '7'
    } else if &input[..] == [' ', '_', ' ', '|', '_', '|', '|', '_', '|', ' ', ' ', ' '] {
        '8'
    } else if &input[..] == [' ', '_', ' ', '|', '_', '|', ' ', '_', '|', ' ', ' ', ' '] {
        '9'
    } else {
        '?'
    }
}
<commit_msg>ocr-numbers: rm unnecessary references<commit_after>use std::collections::BTreeMap;

#[derive(Debug, PartialEq)]
pub enum Error {
    InvalidRowCount(usize),
    InvalidColumnCount(usize),
}

pub fn convert(input: &str) -> Result<String, Error> {
    let line_count = input.lines().count();
    if line_count % 4 != 0 {
        return Err(Error::InvalidRowCount(line_count));
    }
    for line in input.lines() {
        let char_count = line.chars().count();
        if char_count % 3 != 0 {
            return Err(Error::InvalidColumnCount(char_count));
        }
    }

    let y = input.lines().collect::<Vec<_>>();

    let mut converted_lines = vec![];

    for char_lines in y.chunks(4) {
        let mut unparsed_characters = BTreeMap::new();

        for line in char_lines {
            let line_chars = line.chars().collect::<Vec<_>>();

            for (char_number, char_chunk) in line_chars.chunks(3).enumerate() {
                let char_chars = unparsed_characters.entry(char_number).or_insert_with(Vec::new);
                for c in char_chunk {
                    char_chars.push(*c);
                }
            }
        }

        let mut parsed_characters = String::new();

        for (_, v) in unparsed_characters {
            parsed_characters.push(convert_character(&v));
        }

        converted_lines.push(parsed_characters.to_string());
    }

    Ok(converted_lines.join(","))
}

fn convert_character(input: &[char]) -> char {
    if input[..] == [' ', '_', ' ', '|', ' ', '|', '|', '_', '|', ' ', ' ', ' '] {
        '0'
    } else if input[..] == [' ', ' ', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '1'
    } else if input[..] == [' ', '_', ' ', ' ', '_', '|', '|', '_', ' ', ' ', ' ', ' '] {
        '2'
    } else if input[..] == [' ', '_', ' ', ' ', '_', '|', ' ', '_', '|', ' ', ' ', ' '] {
        '3'
    } else if input[..] == [' ', ' ', ' ', '|', '_', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '4'
    } else if input[..] == [' ', '_', ' ', '|', '_', ' ', ' ', '_', '|', ' ', ' ', ' '] {
        '5'
    } else if input[..] == [' ', '_', ' ', '|', '_', ' ', '|', '_', '|', ' ', ' ', ' '] {
        '6'
    } else if input[..] == [' ', '_', ' ', ' ', ' ', '|', ' ', ' ', '|', ' ', ' ', ' '] {
        '7'
    } else if input[..] == [' ', '_', ' ', '|', '_', '|', '|', '_', '|', ' ', ' ', ' '] {
        '8'
    } else if input[..] == [' ', '_', ' ', '|', '_', '|', ' ', '_', '|', ' ', ' ', ' '] {
        '9'
    } else {
        '?'
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use super::{htons, ntohs};
use std::io;

pub mod public {

    use super::libc;
    use super::{htons, ntohs};
    use std::io;
    use std::mem;
    use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
    use std::time::Duration;

    pub type CSocket = libc::c_int;
    pub type Buf = *const libc::c_void;
    pub type MutBuf = *mut libc::c_void;
    pub type BufLen = libc::size_t;
    pub type CouldFail = libc::ssize_t;
    pub type SockLen = libc::socklen_t;
    pub type MutSockLen = *mut libc::socklen_t;
    pub type SockAddr = libc::sockaddr;
    pub type SockAddrIn = libc::sockaddr_in;
    pub type SockAddrIn6 = libc::sockaddr_in6;
    pub type SockAddrStorage = libc::sockaddr_storage;
    pub type SockAddrFamily = libc::sa_family_t;
    pub type SockAddrFamily6 = libc::sa_family_t;
    pub type InAddr = libc::in_addr;
    pub type In6Addr = libc::in6_addr;

    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
    pub type TvUsecType = libc::c_long;
    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub type TvUsecType = libc::c_int;

    pub const AF_INET: libc::c_int = libc::AF_INET;
    pub const AF_INET6: libc::c_int = libc::AF_INET6;
    pub const SOCK_RAW: libc::c_int = libc::SOCK_RAW;

    pub const SOL_SOCKET: libc::c_int = libc::SOL_SOCKET;
    pub const SO_RCVTIMEO: libc::c_int = libc::SO_RCVTIMEO;
    pub const SO_SNDTIMEO: libc::c_int = libc::SO_SNDTIMEO;

    pub const IPPROTO_IP: libc::c_int = libc::IPPROTO_IP;
    pub const IP_HDRINCL: libc::c_int = libc::IP_HDRINCL;
    pub const IP_TTL: libc::c_int = libc::IP_TTL;

    pub use super::libc::{IFF_BROADCAST, IFF_LOOPBACK, IFF_MULTICAST, IFF_POINTOPOINT, IFF_UP};

    pub const INVALID_SOCKET: CSocket = -1;

    pub unsafe fn close(sock: CSocket) {
        let _ = libc::close(sock);
    }

    pub unsafe fn socket(af: libc::c_int, sock: libc::c_int, proto: libc::c_int) -> CSocket {
        libc::socket(af, sock, proto)
    }

    pub unsafe fn getsockopt(
        socket: CSocket,
        level: libc::c_int,
        name: libc::c_int,
        value: MutBuf,
        option_len: MutSockLen,
    ) -> libc::c_int {
        libc::getsockopt(socket, level, name, value, option_len)
    }

    pub unsafe fn setsockopt(
        socket: CSocket,
        level: libc::c_int,
        name: libc::c_int,
        value: Buf,
        option_len: SockLen,
    ) -> libc::c_int {
        libc::setsockopt(socket, level, name, value, option_len)
    }

    /// Convert a platform specific `timeval` into a Duration.
    pub fn timeval_to_duration(tv: libc::timeval) -> Duration {
        Duration::new(tv.tv_sec as u64, (tv.tv_usec as u32) * 1000)
    }

    /// Convert a Duration into a platform specific `timeval`.
    pub fn duration_to_timeval(dur: Duration) -> libc::timeval {
        libc::timeval {
            tv_sec: dur.as_secs() as libc::time_t,
            tv_usec: dur.subsec_micros() as TvUsecType,
        }
    }

    /// Convert a platform specific `timespec` into a Duration.
    pub fn timespec_to_duration(ts: libc::timespec) -> Duration {
        Duration::new(ts.tv_sec as u64, ts.tv_nsec as u32)
    }

    /// Convert a Duration into a platform specific `timespec`.
    pub fn duration_to_timespec(dur: Duration) -> libc::timespec {
        libc::timespec {
            tv_sec: dur.as_secs() as libc::time_t,
            tv_nsec: (dur.subsec_nanos() as TvUsecType).into(),
        }
    }

    fn make_in6_addr(segments: [u16; 8]) -> In6Addr {
        #[allow(deprecated)]
        let mut val: In6Addr = unsafe { mem::uninitialized() };
        val.s6_addr = unsafe {
            mem::transmute([
                htons(segments[0]),
                htons(segments[1]),
                htons(segments[2]),
                htons(segments[3]),
                htons(segments[4]),
                htons(segments[5]),
                htons(segments[6]),
                htons(segments[7]),
            ])
        };
        val
    }

    pub fn addr_to_sockaddr(addr: SocketAddr, storage: &mut SockAddrStorage) -> SockLen {
        unsafe {
            let len = match addr {
                SocketAddr::V4(sa) => {
                    let ip_addr = sa.ip();
                    let octets = ip_addr.octets();
                    let inaddr = super::mk_inaddr(u32::from_be(
                        ((octets[0] as u32) << 24)
                            | ((octets[1] as u32) << 16)
                            | ((octets[2] as u32) << 8)
                            | (octets[3] as u32),
                    ));
                    let storage = storage as *mut _ as *mut SockAddrIn;
                    (*storage).sin_family = AF_INET as SockAddrFamily;
                    (*storage).sin_port = htons(addr.port());
                    (*storage).sin_addr = inaddr;
                    mem::size_of::<SockAddrIn>()
                }
                SocketAddr::V6(sa) => {
                    let ip_addr = sa.ip();
                    let segments = ip_addr.segments();
                    let inaddr = make_in6_addr(segments);
                    let storage = storage as *mut _ as *mut SockAddrIn6;
                    (*storage).sin6_family = AF_INET6 as SockAddrFamily6;
                    (*storage).sin6_port = htons(addr.port());
                    (*storage).sin6_addr = inaddr;
                    (*storage).sin6_scope_id = sa.scope_id();
                    mem::size_of::<SockAddrIn6>()
                }
            };

            len as SockLen
        }
    }

    pub fn sockaddr_to_addr(storage: &SockAddrStorage, len: usize) -> io::Result<SocketAddr> {
        match storage.ss_family as libc::c_int {
            AF_INET => {
                assert!(len as usize >= mem::size_of::<SockAddrIn>());
                let storage: &SockAddrIn = unsafe { mem::transmute(storage) };
                let ip = super::ipv4_addr(storage.sin_addr);
                let a = (ip >> 24) as u8;
                let b = (ip >> 16) as u8;
                let c = (ip >> 8) as u8;
                let d = ip as u8;
                let sockaddrv4 =
                    SocketAddrV4::new(Ipv4Addr::new(a, b, c, d), ntohs(storage.sin_port));
                Ok(SocketAddr::V4(sockaddrv4))
            }
            AF_INET6 => {
                assert!(len as usize >= mem::size_of::<SockAddrIn6>());
                let storage: &SockAddrIn6 = unsafe { mem::transmute(storage) };
                let arr: [u16; 8] = unsafe { mem::transmute(storage.sin6_addr.s6_addr) };
                let a = ntohs(arr[0]);
                let b = ntohs(arr[1]);
                let c = ntohs(arr[2]);
                let d = ntohs(arr[3]);
                let e = ntohs(arr[4]);
                let f = ntohs(arr[5]);
                let g = ntohs(arr[6]);
                let h = ntohs(arr[7]);
                let ip = Ipv6Addr::new(a, b, c, d, e, f, g, h);
                Ok(SocketAddr::V6(SocketAddrV6::new(
                    ip,
                    ntohs(storage.sin6_port),
                    u32::from_be(storage.sin6_flowinfo),
                    storage.sin6_scope_id,
                )))
            }
            _ => Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "expected IPv4 or IPv6 socket",
            )),
        }
    }
}

use self::public::*;

#[inline(always)]
pub fn ipv4_addr(addr: InAddr) -> u32 {
    (addr.s_addr as u32).to_be()
}

#[inline(always)]
pub fn mk_inaddr(addr: u32) -> InAddr {
    InAddr { s_addr: addr }
}

pub unsafe fn sendto(
    socket: CSocket,
    buf: Buf,
    len: BufLen,
    flags: libc::c_int,
    addr: *const SockAddr,
    addrlen: SockLen,
) -> CouldFail {
    libc::sendto(socket, buf, len, flags, addr, addrlen)
}

pub unsafe fn recvfrom(
    socket: CSocket,
    buf: MutBuf,
    len: BufLen,
    flags: libc::c_int,
    addr: *mut SockAddr,
    addrlen: *mut SockLen,
) -> CouldFail {
    libc::recvfrom(socket, buf, len, flags, addr, addrlen)
}

#[inline]
pub fn retry<F>(f: &mut F) -> libc::ssize_t
where
    F: FnMut() -> libc::ssize_t,
{
    loop {
        let ret = f();
        if ret != -1 || errno() as isize != libc::EINTR as isize {
            return ret;
        }
    }
}

fn errno() -> i32 {
    io::Error::last_os_error().raw_os_error().unwrap()
}

#[cfg(test)]
mod tests {
    use duration_to_timespec;
    use std::time::Duration;
    use timespec_to_duration;

    #[test]
    fn test_duration_to_timespec() {
        let d1 = Duration::new(1, 0);
        let d2 = Duration::from_millis(500);

        let t1 = duration_to_timespec(d1);
        let t2 = duration_to_timespec(d2);

        let r1 = timespec_to_duration(t1);
        let r2 = timespec_to_duration(t2);

        assert_eq!(d1, r1);
        assert_eq!(d2, r2);
    }
}
<commit_msg>psys_net: change TvUsecType to long on NetBSD<commit_after>extern crate libc;

use super::{htons, ntohs};
use std::io;

pub mod public {

    use super::libc;
    use super::{htons, ntohs};
    use std::io;
    use std::mem;
    use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
    use std::time::Duration;

    pub type CSocket = libc::c_int;
    pub type Buf = *const libc::c_void;
    pub type MutBuf = *mut libc::c_void;
    pub type BufLen = libc::size_t;
    pub type CouldFail = libc::ssize_t;
    pub type SockLen = libc::socklen_t;
    pub type MutSockLen = *mut libc::socklen_t;
    pub type SockAddr = libc::sockaddr;
    pub type SockAddrIn = libc::sockaddr_in;
    pub type SockAddrIn6 = libc::sockaddr_in6;
    pub type SockAddrStorage = libc::sockaddr_storage;
    pub type SockAddrFamily = libc::sa_family_t;
    pub type SockAddrFamily6 = libc::sa_family_t;
    pub type InAddr = libc::in_addr;
    pub type In6Addr = libc::in6_addr;

    #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "netbsd")))]
    pub type TvUsecType = libc::c_long;
    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
    pub type TvUsecType = libc::c_int;

    pub const AF_INET: libc::c_int = libc::AF_INET;
    pub const AF_INET6: libc::c_int = libc::AF_INET6;
    pub const SOCK_RAW: libc::c_int = libc::SOCK_RAW;

    pub const SOL_SOCKET: libc::c_int = libc::SOL_SOCKET;
    pub const SO_RCVTIMEO: libc::c_int = libc::SO_RCVTIMEO;
    pub const SO_SNDTIMEO: libc::c_int = libc::SO_SNDTIMEO;

    pub const IPPROTO_IP: libc::c_int = libc::IPPROTO_IP;
    pub const IP_HDRINCL: libc::c_int = libc::IP_HDRINCL;
    pub const IP_TTL: libc::c_int = libc::IP_TTL;

    pub use super::libc::{IFF_BROADCAST, IFF_LOOPBACK, IFF_MULTICAST, IFF_POINTOPOINT, IFF_UP};

    pub const INVALID_SOCKET: CSocket = -1;

    pub unsafe fn close(sock: CSocket) {
        let _ = libc::close(sock);
    }

    pub unsafe fn socket(af: libc::c_int, sock: libc::c_int, proto: libc::c_int) -> CSocket {
        libc::socket(af, sock, proto)
    }

    pub unsafe fn getsockopt(
        socket: CSocket,
        level: libc::c_int,
        name: libc::c_int,
        value: MutBuf,
        option_len: MutSockLen,
    ) -> libc::c_int {
        libc::getsockopt(socket, level, name, value, option_len)
    }

    pub unsafe fn setsockopt(
        socket: CSocket,
        level: libc::c_int,
        name: libc::c_int,
        value: Buf,
        option_len: SockLen,
    ) -> libc::c_int {
        libc::setsockopt(socket, level, name, value, option_len)
    }

    /// Convert a platform specific `timeval` into a Duration.
    pub fn timeval_to_duration(tv: libc::timeval) -> Duration {
        Duration::new(tv.tv_sec as u64, (tv.tv_usec as u32) * 1000)
    }

    /// Convert a Duration into a platform specific `timeval`.
    pub fn duration_to_timeval(dur: Duration) -> libc::timeval {
        libc::timeval {
            tv_sec: dur.as_secs() as libc::time_t,
            tv_usec: dur.subsec_micros() as TvUsecType,
        }
    }

    /// Convert a platform specific `timespec` into a Duration.
    pub fn timespec_to_duration(ts: libc::timespec) -> Duration {
        Duration::new(ts.tv_sec as u64, ts.tv_nsec as u32)
    }

    /// Convert a Duration into a platform specific `timespec`.
    pub fn duration_to_timespec(dur: Duration) -> libc::timespec {
        libc::timespec {
            tv_sec: dur.as_secs() as libc::time_t,
            tv_nsec: (dur.subsec_nanos() as TvUsecType).into(),
        }
    }

    fn make_in6_addr(segments: [u16; 8]) -> In6Addr {
        #[allow(deprecated)]
        let mut val: In6Addr = unsafe { mem::uninitialized() };
        val.s6_addr = unsafe {
            mem::transmute([
                htons(segments[0]),
                htons(segments[1]),
                htons(segments[2]),
                htons(segments[3]),
                htons(segments[4]),
                htons(segments[5]),
                htons(segments[6]),
                htons(segments[7]),
            ])
        };
        val
    }

    pub fn addr_to_sockaddr(addr: SocketAddr, storage: &mut SockAddrStorage) -> SockLen {
        unsafe {
            let len = match addr {
                SocketAddr::V4(sa) => {
                    let ip_addr = sa.ip();
                    let octets = ip_addr.octets();
                    let inaddr = super::mk_inaddr(u32::from_be(
                        ((octets[0] as u32) << 24)
                            | ((octets[1] as u32) << 16)
                            | ((octets[2] as u32) << 8)
                            | (octets[3] as u32),
                    ));
                    let storage = storage as *mut _ as *mut SockAddrIn;
                    (*storage).sin_family = AF_INET as SockAddrFamily;
                    (*storage).sin_port = htons(addr.port());
                    (*storage).sin_addr = inaddr;
                    mem::size_of::<SockAddrIn>()
                }
                SocketAddr::V6(sa) => {
                    let ip_addr = sa.ip();
                    let segments = ip_addr.segments();
                    let inaddr = make_in6_addr(segments);
                    let storage = storage as *mut _ as *mut SockAddrIn6;
                    (*storage).sin6_family = AF_INET6 as SockAddrFamily6;
                    (*storage).sin6_port = htons(addr.port());
                    (*storage).sin6_addr = inaddr;
                    (*storage).sin6_scope_id = sa.scope_id();
                    mem::size_of::<SockAddrIn6>()
                }
            };

            len as SockLen
        }
    }

    pub fn sockaddr_to_addr(storage: &SockAddrStorage, len: usize) -> io::Result<SocketAddr> {
        match storage.ss_family as libc::c_int {
            AF_INET => {
                assert!(len as usize >= mem::size_of::<SockAddrIn>());
                let storage: &SockAddrIn = unsafe { mem::transmute(storage) };
                let ip = super::ipv4_addr(storage.sin_addr);
                let a = (ip >> 24) as u8;
                let b = (ip >> 16) as u8;
                let c = (ip >> 8) as u8;
                let d = ip as u8;
                let sockaddrv4 =
                    SocketAddrV4::new(Ipv4Addr::new(a, b, c, d), ntohs(storage.sin_port));
                Ok(SocketAddr::V4(sockaddrv4))
            }
            AF_INET6 => {
                assert!(len as usize >= mem::size_of::<SockAddrIn6>());
                let storage: &SockAddrIn6 = unsafe { mem::transmute(storage) };
                let arr: [u16; 8] = unsafe { mem::transmute(storage.sin6_addr.s6_addr) };
                let a = ntohs(arr[0]);
                let b = ntohs(arr[1]);
                let c = ntohs(arr[2]);
                let d = ntohs(arr[3]);
                let e = ntohs(arr[4]);
                let f = ntohs(arr[5]);
                let g = ntohs(arr[6]);
                let h = ntohs(arr[7]);
                let ip = Ipv6Addr::new(a, b, c, d, e, f, g, h);
                Ok(SocketAddr::V6(SocketAddrV6::new(
                    ip,
                    ntohs(storage.sin6_port),
                    u32::from_be(storage.sin6_flowinfo),
                    storage.sin6_scope_id,
                )))
            }
            _ => Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "expected IPv4 or IPv6 socket",
            )),
        }
    }
}

use self::public::*;

#[inline(always)]
pub fn ipv4_addr(addr: InAddr) -> u32 {
    (addr.s_addr as u32).to_be()
}

#[inline(always)]
pub fn mk_inaddr(addr: u32) -> InAddr {
    InAddr { s_addr: addr }
}

pub unsafe fn sendto(
    socket: CSocket,
    buf: Buf,
    len: BufLen,
    flags: libc::c_int,
    addr: *const SockAddr,
    addrlen: SockLen,
) -> CouldFail {
    libc::sendto(socket, buf, len, flags, addr, addrlen)
}

pub unsafe fn recvfrom(
    socket: CSocket,
    buf: MutBuf,
    len: BufLen,
    flags: libc::c_int,
    addr: *mut SockAddr,
    addrlen: *mut SockLen,
) -> CouldFail {
    libc::recvfrom(socket, buf, len, flags, addr, addrlen)
}

#[inline]
pub fn retry<F>(f: &mut F) -> libc::ssize_t
where
    F: FnMut() -> libc::ssize_t,
{
    loop {
        let ret = f();
        if ret != -1 || errno() as isize != libc::EINTR as isize {
            return ret;
        }
    }
}

fn errno() -> i32 {
    io::Error::last_os_error().raw_os_error().unwrap()
}

#[cfg(test)]
mod tests {
    use duration_to_timespec;
    use std::time::Duration;
    use timespec_to_duration;

    #[test]
    fn test_duration_to_timespec() {
        let d1 = Duration::new(1, 0);
        let d2 = Duration::from_millis(500);

        let t1 = duration_to_timespec(d1);
        let t2 = duration_to_timespec(d2);

        let r1 = timespec_to_duration(t1);
        let r2 = timespec_to_duration(t2);

        assert_eq!(d1, r1);
        assert_eq!(d2, r2);
    }
}
<|endoftext|>