<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 rustc::hir::def_id::DefId;
use rustc::hir;
use rustc::mir::visit::{Visitor, LvalueContext};
use rustc::mir;
use rustc::traits::Reveal;
use rustc::ty::layout::Layout;
use rustc::ty::{subst, self};

use error::{EvalResult, EvalError};
use eval_context::{EvalContext, StackPopCleanup};
use lvalue::{Global, GlobalId, Lvalue};
use value::{Value, PrimVal};
use memory::Pointer;
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() {
            if let Some((instance, ptr)) = self.memory.fetch_tls_dtor() {
                trace!("Running TLS dtor {:?} on {:?}", instance, ptr);
                // TODO: Potientially, this has to support all the other possible instances? See eval_fn_call in terminator/mod.rs
                let mir = self.load_mir(instance.def)?;
                self.push_stack_frame(
                    instance,
                    mir.span,
                    mir,
                    Lvalue::from_ptr(Pointer::zst_ptr()),
                    StackPopCleanup::None,
                )?;
                let arg_local = self.frame().mir.args_iter().next().ok_or(EvalError::AbiViolation("TLS dtor does not take enough arguments.".to_owned()))?;
                let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
                let ty = self.tcx.mk_mut_ptr(self.tcx.types.u8);
                self.write_value(Value::ByVal(PrimVal::Ptr(ptr)), dest, ty)?;
                return Ok(true);
            }
            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,
                instance: self.frame().instance,
                ecx: self,
                mir,
                new_constants: &mut new,
            }.visit_statement(block, stmt, mir::Location { block, statement_index: stmt_id });
            // if ConstantExtractor added new frames, we don't execute anything here
            // but await the next call to step
            if new? == 0 {
                self.statement(stmt)?;
            }
            return Ok(true);
        }

        let terminator = basic_block.terminator();
        let mut new = Ok(0);
        ConstantExtractor {
            span: terminator.source_info.span,
            instance: self.frame().instance,
            ecx: self,
            mir,
            new_constants: &mut new,
        }.visit_terminator(block, terminator, mir::Location { block, statement_index: stmt_id });
        // if ConstantExtractor added new frames, we don't execute anything here
        // but await the next call to step
        if new? == 0 {
            self.terminator(terminator)?;
        }
        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, .. } => {
                        // FIXME: I (oli-obk) think we need to check the
                        // `dest_ty` for the variant's discriminant and write
                        // instead of the variant index
                        // We don't have any tests actually going through these lines
                        let discr_ty = discr.to_ty(&self.tcx, false);
                        let discr_lval = self.lvalue_field(dest, 0, dest_ty, discr_ty)?;

                        self.write_value(Value::ByVal(PrimVal::Bytes(variant_index as u128)), discr_lval, discr_ty)?;
                    }

                    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),
                }
            }

            // Mark locals as dead or alive.
            StorageLive(ref lvalue) | StorageDead(ref lvalue)=> {
                let (frame, local) = match self.eval_lvalue(lvalue)? {
                    Lvalue::Local{ frame, local, field: None } if self.stack.len() == frame+1 => (frame, local),
                    _ => return Err(EvalError::Unimplemented("Storage annotations must refer to locals of the topmost stack frame.".to_owned())) // FIXME maybe this should get its own error type
                };
                let old_val = match stmt.kind {
                    StorageLive(_) => self.stack[frame].storage_live(local)?,
                    StorageDead(_) =>  self.stack[frame].storage_dead(local)?,
                    _ => bug!("We already checked that we are a storage stmt")
                };
                self.deallocate_local(old_val)?;
            }

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

            InlineAsm { .. } => return Err(EvalError::InlineAsm),
        }

        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: &'tcx mir::Mir<'tcx>,
    instance: ty::Instance<'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,
        shared: bool,
    ) {
        let instance = self.ecx.resolve_associated_const(def_id, substs);
        let cid = GlobalId { instance, promoted: None };
        if self.ecx.globals.contains_key(&cid) {
            return;
        }
        if self.ecx.tcx.has_attr(def_id, "linkage") {
            trace!("Initializing an extern global with NULL");
            self.ecx.globals.insert(cid, Global::initialized(self.ecx.tcx.type_of(def_id), Value::ByVal(PrimVal::Ptr(Pointer::from_int(0))), !shared));
            return;
        }
        self.try(|this| {
            let mir = this.ecx.load_mir(instance.def)?;
            this.ecx.globals.insert(cid, Global::uninitialized(mir.return_ty));
            let mutable = !shared ||
                !mir.return_ty.is_freeze(
                    this.ecx.tcx,
                    ty::ParamEnv::empty(Reveal::All),
                    span);
            let cleanup = StackPopCleanup::MarkStatic(mutable);
            let name = ty::tls::with(|tcx| tcx.item_path_str(def_id));
            trace!("pushing stack frame for global: {}", name);
            this.ecx.push_stack_frame(
                instance,
                span,
                mir,
                Lvalue::Global(cid),
                cleanup,
            )
        });
    }

    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 } => {
                self.global_item(def_id, substs, constant.span, true);
            },
            mir::Literal::Promoted { index } => {
                let cid = GlobalId {
                    instance: self.instance,
                    promoted: Some(index),
                };
                if self.ecx.globals.contains_key(&cid) {
                    return;
                }
                let mir = &self.mir.promoted[index];
                self.try(|this| {
                    let ty = this.ecx.monomorphize(mir.return_ty, this.instance.substs);
                    this.ecx.globals.insert(cid, Global::uninitialized(ty));
                    trace!("pushing stack frame for {:?}", index);
                    this.ecx.push_stack_frame(this.instance,
                                              constant.span,
                                              mir,
                                              Lvalue::Global(cid),
                                              StackPopCleanup::MarkStatic(false),
                    )
                });
            }
        }
    }

    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(ref static_) = *lvalue {
            let def_id = static_.def_id;
            let substs = self.ecx.tcx.intern_substs(&[]);
            let span = self.span;
            if let Some(node_item) = self.ecx.tcx.hir.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.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>handle EndRegion as no-op<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 rustc::hir::def_id::DefId;
use rustc::hir;
use rustc::mir::visit::{Visitor, LvalueContext};
use rustc::mir;
use rustc::traits::Reveal;
use rustc::ty::layout::Layout;
use rustc::ty::{subst, self};

use error::{EvalResult, EvalError};
use eval_context::{EvalContext, StackPopCleanup};
use lvalue::{Global, GlobalId, Lvalue};
use value::{Value, PrimVal};
use memory::Pointer;
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() {
            if let Some((instance, ptr)) = self.memory.fetch_tls_dtor() {
                trace!("Running TLS dtor {:?} on {:?}", instance, ptr);
                // TODO: Potientially, this has to support all the other possible instances? See eval_fn_call in terminator/mod.rs
                let mir = self.load_mir(instance.def)?;
                self.push_stack_frame(
                    instance,
                    mir.span,
                    mir,
                    Lvalue::from_ptr(Pointer::zst_ptr()),
                    StackPopCleanup::None,
                )?;
                let arg_local = self.frame().mir.args_iter().next().ok_or(EvalError::AbiViolation("TLS dtor does not take enough arguments.".to_owned()))?;
                let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
                let ty = self.tcx.mk_mut_ptr(self.tcx.types.u8);
                self.write_value(Value::ByVal(PrimVal::Ptr(ptr)), dest, ty)?;
                return Ok(true);
            }
            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,
                instance: self.frame().instance,
                ecx: self,
                mir,
                new_constants: &mut new,
            }.visit_statement(block, stmt, mir::Location { block, statement_index: stmt_id });
            // if ConstantExtractor added new frames, we don't execute anything here
            // but await the next call to step
            if new? == 0 {
                self.statement(stmt)?;
            }
            return Ok(true);
        }

        let terminator = basic_block.terminator();
        let mut new = Ok(0);
        ConstantExtractor {
            span: terminator.source_info.span,
            instance: self.frame().instance,
            ecx: self,
            mir,
            new_constants: &mut new,
        }.visit_terminator(block, terminator, mir::Location { block, statement_index: stmt_id });
        // if ConstantExtractor added new frames, we don't execute anything here
        // but await the next call to step
        if new? == 0 {
            self.terminator(terminator)?;
        }
        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, .. } => {
                        // FIXME: I (oli-obk) think we need to check the
                        // `dest_ty` for the variant's discriminant and write
                        // instead of the variant index
                        // We don't have any tests actually going through these lines
                        let discr_ty = discr.to_ty(&self.tcx, false);
                        let discr_lval = self.lvalue_field(dest, 0, dest_ty, discr_ty)?;

                        self.write_value(Value::ByVal(PrimVal::Bytes(variant_index as u128)), discr_lval, discr_ty)?;
                    }

                    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),
                }
            }

            // Mark locals as dead or alive.
            StorageLive(ref lvalue) | StorageDead(ref lvalue)=> {
                let (frame, local) = match self.eval_lvalue(lvalue)? {
                    Lvalue::Local{ frame, local, field: None } if self.stack.len() == frame+1 => (frame, local),
                    _ => return Err(EvalError::Unimplemented("Storage annotations must refer to locals of the topmost stack frame.".to_owned())) // FIXME maybe this should get its own error type
                };
                let old_val = match stmt.kind {
                    StorageLive(_) => self.stack[frame].storage_live(local)?,
                    StorageDead(_) =>  self.stack[frame].storage_dead(local)?,
                    _ => bug!("We already checked that we are a storage stmt")
                };
                self.deallocate_local(old_val)?;
            }

            EndRegion(..) => {}

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

            InlineAsm { .. } => return Err(EvalError::InlineAsm),
        }

        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: &'tcx mir::Mir<'tcx>,
    instance: ty::Instance<'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,
        shared: bool,
    ) {
        let instance = self.ecx.resolve_associated_const(def_id, substs);
        let cid = GlobalId { instance, promoted: None };
        if self.ecx.globals.contains_key(&cid) {
            return;
        }
        if self.ecx.tcx.has_attr(def_id, "linkage") {
            trace!("Initializing an extern global with NULL");
            self.ecx.globals.insert(cid, Global::initialized(self.ecx.tcx.type_of(def_id), Value::ByVal(PrimVal::Ptr(Pointer::from_int(0))), !shared));
            return;
        }
        self.try(|this| {
            let mir = this.ecx.load_mir(instance.def)?;
            this.ecx.globals.insert(cid, Global::uninitialized(mir.return_ty));
            let mutable = !shared ||
                !mir.return_ty.is_freeze(
                    this.ecx.tcx,
                    ty::ParamEnv::empty(Reveal::All),
                    span);
            let cleanup = StackPopCleanup::MarkStatic(mutable);
            let name = ty::tls::with(|tcx| tcx.item_path_str(def_id));
            trace!("pushing stack frame for global: {}", name);
            this.ecx.push_stack_frame(
                instance,
                span,
                mir,
                Lvalue::Global(cid),
                cleanup,
            )
        });
    }

    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 } => {
                self.global_item(def_id, substs, constant.span, true);
            },
            mir::Literal::Promoted { index } => {
                let cid = GlobalId {
                    instance: self.instance,
                    promoted: Some(index),
                };
                if self.ecx.globals.contains_key(&cid) {
                    return;
                }
                let mir = &self.mir.promoted[index];
                self.try(|this| {
                    let ty = this.ecx.monomorphize(mir.return_ty, this.instance.substs);
                    this.ecx.globals.insert(cid, Global::uninitialized(ty));
                    trace!("pushing stack frame for {:?}", index);
                    this.ecx.push_stack_frame(this.instance,
                                              constant.span,
                                              mir,
                                              Lvalue::Global(cid),
                                              StackPopCleanup::MarkStatic(false),
                    )
                });
            }
        }
    }

    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(ref static_) = *lvalue {
            let def_id = static_.def_id;
            let substs = self.ecx.tcx.intern_substs(&[]);
            let span = self.span;
            if let Some(node_item) = self.ecx.tcx.hir.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.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 Capture;

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_re = ^ "hi" }

#[test]
fn literal() {
    assert_eq!(literal_re("hi").unwrap()[0].end, 2);
    assert!(literal_re("ho").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_star_re = ^ "hi"* }

#[test]
fn literal_star() {
    assert!(literal_star_re("hihihi").unwrap()[0].end == 6);
    assert!(literal_star_re("hihiho").unwrap()[0].end == 4);
    assert!(literal_star_re("hihohi").unwrap()[0].end == 2);
    assert!(literal_star_re("hohihi").unwrap()[0].end == 0);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_plus_re = ^ "hi"+ }

#[test]
fn literal_plus() {
    assert!(literal_plus_re("hihihi").unwrap()[0].end == 6);
    assert!(literal_plus_re("hihiho").unwrap()[0].end == 4);
    assert!(literal_plus_re("hihohi").unwrap()[0].end == 2);
    assert!(literal_plus_re("hohihi").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_literal_re = ^ "hi" "ho"}

#[test]
fn literal_literal() {
    assert!(literal_literal_re("hihihi").is_none());
    assert!(literal_literal_re("hihiho").is_none());
    assert!(literal_literal_re("hihohi").unwrap()[0].end == 4);
    assert!(literal_literal_re("hohihi").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_star_literal_re = ^ ("hi"*) "ho"}

#[test]
fn literal_star_literal() {
    assert!(literal_star_literal_re("hihihi").is_none());
    assert!(literal_star_literal_re("hihiho").is_some());
    assert!(literal_star_literal_re("hihiho").unwrap()[1].end == 4);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { star_plus_re = ^ ("hi"*) ("hi"+) }

#[test]
fn star_plus() {
    assert_eq!(star_plus_re("hihihi").unwrap(), vec![
        Capture { text: "hihihi", start: 0, end: 6 },
        Capture { text: "hihihi", start: 0, end: 4 },
        Capture { text: "hihihi", start: 4, end: 6 }
        ]);

    assert_eq!(star_plus_re("hi").unwrap(), vec![
        Capture { text: "hi", start: 0, end: 2 },
        Capture { text: "hi", start: 0, end: 0 },
        Capture { text: "hi", start: 0, end: 2 }
        ]);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { star_min_plus_re = ^ ("hi"*?) ("hi"+) }

#[test]
fn star_min_plus() {
    assert_eq!(star_min_plus_re("hihihi").unwrap(), vec![
        Capture { text: "hihihi", start: 0, end: 6 },
        Capture { text: "hihihi", start: 0, end: 0 },
        Capture { text: "hihihi", start: 0, end: 6 }
        ]);

    assert_eq!(star_min_plus_re("hi").unwrap(), vec![
        Capture { text: "hi", start: 0, end: 2 },
        Capture { text: "hi", start: 0, end: 0 },
        Capture { text: "hi", start: 0, end: 2 }
        ]);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { star_min_hi_plus_ho_end_re = ^ (['a' 'c']*?) (['b' 'c']+) END }

#[test]
fn star_min_hi_plus_ho() {
    assert_eq!(star_min_hi_plus_ho_end_re("aacbbc").unwrap(), vec![
        Capture { text: "aacbbc", start: 0, end: 6 },
        Capture { text: "aacbbc", start: 0, end: 2 },
        Capture { text: "aacbbc", start: 2, end: 6 },
        ]);

    assert_eq!(star_min_hi_plus_ho_end_re("aacabbc").unwrap(), vec![
        Capture { text: "aacabbc", start: 0, end: 7 },
        Capture { text: "aacabbc", start: 0, end: 4 },
        Capture { text: "aacabbc", start: 4, end: 7 },
        ]);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { plus_plus_re = ^ ("hi"+) ("hi"+) }

#[test]
fn plus_plus() {
    assert_eq!(plus_plus_re("hihihi").unwrap(), vec![
        Capture { text: "hihihi", start: 0, end: 6 },
        Capture { text: "hihihi", start: 0, end: 4 },
        Capture { text: "hihihi", start: 4, end: 6 }
        ]);

    assert!(plus_plus_re("hi").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { paren_no_cap_re = ^ (?:"hi" "hi")+ ("hi"+) }

#[test]
fn paren_no_cap() {
    assert_eq!(paren_no_cap_re("hihihi").unwrap(), vec![
        Capture { text: "hihihi", start: 0, end: 6 },
        Capture { text: "hihihi", start: 4, end: 6 }
        ]);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { char_range_re = ^ ['a' 'b' 'c']+ }

#[test]
fn char_range() {
    assert!(char_range_re("abc").is_some());
    assert!(char_range_re("def").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { inv_char_range_re = ^ [^ 'a' 'b' 'c']+ }

#[test]
fn inv_char_range() {
    assert!(inv_char_range_re("abc").is_none());
    assert!(inv_char_range_re("def").is_some());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { end_re = ^ ['a' 'b' 'c']* END }

#[test]
fn end() {
    assert!(end_re("").is_some());
    assert!(end_re("abcabc").is_some());
    assert!(end_re("abcabcd").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { digit_re = ^ [:digit:]* END }

#[test]
fn digit() {
    assert!(digit_re("0123").is_some());
    assert!(digit_re("0 123").is_none());
    assert!(digit_re("abc").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { digit_or_space_re = ^ [:digit: :space:]* END }

#[test]
fn digit_or_space() {
    assert!(digit_or_space_re("0123").is_some());
    assert!(digit_or_space_re("0 123").is_some());
    assert!(digit_or_space_re("abc").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { dot_re = ^ .* END }

#[test]
fn dot() {
    assert!(dot_re("0123").is_some());
    assert!(dot_re("0 123").is_some());
    assert!(dot_re("abc").is_some());
    assert!(dot_re("").is_some());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { missing_anchor_re = "a"+ }

#[test]
fn missing_anchor() {
    // contains an 'a':
    assert!(missing_anchor_re("gjoijqpavadsaf").is_some());

    // does not:
    assert!(missing_anchor_re("gjoijqpvdsf").is_none());
}

<commit_msg>add uri test from http://lh3lh3.users.sourceforge.net/reb.shtml<commit_after>use Capture;

fn to_captures<'text>(c: Vec<Capture<'text>>) -> Vec<&'text str> {
    c.iter()
     .map(|c| c.to_str())
     .collect()
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_re = ^ "hi" }

#[test]
fn literal() {
    assert_eq!(literal_re("hi").unwrap()[0].end, 2);
    assert!(literal_re("ho").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_star_re = ^ "hi"* }

#[test]
fn literal_star() {
    assert!(literal_star_re("hihihi").unwrap()[0].end == 6);
    assert!(literal_star_re("hihiho").unwrap()[0].end == 4);
    assert!(literal_star_re("hihohi").unwrap()[0].end == 2);
    assert!(literal_star_re("hohihi").unwrap()[0].end == 0);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_plus_re = ^ "hi"+ }

#[test]
fn literal_plus() {
    assert!(literal_plus_re("hihihi").unwrap()[0].end == 6);
    assert!(literal_plus_re("hihiho").unwrap()[0].end == 4);
    assert!(literal_plus_re("hihohi").unwrap()[0].end == 2);
    assert!(literal_plus_re("hohihi").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_literal_re = ^ "hi" "ho"}

#[test]
fn literal_literal() {
    assert!(literal_literal_re("hihihi").is_none());
    assert!(literal_literal_re("hihiho").is_none());
    assert!(literal_literal_re("hihohi").unwrap()[0].end == 4);
    assert!(literal_literal_re("hohihi").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { literal_star_literal_re = ^ ("hi"*) "ho"}

#[test]
fn literal_star_literal() {
    assert!(literal_star_literal_re("hihihi").is_none());
    assert!(literal_star_literal_re("hihiho").is_some());
    assert!(literal_star_literal_re("hihiho").unwrap()[1].end == 4);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { star_plus_re = ^ ("hi"*) ("hi"+) }

#[test]
fn star_plus() {
    assert_eq!(star_plus_re("hihihi").unwrap(), vec![
        Capture { text: "hihihi", start: 0, end: 6 },
        Capture { text: "hihihi", start: 0, end: 4 },
        Capture { text: "hihihi", start: 4, end: 6 }
        ]);

    assert_eq!(star_plus_re("hi").unwrap(), vec![
        Capture { text: "hi", start: 0, end: 2 },
        Capture { text: "hi", start: 0, end: 0 },
        Capture { text: "hi", start: 0, end: 2 }
        ]);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { star_min_plus_re = ^ ("hi"*?) ("hi"+) }

#[test]
fn star_min_plus() {
    assert_eq!(star_min_plus_re("hihihi").unwrap(), vec![
        Capture { text: "hihihi", start: 0, end: 6 },
        Capture { text: "hihihi", start: 0, end: 0 },
        Capture { text: "hihihi", start: 0, end: 6 }
        ]);

    assert_eq!(star_min_plus_re("hi").unwrap(), vec![
        Capture { text: "hi", start: 0, end: 2 },
        Capture { text: "hi", start: 0, end: 0 },
        Capture { text: "hi", start: 0, end: 2 }
        ]);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { star_min_hi_plus_ho_end_re = ^ (['a' 'c']*?) (['b' 'c']+) END }

#[test]
fn star_min_hi_plus_ho() {
    assert_eq!(star_min_hi_plus_ho_end_re("aacbbc").unwrap(), vec![
        Capture { text: "aacbbc", start: 0, end: 6 },
        Capture { text: "aacbbc", start: 0, end: 2 },
        Capture { text: "aacbbc", start: 2, end: 6 },
        ]);

    assert_eq!(star_min_hi_plus_ho_end_re("aacabbc").unwrap(), vec![
        Capture { text: "aacabbc", start: 0, end: 7 },
        Capture { text: "aacabbc", start: 0, end: 4 },
        Capture { text: "aacabbc", start: 4, end: 7 },
        ]);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { plus_plus_re = ^ ("hi"+) ("hi"+) }

#[test]
fn plus_plus() {
    assert_eq!(plus_plus_re("hihihi").unwrap(), vec![
        Capture { text: "hihihi", start: 0, end: 6 },
        Capture { text: "hihihi", start: 0, end: 4 },
        Capture { text: "hihihi", start: 4, end: 6 }
        ]);

    assert!(plus_plus_re("hi").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { paren_no_cap_re = ^ (?:"hi" "hi")+ ("hi"+) }

#[test]
fn paren_no_cap() {
    assert_eq!(paren_no_cap_re("hihihi").unwrap(), vec![
        Capture { text: "hihihi", start: 0, end: 6 },
        Capture { text: "hihihi", start: 4, end: 6 }
        ]);
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { char_range_re = ^ ['a' 'b' 'c']+ }

#[test]
fn char_range() {
    assert!(char_range_re("abc").is_some());
    assert!(char_range_re("def").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { inv_char_range_re = ^ [^ 'a' 'b' 'c']+ }

#[test]
fn inv_char_range() {
    assert!(inv_char_range_re("abc").is_none());
    assert!(inv_char_range_re("def").is_some());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { end_re = ^ ['a' 'b' 'c']* END }

#[test]
fn end() {
    assert!(end_re("").is_some());
    assert!(end_re("abcabc").is_some());
    assert!(end_re("abcabcd").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { digit_re = ^ [:digit:]* END }

#[test]
fn digit() {
    assert!(digit_re("0123").is_some());
    assert!(digit_re("0 123").is_none());
    assert!(digit_re("abc").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { digit_or_space_re = ^ [:digit: :space:]* END }

#[test]
fn digit_or_space() {
    assert!(digit_or_space_re("0123").is_some());
    assert!(digit_or_space_re("0 123").is_some());
    assert!(digit_or_space_re("abc").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { dot_re = ^ .* END }

#[test]
fn dot() {
    assert!(dot_re("0123").is_some());
    assert!(dot_re("0 123").is_some());
    assert!(dot_re("abc").is_some());
    assert!(dot_re("").is_some());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! { missing_anchor_re = "a"+ }

#[test]
fn missing_anchor() {
    // contains an 'a':
    assert!(missing_anchor_re("gjoijqpavadsaf").is_some());

    // does not:
    assert!(missing_anchor_re("gjoijqpvdsf").is_none());
}

///////////////////////////////////////////////////////////////////////////

rusty_regex! {
    uri_re =
        (['a'-'z' 'A'-'Z']['a'-'z' 'A'-'Z' '0'-'9']*) // e.g., http
        "://"
        ([^' ' '/']+)
        ("/" [^' ']*)?
}

#[test]
fn uri() {
    assert_eq!(to_captures(uri_re("The url is http://foo/bar/baz so go click on it!").unwrap()),
               vec!["http://foo/bar/baz", "http", "foo", "/bar/baz"]);
}

<|endoftext|>


<commit_before>use ::{Player, RPS, Outcome};

pub trait Unit: Copy + Clone {
    fn owner(&self) -> Player;
    fn rps(&self) -> Option<RPS>;
    fn attack(&self, opponent: &Self) -> Option<Outcome> {
        match (self.rps(), opponent.rps()) {
            (Some(attacker), Some(defender)) => Some(attacker.attack(defender)),
            _ => None
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct GeneralUnit {
    pub rps: RPS,
    pub owner: Player,
    pub visible: bool,
}

impl GeneralUnit {
    pub fn new(rps: RPS, owner: Player,) -> GeneralUnit {
        GeneralUnit {
            rps: rps,
            owner: owner,
            visible: false,
        }
    }

}

impl Unit for GeneralUnit {
    fn owner(&self) -> Player { self.owner }
    fn rps(&self) -> Option<RPS> { Some(self.rps) }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct PovUnit {
    pub owner: Player,
    pub part: Part,
}

impl Unit for PovUnit {
    fn owner(&self) -> Player {
        self.owner
    }

    fn rps(&self) -> Option<RPS> {
        match self.part {
            Part::Ally(unit) => { Some(unit.rps) },
            Part::Enemy(unit) => { unit.rps },
        }
    }
}

impl From<(GeneralUnit , Player)> for PovUnit {
    fn from( data: (GeneralUnit, Player) ) -> PovUnit {
        let (ref unit, ref player) = data;

        if unit.owner() == *player {
            PovUnit {
                owner: unit.owner(),
                part: Part::Ally( AllyUnit { rps: unit.rps, visible: unit.visible } )
            }
        } else {
            PovUnit {
                owner: unit.owner(),
                part: Part::Enemy( EnemyUnit { rps: if unit.visible { Some(unit.rps) } else { None } } )
            }
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum Part {
    Ally(AllyUnit),
    Enemy(EnemyUnit),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct AllyUnit {
    rps: RPS,
    visible: bool,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct EnemyUnit {
    rps: Option<RPS>,
}
<commit_msg>pub members for AllyUnit and EnemyUnit<commit_after>use ::{Player, RPS, Outcome};

pub trait Unit: Copy + Clone {
    fn owner(&self) -> Player;
    fn rps(&self) -> Option<RPS>;
    fn attack(&self, opponent: &Self) -> Option<Outcome> {
        match (self.rps(), opponent.rps()) {
            (Some(attacker), Some(defender)) => Some(attacker.attack(defender)),
            _ => None
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct GeneralUnit {
    pub rps: RPS,
    pub owner: Player,
    pub visible: bool,
}

impl GeneralUnit {
    pub fn new(rps: RPS, owner: Player,) -> GeneralUnit {
        GeneralUnit {
            rps: rps,
            owner: owner,
            visible: false,
        }
    }

}

impl Unit for GeneralUnit {
    fn owner(&self) -> Player { self.owner }
    fn rps(&self) -> Option<RPS> { Some(self.rps) }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct PovUnit {
    pub owner: Player,
    pub part: Part,
}

impl Unit for PovUnit {
    fn owner(&self) -> Player {
        self.owner
    }

    fn rps(&self) -> Option<RPS> {
        match self.part {
            Part::Ally(unit) => { Some(unit.rps) },
            Part::Enemy(unit) => { unit.rps },
        }
    }
}

impl From<(GeneralUnit , Player)> for PovUnit {
    fn from( data: (GeneralUnit, Player) ) -> PovUnit {
        let (ref unit, ref player) = data;

        if unit.owner() == *player {
            PovUnit {
                owner: unit.owner(),
                part: Part::Ally( AllyUnit { rps: unit.rps, visible: unit.visible } )
            }
        } else {
            PovUnit {
                owner: unit.owner(),
                part: Part::Enemy( EnemyUnit { rps: if unit.visible { Some(unit.rps) } else { None } } )
            }
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum Part {
    Ally(AllyUnit),
    Enemy(EnemyUnit),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct AllyUnit {
    pub rps: RPS,
    pub visible: bool,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub struct EnemyUnit {
    pub rps: Option<RPS>,
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

/// Escape a filter literal.
///
/// Literal values appearing in an LDAP filter can contain any character,
/// but some characters (parentheses, asterisk, backslash, NUL) must be
/// escaped in the filter's string representation. This function does the
/// escaping.
///
/// The argument, `lit`, can be owned or borrowed. The function doesn't
/// allocate the return value unless there's need to escape the input.
pub fn ldap_escape<'a, S: Into<Cow<'a, str>>>(lit: S) -> Cow<'a, str> {
    #[inline]
    fn needs_escape(c: u8) -> bool {
        c == b'\\' || c == b'*' || c == b'(' || c == b')' || c == 0
    }

    #[inline]
    fn xdigit(c: u8) -> u8 {
        c + if c < 10 { b'0' } else { b'a' - 10 }
    }

    let lit = lit.into();
    let mut output = None;
    for (i, &c) in lit.as_bytes().iter().enumerate() {
        if needs_escape(c) {
            if output.is_none() {
                output = Some(Vec::with_capacity(lit.len() + 12)); // guess: up to 4 escaped chars
                output.as_mut().unwrap().extend(lit[..i].as_bytes());
            }
            let output = output.as_mut().unwrap();
            output.push(b'\\');
            output.push(xdigit(c >> 4));
            output.push(xdigit(c & 0xF));
        } else if let Some(ref mut output) = output {
            output.push(c);
        }
    }
    if let Some(output) = output {
        // unchecked conversion is safe here: we receive a valid
        // UTF-8 value, by definition, and only replace single ASCII
        // bytes with ASCII byte sequences
        Cow::Owned(unsafe { String::from_utf8_unchecked(output) })
    } else {
        lit.into()
    }
}

/// Escape an attribute value in a relative distinguished name (RDN).
///
/// When a literal string is used to represent an attribute value in an RDN,
/// some of its characters might need to be escaped according to the rules
/// of [RFC 4514](https://tools.ietf.org/html/rfc4514).
///
/// The function is named `dn_escape()` instead of `rdn_escape()` because of
/// a long-standing association of its intended use with the handling of DNs.
///
/// The argument, `val`, can be owned or borrowed. The function doesn't
/// allocate the return value unless there's need to escape the input.
pub fn dn_escape<'a, S: Into<Cow<'a, str>>>(val: S) -> Cow<'a, str> {
    #[inline]
    fn always_escape(c: u8) -> bool {
        c == b'"' || c == b'+' || c == b',' || c == b';' ||
        c == b'<' || c == b'=' || c == b'>' || c == b'\\' ||
        c == 0
    }

    #[inline]
    fn escape_leading(c: u8) -> bool {
        c == b' ' || c == b'#'
    }

    #[inline]
    fn escape_trailing(c: u8) -> bool {
        c == b' '
    }

    #[inline]
    fn xdigit(c: u8) -> u8 {
        c + if c < 10 { b'0' } else { b'a' - 10 }
    }

    let val = val.into();
    let mut output = None;
    for (i, &c) in val.as_bytes().iter().enumerate() {
        if always_escape(c) || i == 0 && escape_leading(c) || i + 1 == val.len() && escape_trailing(c) {
            if output.is_none() {
                output = Some(Vec::with_capacity(val.len() + 12)); // guess: up to 4 escaped chars
                output.as_mut().unwrap().extend(val[..i].as_bytes());
            }
            let output = output.as_mut().unwrap();
            output.push(b'\\');
            output.push(xdigit(c >> 4));
            output.push(xdigit(c & 0xF));
        } else if let Some(ref mut output) = output {
            output.push(c);
        }
    }
    if let Some(output) = output {
        // see the rationale for the same construct in ldap_escape()
        Cow::Owned(unsafe { String::from_utf8_unchecked(output) })
    } else {
        val.into()
    }
}

#[cfg(test)]
mod test {
    use super::dn_escape;

    #[test]
    fn dn_esc_leading_space() {
        assert_eq!(dn_escape(" foo"), "\\20foo");
    }

    #[test]
    fn dn_esc_trailing_space() {
        assert_eq!(dn_escape("foo "), "foo\\20");
    }

    #[test]
    fn dn_esc_inner_space() {
        assert_eq!(dn_escape("f o o"), "f o o");
    }

    #[test]
    fn dn_esc_single_space() {
        assert_eq!(dn_escape(" "), "\\20");
    }

    #[test]
    fn dn_esc_two_spaces() {
        assert_eq!(dn_escape("  "), "\\20\\20");
    }

    #[test]
    fn dn_esc_three_spaces() {
        assert_eq!(dn_escape("   "), "\\20 \\20");
    }

    #[test]
    fn dn_esc_leading_hash() {
        assert_eq!(dn_escape("#rust"), "\\23rust");
    }
}
<commit_msg>Formatting<commit_after>use std::borrow::Cow;

/// Escape a filter literal.
///
/// Literal values appearing in an LDAP filter can contain any character,
/// but some characters (parentheses, asterisk, backslash, NUL) must be
/// escaped in the filter's string representation. This function does the
/// escaping.
///
/// The argument, `lit`, can be owned or borrowed. The function doesn't
/// allocate the return value unless there's need to escape the input.
pub fn ldap_escape<'a, S: Into<Cow<'a, str>>>(lit: S) -> Cow<'a, str> {
    #[inline]
    fn needs_escape(c: u8) -> bool {
        c == b'\\' || c == b'*' || c == b'(' || c == b')' || c == 0
    }

    #[inline]
    fn xdigit(c: u8) -> u8 {
        c + if c < 10 { b'0' } else { b'a' - 10 }
    }

    let lit = lit.into();
    let mut output = None;
    for (i, &c) in lit.as_bytes().iter().enumerate() {
        if needs_escape(c) {
            if output.is_none() {
                output = Some(Vec::with_capacity(lit.len() + 12)); // guess: up to 4 escaped chars
                output.as_mut().unwrap().extend(lit[..i].as_bytes());
            }
            let output = output.as_mut().unwrap();
            output.push(b'\\');
            output.push(xdigit(c >> 4));
            output.push(xdigit(c & 0xF));
        } else if let Some(ref mut output) = output {
            output.push(c);
        }
    }
    if let Some(output) = output {
        // unchecked conversion is safe here: we receive a valid
        // UTF-8 value, by definition, and only replace single ASCII
        // bytes with ASCII byte sequences
        Cow::Owned(unsafe { String::from_utf8_unchecked(output) })
    } else {
        lit.into()
    }
}

/// Escape an attribute value in a relative distinguished name (RDN).
///
/// When a literal string is used to represent an attribute value in an RDN,
/// some of its characters might need to be escaped according to the rules
/// of [RFC 4514](https://tools.ietf.org/html/rfc4514).
///
/// The function is named `dn_escape()` instead of `rdn_escape()` because of
/// a long-standing association of its intended use with the handling of DNs.
///
/// The argument, `val`, can be owned or borrowed. The function doesn't
/// allocate the return value unless there's need to escape the input.
pub fn dn_escape<'a, S: Into<Cow<'a, str>>>(val: S) -> Cow<'a, str> {
    #[inline]
    fn always_escape(c: u8) -> bool {
        c == b'"'
            || c == b'+'
            || c == b','
            || c == b';'
            || c == b'<'
            || c == b'='
            || c == b'>'
            || c == b'\\'
            || c == 0
    }

    #[inline]
    fn escape_leading(c: u8) -> bool {
        c == b' ' || c == b'#'
    }

    #[inline]
    fn escape_trailing(c: u8) -> bool {
        c == b' '
    }

    #[inline]
    fn xdigit(c: u8) -> u8 {
        c + if c < 10 { b'0' } else { b'a' - 10 }
    }

    let val = val.into();
    let mut output = None;
    for (i, &c) in val.as_bytes().iter().enumerate() {
        if always_escape(c)
            || i == 0 && escape_leading(c)
            || i + 1 == val.len() && escape_trailing(c)
        {
            if output.is_none() {
                output = Some(Vec::with_capacity(val.len() + 12)); // guess: up to 4 escaped chars
                output.as_mut().unwrap().extend(val[..i].as_bytes());
            }
            let output = output.as_mut().unwrap();
            output.push(b'\\');
            output.push(xdigit(c >> 4));
            output.push(xdigit(c & 0xF));
        } else if let Some(ref mut output) = output {
            output.push(c);
        }
    }
    if let Some(output) = output {
        // see the rationale for the same construct in ldap_escape()
        Cow::Owned(unsafe { String::from_utf8_unchecked(output) })
    } else {
        val.into()
    }
}

#[cfg(test)]
mod test {
    use super::dn_escape;

    #[test]
    fn dn_esc_leading_space() {
        assert_eq!(dn_escape(" foo"), "\\20foo");
    }

    #[test]
    fn dn_esc_trailing_space() {
        assert_eq!(dn_escape("foo "), "foo\\20");
    }

    #[test]
    fn dn_esc_inner_space() {
        assert_eq!(dn_escape("f o o"), "f o o");
    }

    #[test]
    fn dn_esc_single_space() {
        assert_eq!(dn_escape(" "), "\\20");
    }

    #[test]
    fn dn_esc_two_spaces() {
        assert_eq!(dn_escape("  "), "\\20\\20");
    }

    #[test]
    fn dn_esc_three_spaces() {
        assert_eq!(dn_escape("   "), "\\20 \\20");
    }

    #[test]
    fn dn_esc_leading_hash() {
        assert_eq!(dn_escape("#rust"), "\\23rust");
    }
}
<|endoftext|>


<commit_before>use {Future, Poll};

/// A helpful structure for representing a future that is collapsed over time.
///
/// This basically implements `Future` without literally implementing the trait,
/// and the primary `collapse` method will perform tail call optimization
/// except that it won't propagate upwards, but rather store the result
/// immediately.
pub enum Collapsed<T: Future> {
    Start(T),
    Tail(Box<Future<Item=T::Item, Error=T::Error>>),
}

unsafe impl<T: Send + Future> Send for Collapsed<T> {}
unsafe impl<T: Sync + Future> Sync for Collapsed<T> {}

impl<T: Future> Collapsed<T> {
    pub fn poll(&mut self) -> Poll<T::Item, T::Error> {
        match *self {
            Collapsed::Start(ref mut a) => a.poll(),
            Collapsed::Tail(ref mut a) => a.poll(),
        }
    }

    pub fn collapse(&mut self) {
        unsafe {
            let a = match *self {
                Collapsed::Start(ref mut a) => {
                    match a.tailcall() {
                        Some(a) => a,
                        None => return,
                    }
                }
                Collapsed::Tail(ref mut a) => {
                    if let Some(b) = a.tailcall() {
                        *a = b;
                    }
                    return
                }
            };
            *self = Collapsed::Tail(a);
        }
    }
}
<commit_msg>Remove unused util.rs file<commit_after><|endoftext|>


<commit_before>use state::{Selectable, Editable, Named};
use std::cmp;
use std::io::{stdout, Stdout, Write, Result};
use termion::terminal_size;
use termion::input::MouseTerminal;
use termion::raw::{IntoRawMode, RawTerminal};
use termion::{clear, style, cursor, color};

pub struct View {
    stdout: MouseTerminal<RawTerminal<Stdout>>,
    message: Option<String>,
    is_prompt: bool,
}

impl View {
    pub fn new() -> Result<View> {
        let mut stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap());
        try!(write!(stdout, "{}{}", clear::All, cursor::Show));
        Ok(View {
            stdout: stdout,
            message: None,
            is_prompt: false,
        })
    }

    pub fn message(&mut self, message: &str) {
        self.is_prompt = false;
        self.message = Some(String::from(message));
    }

    pub fn prompt(&mut self, prompt: &str, message: &str) {
        self.is_prompt = true;
        let msg = String::from(prompt) + message;
        self.message = Some(msg);
    }

    pub fn quiet(&mut self) {
        self.is_prompt = false;
        self.message = None;
    }

    pub fn render<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Named + Selectable
    {
        try!(write!(self.stdout, "{}", clear::All));
        try!(self.paint_lines(content));
        try!(self.paint_status(content));
        try!(self.paint_message());
        try!(self.paint_cursor(content));
        try!(self.stdout.flush());
        Ok(())
    }

    pub fn translate_coordinates<T>(&self, content: &T, x: u16, y: u16) -> (usize, usize)
        where T: Editable
    {
        let line = y as isize + self.line_offset(content.line()) as isize - 1;
        let col = cmp::max(0,
                           x as isize -
                           self.line_number_width(content.line(), content.line_count()) as isize -
                           2);
        (line as usize, col as usize)
    }

    fn paint_message(&mut self) -> Result<()> {
        if let Some(ref message) = self.message {
            let y = self.lines_height() + 1;
            try!(write!(self.stdout, "{}{}", cursor::Goto(1, 1 + y as u16), message));
            try!(self.stdout.flush());
        }
        Ok(())
    }

    fn paint_cursor<T>(&mut self, content: &T) -> Result<()>
        where T: Editable
    {
        // in the case of a prompt, the cursor should be drawn in the message line
        let (x, y) = if self.is_prompt {
            (self.message.clone().unwrap().len(), self.lines_height() as usize + 1)
        } else {
            self.cursor_pos(content)
        };
        try!(write!(self.stdout, "{}", cursor::Goto(1 + x as u16, 1 + y as u16)));
        Ok(())
    }

    fn paint_status<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Named
    {
        let line = content.line();
        let column = content.col();
        let line_count = content.line_count();
        let advance = ((line + 1) as f64 / line_count as f64 * 100.0).floor();

        let (screen_width, _) = terminal_size().unwrap();
        let empty_line = (0..screen_width).map(|_| ' ').collect::<String>();
        let y = self.lines_height() as u16;

        try!(write!(self.stdout,
                    "{}{}{}{}{}",
                    style::Invert,
                    cursor::Goto(1, 1 + y),
                    empty_line,
                    cursor::Goto(1, 1 + y),
                    content.name()));

        let position_info = format!("{}% {}/{}: {}", advance, line + 1, line_count, column);
        let x = screen_width - position_info.len() as u16;
        try!(write!(self.stdout,
                    "{}{}{}",
                    cursor::Goto(1 + x, 1 + y),
                    position_info,
                    style::Reset));
        Ok(())
    }

    fn paint_lines<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Selectable
    {
        let line_offset = self.line_offset(content.line());
        let line_height = self.lines_height();
        let line_count = content.line_count();

        let window_it = content.iter()
            .take(content.len() - 1) // the last endline should be invisible to the user
            .scan(('\n', 0, 1), |state, k| {
                {
                    let (ref mut c, ref mut chars, ref mut lines) = *state;
                    if *c == '\n' {
                        *lines += 1;
                    }
                    *chars += 1;
                    *c = k;
                }
                Some(*state)
            })
            .skip_while(|&(_, _, lines)| lines <= 1 + line_offset)
            .take_while(|&(_, _, lines)| lines <= 1 + line_offset + line_height);

        {
            let line_start = self.line_number_width(content.line(), line_count) as u16 + 1;
            try!(write!(self.stdout,
                        "{}{}{}",
                        cursor::Goto(1, 1),
                        line_offset + 1,
                        cursor::Goto(1 + line_start, 1)));
        }
        let mut y = 1;
        for (c, chars, lines) in window_it {
            if c == '\n' {
                let line_start = self.line_number_width(content.line(), line_count) as u16 + 1;
                try!(write!(self.stdout,
                            "{}{}{}",
                            cursor::Goto(1, 1 + y),
                            lines,
                            cursor::Goto(1 + line_start, 1 + y)));
                y += 1;
            } else if match *content.sel() {
                Some((beg, end)) => chars > beg && chars <= end,
                None => false,
            } {
                try!(write!(self.stdout, "{}{}{}{}", color::Fg(color::White), style::Invert, c, style::Reset));
            } else {
                try!(write!(self.stdout, "{}", c));
            }
        }

        Ok(())
    }

    fn cursor_pos<T: Editable>(&self, content: &T) -> (usize, usize) {
        // TODO: column offsetting for long lines
        let line = content.line();
        let column = content.col();
        let first_line = self.line_offset(line);
        let y = line - first_line as usize;
        ((self.line_number_width(line, content.line_count()) as usize + 1 + column), y)
    }

    fn line_number_width(&self, line: usize, line_count: usize) -> u16 {
        let max_in_window = self.line_offset(line) + self.lines_height() + 2;
        let max = cmp::min(max_in_window, line_count as u16);
        max.to_string().len() as u16
    }

    fn line_offset(&self, line: usize) -> u16 {
        match line.checked_sub(self.lines_height() as usize / 2) {
            None => 0,
            Some(val) => val as u16,
        }
    }

    fn status_height(&self) -> u16 {
        2
    }

    pub fn lines_height(&self) -> u16 {
        let (_, screen_height) = terminal_size().unwrap();
        cmp::max(screen_height, self.status_height()) - self.status_height()
    }
}
<commit_msg>fixed selection off by one<commit_after>use state::{Selectable, Editable, Named};
use std::cmp;
use std::io::{stdout, Stdout, Write, Result};
use termion::terminal_size;
use termion::input::MouseTerminal;
use termion::raw::{IntoRawMode, RawTerminal};
use termion::{clear, style, cursor, color};

pub struct View {
    stdout: MouseTerminal<RawTerminal<Stdout>>,
    message: Option<String>,
    is_prompt: bool,
}

impl View {
    pub fn new() -> Result<View> {
        let mut stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap());
        try!(write!(stdout, "{}{}", clear::All, cursor::Show));
        Ok(View {
            stdout: stdout,
            message: None,
            is_prompt: false,
        })
    }

    pub fn message(&mut self, message: &str) {
        self.is_prompt = false;
        self.message = Some(String::from(message));
    }

    pub fn prompt(&mut self, prompt: &str, message: &str) {
        self.is_prompt = true;
        let msg = String::from(prompt) + message;
        self.message = Some(msg);
    }

    pub fn quiet(&mut self) {
        self.is_prompt = false;
        self.message = None;
    }

    pub fn render<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Named + Selectable
    {
        try!(write!(self.stdout, "{}", clear::All));
        try!(self.paint_lines(content));
        try!(self.paint_status(content));
        try!(self.paint_message());
        try!(self.paint_cursor(content));
        try!(self.stdout.flush());
        Ok(())
    }

    pub fn translate_coordinates<T>(&self, content: &T, x: u16, y: u16) -> (usize, usize)
        where T: Editable
    {
        let line = y as isize + self.line_offset(content.line()) as isize - 1;
        let col = cmp::max(0,
                           x as isize -
                           self.line_number_width(content.line(), content.line_count()) as isize -
                           2);
        (line as usize, col as usize)
    }

    fn paint_message(&mut self) -> Result<()> {
        if let Some(ref message) = self.message {
            let y = self.lines_height() + 1;
            try!(write!(self.stdout, "{}{}", cursor::Goto(1, 1 + y as u16), message));
            try!(self.stdout.flush());
        }
        Ok(())
    }

    fn paint_cursor<T>(&mut self, content: &T) -> Result<()>
        where T: Editable
    {
        // in the case of a prompt, the cursor should be drawn in the message line
        let (x, y) = if self.is_prompt {
            (self.message.clone().unwrap().len(), self.lines_height() as usize + 1)
        } else {
            self.cursor_pos(content)
        };
        try!(write!(self.stdout, "{}", cursor::Goto(1 + x as u16, 1 + y as u16)));
        Ok(())
    }

    fn paint_status<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Named
    {
        let line = content.line();
        let column = content.col();
        let line_count = content.line_count();
        let advance = ((line + 1) as f64 / line_count as f64 * 100.0).floor();

        let (screen_width, _) = terminal_size().unwrap();
        let empty_line = (0..screen_width).map(|_| ' ').collect::<String>();
        let y = self.lines_height() as u16;

        try!(write!(self.stdout,
                    "{}{}{}{}{}",
                    style::Invert,
                    cursor::Goto(1, 1 + y),
                    empty_line,
                    cursor::Goto(1, 1 + y),
                    content.name()));

        let position_info = format!("{}% {}/{}: {}", advance, line + 1, line_count, column);
        let x = screen_width - position_info.len() as u16;
        try!(write!(self.stdout,
                    "{}{}{}",
                    cursor::Goto(1 + x, 1 + y),
                    position_info,
                    style::Reset));
        Ok(())
    }

    fn paint_lines<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Selectable
    {
        let line_offset = self.line_offset(content.line());
        let line_height = self.lines_height();
        let line_count = content.line_count();

        let window_it = content.iter()
            .take(content.len() - 1) // the last endline should be invisible to the user
            .scan(('\n', 0, 1), |state, k| {
                {
                    let (ref mut c, ref mut chars, ref mut lines) = *state;
                    if *c == '\n' {
                        *lines += 1;
                    }
                    *chars += 1;
                    *c = k;
                }
                Some(*state)
            })
            .skip_while(|&(_, _, lines)| lines <= 1 + line_offset)
            .take_while(|&(_, _, lines)| lines <= 1 + line_offset + line_height);

        {
            let line_start = self.line_number_width(content.line(), line_count) as u16 + 1;
            try!(write!(self.stdout,
                        "{}{}{}",
                        cursor::Goto(1, 1),
                        line_offset + 1,
                        cursor::Goto(1 + line_start, 1)));
        }
        let mut y = 1;
        for (c, chars, lines) in window_it {
            if c == '\n' {
                let line_start = self.line_number_width(content.line(), line_count) as u16 + 1;
                try!(write!(self.stdout,
                            "{}{}{}",
                            cursor::Goto(1, 1 + y),
                            lines,
                            cursor::Goto(1 + line_start, 1 + y)));
                y += 1;
            } else if match *content.sel() {
                Some((beg, end)) => chars > beg && chars <= end+1,
                None => false,
            } {
                try!(write!(self.stdout, "{}{}{}", color::Bg(color::White), c, style::Reset));
            } else {
                try!(write!(self.stdout, "{}", c));
            }
        }

        Ok(())
    }

    fn cursor_pos<T: Editable>(&self, content: &T) -> (usize, usize) {
        // TODO: column offsetting for long lines
        let line = content.line();
        let column = content.col();
        let first_line = self.line_offset(line);
        let y = line - first_line as usize;
        ((self.line_number_width(line, content.line_count()) as usize + 1 + column), y)
    }

    fn line_number_width(&self, line: usize, line_count: usize) -> u16 {
        let max_in_window = self.line_offset(line) + self.lines_height() + 2;
        let max = cmp::min(max_in_window, line_count as u16);
        max.to_string().len() as u16
    }

    fn line_offset(&self, line: usize) -> u16 {
        match line.checked_sub(self.lines_height() as usize / 2) {
            None => 0,
            Some(val) => val as u16,
        }
    }

    fn status_height(&self) -> u16 {
        2
    }

    pub fn lines_height(&self) -> u16 {
        let (_, screen_height) = terminal_size().unwrap();
        cmp::max(screen_height, self.status_height()) - self.status_height()
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate uuid;
extern crate time;
extern crate ws;

use std::env;
use std::thread;
use std::io::Read;
use std::path::Path;
use std::sync::{Arc,Mutex};
use std::collections::HashMap;

use uuid::Uuid;

use iron::prelude::*;
use iron::status;
use iron::modifiers::Header;
use iron::headers::{AccessControlAllowOrigin,SetCookie};
use iron::middleware::{BeforeMiddleware};

use mount::Mount;
use staticfile::Static;

#[derive(Debug, Clone, Copy)]
pub struct Connection {
    uuid: Uuid,
    ip: std::net::SocketAddr,
}

impl std::fmt::Display for Connection {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}⁖{}", self.uuid, self.ip)
    }
}

fn respond(status: status::Status, msg: &str) -> Response {
    Response::with((status, msg, Header(AccessControlAllowOrigin::Any)))
}

fn respond_ok(msg: &str) -> Response {
    respond(status::Ok, msg)
}

struct ParseCookie { }

impl BeforeMiddleware for ParseCookie {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        // Parse some cookies
        if let Some(cookie_header) = req.headers.get::<iron::headers::Cookie>() {
            // println!("coooookie: {:?}", cookie_header)
        }
        Ok(())
    }

    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<()> {
        // TODO??? Not really sure what this is.
        Ok(())
    }
}

fn main() {
    let connections = Arc::new(Mutex::new(HashMap::new()));

    let mut router = router::Router::new();

    {
        let connections = connections.clone();
        let game_connect = move |req: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let new_uuid = Uuid::new_v4();
            let new_conn = Connection {
                uuid: new_uuid,
                ip: req.remote_addr,
            };
            conn_map.insert(new_conn.uuid, new_conn);
            println!("connect: new user with uuid {}", new_uuid);
            println!("{} connected users", conn_map.len());

            let resp = respond_ok(&format!("{}", new_uuid));
            Ok(resp.set(Header(SetCookie(vec![
                              String::from(format!("bzwf_anon_wstx={}", new_conn))
            ]))))
        };
        router.get("/connect", game_connect, "connect");
    }

    {
        let connections = connections.clone();
        let game_disconnect = move |req: &mut Request| -> IronResult<Response> {
            let mut conn_map = connections.lock().unwrap();

            let mut req_body = String::new();
            /* NOTE(jordan): Must "let _ = ..." Otherwise this gives compiler warning "unused
             * result which must be used"
             */
            /* FIXME(jordan): Is there error-handling we aren't doing here? Whoops... That return
             * value probably *means* something.
             */
            let _ = req.body.read_to_string(&mut req_body);
            let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

            match conn_map.remove(&req_uuid) {
                Some(dropped_conn) => {
                    println!("disconnect: user with uuid {}", dropped_conn.uuid);
                    println!("{} connected users", conn_map.len());
                    Ok(respond_ok("dropped"))
                },
                None => {
                    println!("error: disconnect: tried to drop unconnected user {}", req_uuid);
                    Ok(
                        respond(status::Conflict, "error: cannot drop a user who is not connected")
                    )
                },
            }
        };
        router.post("/disconnect", game_disconnect, "disconnect");
    }

    {
        let connections = connections.clone();
        let game_ping = move |req: &mut Request| -> IronResult<Response> {
            if let Ok(conn_map) = connections.lock() {
                let mut req_body = String::new();
                let _ = req.body.read_to_string(&mut req_body);
                let req_uuid = Uuid::parse_str(req_body.as_str()).unwrap();

                match conn_map.get(&req_uuid) {
                    Some(conn) => {
                        println!("ping[{}]: user with uuid {} sent ping",
                                 time::precise_time_ns(),
                                 conn.uuid);
                        Ok(respond_ok("pong"))
                    },
                    None => {
                        println!("error: ping: nonexistent user {} tried to ping", req_uuid);
                        Ok(respond(status::NotFound, ""))
                    },
                }
            } else {
                panic!("error: ping: cannot obtain lock on connections map");
            }
        };

        let game_ping_ref = Arc::new(game_ping);
        for endpoint in vec!["/ping", "/keep-alive"] {
            let handle = game_ping_ref.clone();
            let desc   = format!("ping:{}", endpoint);
            router.post(endpoint, move |req: &mut Request| handle(req), desc);
        }
    }

    let mut assets_mount = Mount::new();
    assets_mount
        .mount("/", router)
        .mount("/client", Static::new(Path::new("../client")));

    struct WSServer {
        out: ws::Sender,
    }

    impl ws::Handler for WSServer {
        fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
            // TODO
            println!("ws:rcv[{}]: user with uuid {} sent ws msg {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     msg);
            Ok(())
        }

        fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
            // TODO
            println!("ws:opn[{}]: user with uuid {} opened ws cxn",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]");
            Ok(())
        }

        fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
            println!("ws:cls[{}]: user with uuid {} closed ws cxn\n\tCode [{:?}] reason: {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     code,
                     reason);
            // TODO
        }

        fn on_error(&mut self, err: ws::Error) {
            println!("ws:err[{}]: user with uuid {} got error {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     err);
            // TODO
        }
    }

    {
        let domain : String;

        match env::var("ADDR") {
            Ok(val) => domain = val,
            Err(_)  => {
                println!("Environment error! ADDR not found; using localhost for default.");
                domain = String::from("localhost")
            }
        }

        // FIXME(jordan): Printing that servers are running before they fail or succeed...
        let web_domain = domain.clone();
        let webserver_thread = thread::spawn(move || {
            let web_addr = format!("{}:3000", web_domain);
            println!("TCP Web server listening on {}", web_addr);
            println!("\tGo to: http://{}/client/html", web_addr);
            Iron::new(assets_mount).http(web_addr.clone()).unwrap()
        });

        let ws_domain = domain.clone();
        let websocket_thread = thread::spawn(move || {
            let ws_addr = format!("{}:3001", ws_domain);
            println!("WS WebSockets server listening on {}", ws_addr);
            ws::listen(ws_addr.clone(), |out| WSServer { out: out }).unwrap()
        });

        webserver_thread.join().unwrap();
        websocket_thread.join().unwrap();
    }
}

#[cfg(test)]
mod tests {
    // NOTE: bring into scope everything defined above
    use super::*;

    #[test]
    fn it_works() {
        // TODO: write a test
    }
}
<commit_msg>Refactor/Major: Remove HTTP; Set-Cookie during WebSocket<commit_after>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate uuid;
extern crate time;
extern crate ws;

use std::env;
use std::thread;
use std::path::Path;
use std::sync::{Arc,Mutex};
use std::collections::HashMap;

use uuid::Uuid;

use iron::prelude::*;

use mount::Mount;
use staticfile::Static;

#[derive(Debug, Clone, Copy)]
pub struct Connection {
    uuid: Uuid,
}

impl std::fmt::Display for Connection {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "conn{{{}}}", self.uuid)
    }
}

fn main() {
    let connections = Arc::new(Mutex::new(HashMap::new()));

    struct WSServer {
        out: ws::Sender,
        connections: Arc<Mutex<HashMap<Uuid, Connection>>>
    }

    impl ws::Handler for WSServer {
        fn on_request(&mut self, req: &ws::Request) -> ws::Result<ws::Response> {
            let mut resp = ws::Response::from_request(req).unwrap();

            let mut conn_map = self.connections.lock().unwrap();

            println!("ws:req[{}]", time::precise_time_ns());

            let new_uuid = Uuid::new_v4();
            let new_conn = Connection {
                uuid: new_uuid
            };
            conn_map.insert(new_conn.uuid, new_conn);
            println!("wsconnect: new user with uuid {}", new_uuid);
            println!("{} connected users", conn_map.len());

            println!("wsconnect: putting cookie: bzwf_anon_wstx={}", new_conn);
            let new_bzwf_cookie_str = format!("bzwf_anon_wstx={}", new_conn);
            {
                let headers = resp.headers_mut();
                headers.push((
                    String::from("Set-Cookie"),
                    new_bzwf_cookie_str.as_bytes().to_vec()
                ));
            }

            Ok(resp)
        }

        fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
            // TODO
            println!("ws:rcv[{}]: user with uuid {} sent ws msg {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     msg);
            self.out.send("I hear you loud and clear").unwrap();
            Ok(())
        }

        fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
            // TODO
            println!("ws:opn[{}]: user with uuid {} opened ws cxn",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]");
            Ok(())
        }

        fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
            println!("ws:cls[{}]: user with uuid {} closed ws cxn\n\tCode [{:?}] reason: {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     code,
                     reason);
            // TODO
        }

        fn on_error(&mut self, err: ws::Error) {
            println!("ws:err[{}]: user with uuid {} got error {}",
                     time::precise_time_ns(),
                     "[[[ we don't have uuids in ws yet ]]]",
                     err);
            // TODO
        }
    }

    {
        let domain : String;

        match env::var("DOMAIN") {
            Ok(val) => domain = val,
            Err(_)  => {
                println!("DOMAIN not found; using localhost for default.");
                domain = String::from("localhost")
            }
        }

        let web_domain = domain.clone();
        let webserver_thread = thread::spawn(move || {
            let web_addr = format!("{}:3000", web_domain);
            println!("TCP Web server listening on {}", web_addr);
            println!("\tGo to: http://{}/client/html", web_addr);

            let mut assets_mount = Mount::new();
            assets_mount
                .mount("/client", Static::new(Path::new("../client")));

            Iron::new(assets_mount).http(web_addr.clone()).unwrap()
        });

        let ws_domain = domain.clone();
        let websocket_thread = thread::spawn(move || {
            let ws_addr = format!("{}:3001", ws_domain);
            println!("WS WebSockets server listening on {}", ws_addr);
            ws::listen(ws_addr.clone(), |out| WSServer {
                out: out,
                connections: connections.clone()
            }).unwrap();
        });

        webserver_thread.join().unwrap();
        websocket_thread.join().unwrap();
    }
}

#[cfg(test)]
mod tests {
    // NOTE: bring into scope everything defined above
    use super::*;

    #[test]
    fn it_works() {
        // TODO: write a test
    }
}
<|endoftext|>


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

macro_rules! int_module { ($T:ident, $T_i:ident) => (
#[cfg(test)]
mod tests {
    use core::$T_i::*;
    use core::isize;
    use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
    use core::mem;

    use num;

    #[test]
    fn test_overflows() {
        assert!(MAX > 0);
        assert!(MIN <= 0);
        assert!(MIN + MAX + 1 == 0);
    }

    #[test]
    fn test_num() {
        num::test_num(10 as $T, 2 as $T);
    }

    #[test]
    fn test_mod_euclid() {
        assert!((-1 as $T).mod_euclid(MIN) == MAX);
    }

    #[test]
    pub fn test_abs() {
        assert!((1 as $T).abs() == 1 as $T);
        assert!((0 as $T).abs() == 0 as $T);
        assert!((-1 as $T).abs() == 1 as $T);
    }

    #[test]
    fn test_signum() {
        assert!((1 as $T).signum() == 1 as $T);
        assert!((0 as $T).signum() == 0 as $T);
        assert!((-0 as $T).signum() == 0 as $T);
        assert!((-1 as $T).signum() == -1 as $T);
    }

    #[test]
    fn test_is_positive() {
        assert!((1 as $T).is_positive());
        assert!(!(0 as $T).is_positive());
        assert!(!(-0 as $T).is_positive());
        assert!(!(-1 as $T).is_positive());
    }

    #[test]
    fn test_is_negative() {
        assert!(!(1 as $T).is_negative());
        assert!(!(0 as $T).is_negative());
        assert!(!(-0 as $T).is_negative());
        assert!((-1 as $T).is_negative());
    }

    #[test]
    fn test_bitwise_operators() {
        assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
        assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
        assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
        assert!(0b1110 as $T == (0b0111 as $T).shl(1));
        assert!(0b0111 as $T == (0b1110 as $T).shr(1));
        assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not());
    }

    const A: $T = 0b0101100;
    const B: $T = 0b0100001;
    const C: $T = 0b1111001;

    const _0: $T = 0;
    const _1: $T = !0;

    #[test]
    fn test_count_ones() {
        assert!(A.count_ones() == 3);
        assert!(B.count_ones() == 2);
        assert!(C.count_ones() == 5);
    }

    #[test]
    fn test_count_zeros() {
        let bits = mem::size_of::<$T>() * 8;
        assert!(A.count_zeros() == bits as u32 - 3);
        assert!(B.count_zeros() == bits as u32 - 2);
        assert!(C.count_zeros() == bits as u32 - 5);
    }

    #[test]
    fn test_rotate() {
        assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
        assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
        assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);

        // Rotating these should make no difference
        //
        // We test using 124 bits because to ensure that overlong bit shifts do
        // not cause undefined behaviour. See #10183.
        assert_eq!(_0.rotate_left(124), _0);
        assert_eq!(_1.rotate_left(124), _1);
        assert_eq!(_0.rotate_right(124), _0);
        assert_eq!(_1.rotate_right(124), _1);

        // Rotating by 0 should have no effect
        assert_eq!(A.rotate_left(0), A);
        assert_eq!(B.rotate_left(0), B);
        assert_eq!(C.rotate_left(0), C);
        // Rotating by a multiple of word size should also have no effect
        assert_eq!(A.rotate_left(64), A);
        assert_eq!(B.rotate_left(64), B);
        assert_eq!(C.rotate_left(64), C);
    }

    #[test]
    fn test_swap_bytes() {
        assert_eq!(A.swap_bytes().swap_bytes(), A);
        assert_eq!(B.swap_bytes().swap_bytes(), B);
        assert_eq!(C.swap_bytes().swap_bytes(), C);

        // Swapping these should make no difference
        assert_eq!(_0.swap_bytes(), _0);
        assert_eq!(_1.swap_bytes(), _1);
    }

    #[test]
    fn test_le() {
        assert_eq!($T::from_le(A.to_le()), A);
        assert_eq!($T::from_le(B.to_le()), B);
        assert_eq!($T::from_le(C.to_le()), C);
        assert_eq!($T::from_le(_0), _0);
        assert_eq!($T::from_le(_1), _1);
        assert_eq!(_0.to_le(), _0);
        assert_eq!(_1.to_le(), _1);
    }

    #[test]
    fn test_be() {
        assert_eq!($T::from_be(A.to_be()), A);
        assert_eq!($T::from_be(B.to_be()), B);
        assert_eq!($T::from_be(C.to_be()), C);
        assert_eq!($T::from_be(_0), _0);
        assert_eq!($T::from_be(_1), _1);
        assert_eq!(_0.to_be(), _0);
        assert_eq!(_1.to_be(), _1);
    }

    #[test]
    fn test_signed_checked_div() {
        assert!((10 as $T).checked_div(2) == Some(5));
        assert!((5 as $T).checked_div(0) == None);
        assert!(isize::MIN.checked_div(-1) == None);
    }

    #[test]
    fn test_from_str() {
        fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
            ::std::str::FromStr::from_str(t).ok()
        }
        assert_eq!(from_str::<$T>("0"), Some(0 as $T));
        assert_eq!(from_str::<$T>("3"), Some(3 as $T));
        assert_eq!(from_str::<$T>("10"), Some(10 as $T));
        assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
        assert_eq!(from_str::<$T>("00100"), Some(100 as $T));

        assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
        assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
        assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
        assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
        assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));

        assert_eq!(from_str::<$T>(""), None);
        assert_eq!(from_str::<$T>(" "), None);
        assert_eq!(from_str::<$T>("x"), None);
    }

    #[test]
    fn test_from_str_radix() {
        assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
        assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
        assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
        assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
        assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
        assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
        assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
        assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));

        assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
        assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
        assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
        assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
        assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
        assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
        assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
        assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));

        assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
        assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
    }

    #[test]
    fn test_pow() {
        let mut r = 2 as $T;

        assert_eq!(r.pow(2), 4 as $T);
        assert_eq!(r.pow(0), 1 as $T);
        r = -2 as $T;
        assert_eq!(r.pow(2), 4 as $T);
        assert_eq!(r.pow(3), -8 as $T);
    }
}

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

macro_rules! int_module { ($T:ident, $T_i:ident) => (
#[cfg(test)]
mod tests {
    use core::$T_i::*;
    use core::isize;
    use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
    use core::mem;

    use num;

    #[test]
    fn test_overflows() {
        assert!(MAX > 0);
        assert!(MIN <= 0);
        assert!(MIN + MAX + 1 == 0);
    }

    #[test]
    fn test_num() {
        num::test_num(10 as $T, 2 as $T);
    }

    #[test]
    fn test_rem_euclid() {
        assert!((-1 as $T).rem_euclid(MIN) == MAX);
    }

    #[test]
    pub fn test_abs() {
        assert!((1 as $T).abs() == 1 as $T);
        assert!((0 as $T).abs() == 0 as $T);
        assert!((-1 as $T).abs() == 1 as $T);
    }

    #[test]
    fn test_signum() {
        assert!((1 as $T).signum() == 1 as $T);
        assert!((0 as $T).signum() == 0 as $T);
        assert!((-0 as $T).signum() == 0 as $T);
        assert!((-1 as $T).signum() == -1 as $T);
    }

    #[test]
    fn test_is_positive() {
        assert!((1 as $T).is_positive());
        assert!(!(0 as $T).is_positive());
        assert!(!(-0 as $T).is_positive());
        assert!(!(-1 as $T).is_positive());
    }

    #[test]
    fn test_is_negative() {
        assert!(!(1 as $T).is_negative());
        assert!(!(0 as $T).is_negative());
        assert!(!(-0 as $T).is_negative());
        assert!((-1 as $T).is_negative());
    }

    #[test]
    fn test_bitwise_operators() {
        assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
        assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
        assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
        assert!(0b1110 as $T == (0b0111 as $T).shl(1));
        assert!(0b0111 as $T == (0b1110 as $T).shr(1));
        assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not());
    }

    const A: $T = 0b0101100;
    const B: $T = 0b0100001;
    const C: $T = 0b1111001;

    const _0: $T = 0;
    const _1: $T = !0;

    #[test]
    fn test_count_ones() {
        assert!(A.count_ones() == 3);
        assert!(B.count_ones() == 2);
        assert!(C.count_ones() == 5);
    }

    #[test]
    fn test_count_zeros() {
        let bits = mem::size_of::<$T>() * 8;
        assert!(A.count_zeros() == bits as u32 - 3);
        assert!(B.count_zeros() == bits as u32 - 2);
        assert!(C.count_zeros() == bits as u32 - 5);
    }

    #[test]
    fn test_rotate() {
        assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
        assert_eq!(B.rotate_left(3).rotate_left(2).rotate_right(5), B);
        assert_eq!(C.rotate_left(6).rotate_right(2).rotate_right(4), C);

        // Rotating these should make no difference
        //
        // We test using 124 bits because to ensure that overlong bit shifts do
        // not cause undefined behaviour. See #10183.
        assert_eq!(_0.rotate_left(124), _0);
        assert_eq!(_1.rotate_left(124), _1);
        assert_eq!(_0.rotate_right(124), _0);
        assert_eq!(_1.rotate_right(124), _1);

        // Rotating by 0 should have no effect
        assert_eq!(A.rotate_left(0), A);
        assert_eq!(B.rotate_left(0), B);
        assert_eq!(C.rotate_left(0), C);
        // Rotating by a multiple of word size should also have no effect
        assert_eq!(A.rotate_left(64), A);
        assert_eq!(B.rotate_left(64), B);
        assert_eq!(C.rotate_left(64), C);
    }

    #[test]
    fn test_swap_bytes() {
        assert_eq!(A.swap_bytes().swap_bytes(), A);
        assert_eq!(B.swap_bytes().swap_bytes(), B);
        assert_eq!(C.swap_bytes().swap_bytes(), C);

        // Swapping these should make no difference
        assert_eq!(_0.swap_bytes(), _0);
        assert_eq!(_1.swap_bytes(), _1);
    }

    #[test]
    fn test_le() {
        assert_eq!($T::from_le(A.to_le()), A);
        assert_eq!($T::from_le(B.to_le()), B);
        assert_eq!($T::from_le(C.to_le()), C);
        assert_eq!($T::from_le(_0), _0);
        assert_eq!($T::from_le(_1), _1);
        assert_eq!(_0.to_le(), _0);
        assert_eq!(_1.to_le(), _1);
    }

    #[test]
    fn test_be() {
        assert_eq!($T::from_be(A.to_be()), A);
        assert_eq!($T::from_be(B.to_be()), B);
        assert_eq!($T::from_be(C.to_be()), C);
        assert_eq!($T::from_be(_0), _0);
        assert_eq!($T::from_be(_1), _1);
        assert_eq!(_0.to_be(), _0);
        assert_eq!(_1.to_be(), _1);
    }

    #[test]
    fn test_signed_checked_div() {
        assert!((10 as $T).checked_div(2) == Some(5));
        assert!((5 as $T).checked_div(0) == None);
        assert!(isize::MIN.checked_div(-1) == None);
    }

    #[test]
    fn test_from_str() {
        fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
            ::std::str::FromStr::from_str(t).ok()
        }
        assert_eq!(from_str::<$T>("0"), Some(0 as $T));
        assert_eq!(from_str::<$T>("3"), Some(3 as $T));
        assert_eq!(from_str::<$T>("10"), Some(10 as $T));
        assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
        assert_eq!(from_str::<$T>("00100"), Some(100 as $T));

        assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
        assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
        assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
        assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
        assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));

        assert_eq!(from_str::<$T>(""), None);
        assert_eq!(from_str::<$T>(" "), None);
        assert_eq!(from_str::<$T>("x"), None);
    }

    #[test]
    fn test_from_str_radix() {
        assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
        assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
        assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
        assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
        assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
        assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
        assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
        assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));

        assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
        assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
        assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
        assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
        assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
        assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
        assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
        assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));

        assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
        assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
    }

    #[test]
    fn test_pow() {
        let mut r = 2 as $T;

        assert_eq!(r.pow(2), 4 as $T);
        assert_eq!(r.pow(0), 1 as $T);
        r = -2 as $T;
        assert_eq!(r.pow(2), 4 as $T);
        assert_eq!(r.pow(3), -8 as $T);
    }
}

)}
<|endoftext|>