<commit_before>#[macro_use]
extern crate prettytable;
use prettytable::Table;

use std::io;
use std::io::Write;
use std::str::FromStr;

const CROSS: &'static str = "X";
const EMPTY: &'static str = " ";
const ROUND: &'static str = "O";

fn main() {
    let mut table = table![
        [EMPTY, EMPTY, EMPTY],
        [EMPTY, EMPTY, EMPTY],
        [EMPTY, EMPTY, EMPTY]
    ];
    table.printstd();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    let mut current = CROSS;
    loop {
        let mut line = String::new();
        print!("{} plays > ", current);
        stdout.flush().unwrap();
        stdin.read_line(&mut line).expect("Cannot read input");
        let i = match usize::from_str(line.trim()) {
            Ok(i) => i,
            _ => {
                println!("Bad input");
                continue;
            }
        };
        if i < 1 || i > 9 {
            println!("Bad input, should be between 1 and 9");
            continue;
        }
        let x = (i - 1) % 3;
        let y = (i - 1) / 3;
        {
            let row = table.get_mut_row(y).unwrap();
            if row.get_cell(x).unwrap().to_string() != EMPTY {
                println!("There's already someone there");
                continue;
            }
            row.set_cell(cell!(current), x).unwrap();
        }
        table.printstd();
        if check(&table) {
            return;
        }
        if current == CROSS {
            current = ROUND;
        } else {
            current = CROSS;
        }
    }
}

fn get(table: &Table, x: usize, y: usize) -> String {
    match table.get_row(y) {
        Some(r) => match r.get_cell(x) {
            Some(c) => c.to_string(),
            _ => EMPTY.to_string(),
        },
        _ => EMPTY.to_string(),
    }
}

fn is(table: &Table, s: &str, x: usize, y: usize) -> bool {
    get(table, x, y).as_str() == s
}

fn check(table: &Table) -> bool {
    let mut full = true;
    for y in 0..3 {
        for x in 0..3 {
            if is(table, EMPTY, x, y) {
                full = false;
                continue;
            }
            let current = get(table, x, y);
            let c = current.as_str();
            if is(table, c, x + 1, y) && is(table, c, x + 2, y)
                || is(table, c, x + 1, y + 1) && is(table, c, x + 2, y + 2)
                || x >= 2 && is(table, c, x - 1, y + 1) && is(table, c, x - 2, y + 2)
                || is(table, c, x, y + 1) && is(table, c, x, y + 2)
            {
                println!("Game is over. {} is the winner", current);
                return true;
            }
        }
    }
    if full {
        println!("Game is over. It's a draw");
    }
    full
}
<commit_msg>Updated tictactoe example to change the table in place<commit_after>#[macro_use]
extern crate prettytable;
extern crate term;

use prettytable::Table;

use std::io;
use std::io::Write;
use std::str::FromStr;

const CROSS: &'static str = "X";
const EMPTY: &'static str = " ";
const ROUND: &'static str = "O";

fn main() {
    let mut table = table![
        [EMPTY, EMPTY, EMPTY],
        [EMPTY, EMPTY, EMPTY],
        [EMPTY, EMPTY, EMPTY]
    ];
    let mut height = table.printstd();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    let mut current = CROSS;
    let mut terminal = term::stdout().unwrap();
    loop {
        let mut line = String::new();
        print!("{} plays > ", current);
        height += 1;
        stdout.flush().unwrap();
        stdin.read_line(&mut line).expect("Cannot read input");
        let i = match usize::from_str(line.trim()) {
            Ok(i) => i,
            _ => {
                println!("Bad input");
                height += 1;
                continue;
            }
        };
        if i < 1 || i > 9 {
            println!("Bad input, should be between 1 and 9");
            height += 1;
            continue;
        }
        let x = (i - 1) % 3;
        let y = (i - 1) / 3;
        {
            let row = table.get_mut_row(y).unwrap();
            if row.get_cell(x).unwrap().to_string() != EMPTY {
                println!("There's already someone there");
                height += 1;
                continue;
            }
            row.set_cell(cell!(current), x).unwrap();
        }
        for _ in 0..height {
            terminal.cursor_up().unwrap();
            terminal.delete_line().unwrap();
        }
        height = table.printstd();
        if check(&table) {
            return;
        }
        if current == CROSS {
            current = ROUND;
        } else {
            current = CROSS;
        }
    }
}

fn get(table: &Table, x: usize, y: usize) -> String {
    match table.get_row(y) {
        Some(r) => match r.get_cell(x) {
            Some(c) => c.to_string(),
            _ => EMPTY.to_string(),
        },
        _ => EMPTY.to_string(),
    }
}

fn is(table: &Table, s: &str, x: usize, y: usize) -> bool {
    get(table, x, y).as_str() == s
}

fn check(table: &Table) -> bool {
    let mut full = true;
    for y in 0..3 {
        for x in 0..3 {
            if is(table, EMPTY, x, y) {
                full = false;
                continue;
            }
            let current = get(table, x, y);
            let c = current.as_str();
            if is(table, c, x + 1, y) && is(table, c, x + 2, y)
                || is(table, c, x + 1, y + 1) && is(table, c, x + 2, y + 2)
                || x >= 2 && is(table, c, x - 1, y + 1) && is(table, c, x - 2, y + 2)
                || is(table, c, x, y + 1) && is(table, c, x, y + 2)
            {
                println!("Game is over. {} is the winner", current);
                return true;
            }
        }
    }
    if full {
        println!("Game is over. It's a draw");
    }
    full
}
<|endoftext|>


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

use rustc::hir::{self, ImplPolarity};
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::ty::{self, TyCtxt};
use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
use syntax::ast;
use rustc_data_structures::sync::Lrc;

trait Lower<T> {
    /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
    fn lower(&self) -> T;
}

impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
    fn lower(&self) -> Vec<U> {
        self.iter().map(|item| item.lower()).collect()
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::TraitPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::Implemented(*self)
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::ProjectionEq(*self)
    }
}

impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::Holds(self.lower())
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::RegionOutlives(*self)
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::TypeOutlives(*self)
    }
}

/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
/// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
/// example), we model them with quantified goals, e.g. as for the previous example:
/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
/// `Binder<Holds(Implemented(TraitPredicate))>`.
///
/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
/// can directly lower to a leaf goal instead of a quantified goal.
impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
{
    fn lower(&self) -> Goal<'tcx> {
        match self.no_late_bound_regions() {
            Some(p) => p.lower().into(),
            None => Goal::Quantified(
                QuantifierKind::Universal,
                Box::new(self.map_bound(|p| p.lower().into()))
            ),
        }
    }
}

impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
    fn lower(&self) -> Goal<'tcx> {
        use rustc::ty::Predicate::*;

        match self {
            Trait(predicate) => predicate.lower(),
            RegionOutlives(predicate) => predicate.lower(),
            TypeOutlives(predicate) => predicate.lower(),
            Projection(predicate) => predicate.lower(),
            WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
            ObjectSafe(..) |
            ClosureKind(..) |
            Subtype(..) |
            ConstEvaluatable(..) => unimplemented!(),
        }
    }
}

crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
    let item = tcx.hir.expect_item(node_id);
    match item.node {
        hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),

        // FIXME: other constructions e.g. traits, associated types...
        _ => Lrc::new(vec![]),
    }
}

fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
        return Lrc::new(vec![]);
    }

    // Rule Implemented-From-Impl (see rustc guide)
    //
    // `impl<P0..Pn> Trait<A1..An> for A0 where WC { .. }`
    //
    // ```
    // forall<P0..Pn> {
    //   Implemented(A0: Trait<A1..An>) :- WC
    // }
    // ```

    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
    // `Implemented(A0: Trait<A1..An>)`
    let trait_pred = ty::TraitPredicate { trait_ref }.lower();
     // `WC`
    let where_clauses = tcx.predicates_of(def_id).predicates.lower();

     // `Implemented(A0: Trait<A1..An>) :- WC`
    let clause = Clause::Implies(where_clauses, trait_pred);
    Lrc::new(vec![clause])
}

pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
    if !tcx.features().rustc_attrs {
        return;
    }

    let mut visitor = ClauseDumper { tcx };
    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
}

struct ClauseDumper<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
    fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
        let def_id = self.tcx.hir.local_def_id(node_id);
        for attr in attrs {
            if attr.check_name("rustc_dump_program_clauses") {
                let clauses = self.tcx.program_clauses_for(def_id);
                for clause in &*clauses {
                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
                }
            }
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_item(&mut self, item: &'tcx hir::Item) {
        self.process_attrs(item.id, &item.attrs);
        intravisit::walk_item(self, item);
    }

    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
        self.process_attrs(trait_item.id, &trait_item.attrs);
        intravisit::walk_trait_item(self, trait_item);
    }

    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
        self.process_attrs(impl_item.id, &impl_item.attrs);
        intravisit::walk_impl_item(self, impl_item);
    }

    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
        self.process_attrs(s.id, &s.attrs);
        intravisit::walk_struct_field(self, s);
    }
}
<commit_msg>Implement Rule Implemented-From-Env<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::hir::{self, ImplPolarity};
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::ty::{self, TyCtxt};
use rustc::ty::subst::Substs;
use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
use syntax::ast;
use rustc_data_structures::sync::Lrc;

trait Lower<T> {
    /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
    fn lower(&self) -> T;
}

impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
    fn lower(&self) -> Vec<U> {
        self.iter().map(|item| item.lower()).collect()
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::TraitPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::Implemented(*self)
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::ProjectionEq(*self)
    }
}

impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::Holds(self.lower())
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::RegionOutlives(*self)
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::TypeOutlives(*self)
    }
}

/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
/// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
/// example), we model them with quantified goals, e.g. as for the previous example:
/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
/// `Binder<Holds(Implemented(TraitPredicate))>`.
///
/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
/// can directly lower to a leaf goal instead of a quantified goal.
impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
{
    fn lower(&self) -> Goal<'tcx> {
        match self.no_late_bound_regions() {
            Some(p) => p.lower().into(),
            None => Goal::Quantified(
                QuantifierKind::Universal,
                Box::new(self.map_bound(|p| p.lower().into()))
            ),
        }
    }
}

impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
    fn lower(&self) -> Goal<'tcx> {
        use rustc::ty::Predicate::*;

        match self {
            Trait(predicate) => predicate.lower(),
            RegionOutlives(predicate) => predicate.lower(),
            TypeOutlives(predicate) => predicate.lower(),
            Projection(predicate) => predicate.lower(),
            WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
            ObjectSafe(..) |
            ClosureKind(..) |
            Subtype(..) |
            ConstEvaluatable(..) => unimplemented!(),
        }
    }
}

crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
    let item = tcx.hir.expect_item(node_id);
    match item.node {
        hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
        hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),

        // FIXME: other constructions e.g. traits, associated types...
        _ => Lrc::new(vec![]),
    }
}

fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    // Rule Implemented-From-Env (see rustc guide)
    //
    // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
    //
    // ```
    // forall<Self, P1..Pn> {
    //   Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)
    // }
    // ```

    // `Self: Trait<P1..Pn>`
    let trait_pred = ty::TraitPredicate {
        trait_ref: ty::TraitRef {
            def_id,
            substs: Substs::identity_for_item(tcx, def_id)
        }
    };
    // `FromEnv(Self: Trait<P1..Pn>)`
    let from_env = Goal::DomainGoal(DomainGoal::FromEnv(trait_pred.lower()));
    // `Implemented(Self: Trait<P1..Pn>)`
    let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred));

    // `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
    let clause = Clause::Implies(vec![from_env], impl_trait);
    Lrc::new(vec![clause])
}

fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
        return Lrc::new(vec![]);
    }

    // Rule Implemented-From-Impl (see rustc guide)
    //
    // `impl<P0..Pn> Trait<A1..An> for A0 where WC { .. }`
    //
    // ```
    // forall<P0..Pn> {
    //   Implemented(A0: Trait<A1..An>) :- WC
    // }
    // ```

    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
    // `Implemented(A0: Trait<A1..An>)`
    let trait_pred = ty::TraitPredicate { trait_ref }.lower();
     // `WC`
    let where_clauses = tcx.predicates_of(def_id).predicates.lower();

     // `Implemented(A0: Trait<A1..An>) :- WC`
    let clause = Clause::Implies(where_clauses, trait_pred);
    Lrc::new(vec![clause])
}

pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
    if !tcx.features().rustc_attrs {
        return;
    }

    let mut visitor = ClauseDumper { tcx };
    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
}

struct ClauseDumper<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
    fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
        let def_id = self.tcx.hir.local_def_id(node_id);
        for attr in attrs {
            if attr.check_name("rustc_dump_program_clauses") {
                let clauses = self.tcx.program_clauses_for(def_id);
                for clause in &*clauses {
                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
                }
            }
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_item(&mut self, item: &'tcx hir::Item) {
        self.process_attrs(item.id, &item.attrs);
        intravisit::walk_item(self, item);
    }

    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
        self.process_attrs(trait_item.id, &trait_item.attrs);
        intravisit::walk_trait_item(self, trait_item);
    }

    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
        self.process_attrs(impl_item.id, &impl_item.attrs);
        intravisit::walk_impl_item(self, impl_item);
    }

    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
        self.process_attrs(s.id, &s.attrs);
        intravisit::walk_struct_field(self, s);
    }
}
<|endoftext|>


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

use syntax_pos::symbol::Symbol;
use back::write::create_target_machine;
use llvm;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
use libc::c_int;
use std::ffi::{CStr, CString};

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;

static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();

pub(crate) fn init(sess: &Session) {
    unsafe {
        // Before we touch LLVM, make sure that multithreading is enabled.
        INIT.call_once(|| {
            if llvm::LLVMStartMultithreaded() != 1 {
                // use an extra bool to make sure that all future usage of LLVM
                // cannot proceed despite the Once not running more than once.
                POISONED.store(true, Ordering::SeqCst);
            }

            configure_llvm(sess);
        });

        if POISONED.load(Ordering::SeqCst) {
            bug!("couldn't enable multi-threaded LLVM");
        }
    }
}

fn require_inited() {
    INIT.call_once(|| bug!("llvm is not initialized"));
    if POISONED.load(Ordering::SeqCst) {
        bug!("couldn't enable multi-threaded LLVM");
    }
}

unsafe fn configure_llvm(sess: &Session) {
    let mut llvm_c_strs = Vec::new();
    let mut llvm_args = Vec::new();

    {
        let mut add = |arg: &str| {
            let s = CString::new(arg).unwrap();
            llvm_args.push(s.as_ptr());
            llvm_c_strs.push(s);
        };
        add("rustc"); // fake program name
        if sess.time_llvm_passes() { add("-time-passes"); }
        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }

        for arg in &sess.opts.cg.llvm_args {
            add(&(*arg));
        }
    }

    llvm::LLVMInitializePasses();

    llvm::initialize_available_targets();

    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                 llvm_args.as_ptr());
}

// WARNING: the features must be known to LLVM or the feature
// detection code will walk past the end of the feature array,
// leading to crashes.

const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "v7\0", "vfp2\0", "vfp3\0", "vfp4\0"];

const AARCH64_WHITELIST: &'static [&'static str] = &["neon\0", "v7\0"];

const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
                                                 "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
                                                 "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0",
                                                 "xsave\0", "xsaveopt\0", "xsavec\0",
                                                 "xsaves\0", "aes\0", "pclmul\0"
                                                 "avx512bw\0", "avx512cd\0",
                                                 "avx512dq\0", "avx512er\0",
                                                 "avx512f\0", "avx512ifma\0",
                                                 "avx512pf\0", "avx512vbmi\0",
                                                 "avx512vl\0", "avx512vpopcntdq\0",
                                                 "mmx\0", "fxsr\0"];

const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];

const POWERPC_WHITELIST: &'static [&'static str] = &["altivec\0",
                                                     "power8-altivec\0", "power9-altivec\0",
                                                     "power8-vector\0", "power9-vector\0",
                                                     "vsx\0"];

const MIPS_WHITELIST: &'static [&'static str] = &["msa\0"];

pub fn target_features(sess: &Session) -> Vec<Symbol> {
    let whitelist = target_feature_whitelist(sess);
    let target_machine = create_target_machine(sess);
    let mut features = Vec::new();
    for feat in whitelist {
        if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr()) } {
            features.push(Symbol::intern(feat.to_str().unwrap()));
        }
    }
    features
}

pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
    let whitelist = match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "aarch64" => AARCH64_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        "hexagon" => HEXAGON_WHITELIST,
        "mips" | "mips64" => MIPS_WHITELIST,
        "powerpc" | "powerpc64" => POWERPC_WHITELIST,
        _ => &[],
    };
    whitelist.iter().map(|m| {
        CStr::from_bytes_with_nul(m.as_bytes()).unwrap()
    }).collect()
}

pub fn print_version() {
    // Can be called without initializing LLVM
    unsafe {
        println!("LLVM version: {}.{}",
                 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
    }
}

pub fn print_passes() {
    // Can be called without initializing LLVM
    unsafe { llvm::LLVMRustPrintPasses(); }
}

pub(crate) fn print(req: PrintRequest, sess: &Session) {
    require_inited();
    let tm = create_target_machine(sess);
    unsafe {
        match req {
            PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
            PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
            _ => bug!("rustc_trans can't handle print request: {:?}", req),
        }
    }
}
<commit_msg>typo fix<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syntax_pos::symbol::Symbol;
use back::write::create_target_machine;
use llvm;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
use libc::c_int;
use std::ffi::{CStr, CString};

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;

static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();

pub(crate) fn init(sess: &Session) {
    unsafe {
        // Before we touch LLVM, make sure that multithreading is enabled.
        INIT.call_once(|| {
            if llvm::LLVMStartMultithreaded() != 1 {
                // use an extra bool to make sure that all future usage of LLVM
                // cannot proceed despite the Once not running more than once.
                POISONED.store(true, Ordering::SeqCst);
            }

            configure_llvm(sess);
        });

        if POISONED.load(Ordering::SeqCst) {
            bug!("couldn't enable multi-threaded LLVM");
        }
    }
}

fn require_inited() {
    INIT.call_once(|| bug!("llvm is not initialized"));
    if POISONED.load(Ordering::SeqCst) {
        bug!("couldn't enable multi-threaded LLVM");
    }
}

unsafe fn configure_llvm(sess: &Session) {
    let mut llvm_c_strs = Vec::new();
    let mut llvm_args = Vec::new();

    {
        let mut add = |arg: &str| {
            let s = CString::new(arg).unwrap();
            llvm_args.push(s.as_ptr());
            llvm_c_strs.push(s);
        };
        add("rustc"); // fake program name
        if sess.time_llvm_passes() { add("-time-passes"); }
        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }

        for arg in &sess.opts.cg.llvm_args {
            add(&(*arg));
        }
    }

    llvm::LLVMInitializePasses();

    llvm::initialize_available_targets();

    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                 llvm_args.as_ptr());
}

// WARNING: the features must be known to LLVM or the feature
// detection code will walk past the end of the feature array,
// leading to crashes.

const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "v7\0", "vfp2\0", "vfp3\0", "vfp4\0"];

const AARCH64_WHITELIST: &'static [&'static str] = &["neon\0", "v7\0"];

const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
                                                 "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
                                                 "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0",
                                                 "xsave\0", "xsaveopt\0", "xsavec\0",
                                                 "xsaves\0", "aes\0", "pclmul\0",
                                                 "avx512bw\0", "avx512cd\0",
                                                 "avx512dq\0", "avx512er\0",
                                                 "avx512f\0", "avx512ifma\0",
                                                 "avx512pf\0", "avx512vbmi\0",
                                                 "avx512vl\0", "avx512vpopcntdq\0",
                                                 "mmx\0", "fxsr\0"];

const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];

const POWERPC_WHITELIST: &'static [&'static str] = &["altivec\0",
                                                     "power8-altivec\0", "power9-altivec\0",
                                                     "power8-vector\0", "power9-vector\0",
                                                     "vsx\0"];

const MIPS_WHITELIST: &'static [&'static str] = &["msa\0"];

pub fn target_features(sess: &Session) -> Vec<Symbol> {
    let whitelist = target_feature_whitelist(sess);
    let target_machine = create_target_machine(sess);
    let mut features = Vec::new();
    for feat in whitelist {
        if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr()) } {
            features.push(Symbol::intern(feat.to_str().unwrap()));
        }
    }
    features
}

pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
    let whitelist = match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "aarch64" => AARCH64_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        "hexagon" => HEXAGON_WHITELIST,
        "mips" | "mips64" => MIPS_WHITELIST,
        "powerpc" | "powerpc64" => POWERPC_WHITELIST,
        _ => &[],
    };
    whitelist.iter().map(|m| {
        CStr::from_bytes_with_nul(m.as_bytes()).unwrap()
    }).collect()
}

pub fn print_version() {
    // Can be called without initializing LLVM
    unsafe {
        println!("LLVM version: {}.{}",
                 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
    }
}

pub fn print_passes() {
    // Can be called without initializing LLVM
    unsafe { llvm::LLVMRustPrintPasses(); }
}

pub(crate) fn print(req: PrintRequest, sess: &Session) {
    require_inited();
    let tm = create_target_machine(sess);
    unsafe {
        match req {
            PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
            PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
            _ => bug!("rustc_trans can't handle print request: {:?}", req),
        }
    }
}
<|endoftext|>


<commit_before>//! CSS funciri values.

use cssparser::Parser;

use crate::document::NodeId;
use crate::error::*;
use crate::parsers::Parse;

/// Used where style properties take a funciri or "none"
///
/// This is not to be used for values which don't come from properties.
/// For example, the `xlink:href` attribute in the `<image>` element
/// does not take a funciri value (which looks like `url(...)`), but rather
/// it takes a plain URL.
#[derive(Debug, Clone, PartialEq)]
pub enum Iri {
    None,
    Resource(Box<NodeId>),
}

impl Default for Iri {
    fn default() -> Iri {
        Iri::None
    }
}

impl Iri {
    /// Returns the contents of an `IRI::Resource`, or `None`
    pub fn get(&self) -> Option<&NodeId> {
        match *self {
            Iri::None => None,
            Iri::Resource(ref f) => Some(&*f),
        }
    }
}

impl Parse for Iri {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Iri, ParseError<'i>> {
        if parser
            .try_parse(|i| i.expect_ident_matching("none"))
            .is_ok()
        {
            Ok(Iri::None)
        } else {
            let loc = parser.current_source_location();
            let url = parser.expect_url()?;
            let node_id =
                NodeId::parse(&url).map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?;

            Ok(Iri::Resource(Box::new(node_id)))
        }
    }
}

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

    #[test]
    fn parses_none() {
        assert_eq!(Iri::parse_str("none").unwrap(), Iri::None);
    }

    #[test]
    fn parses_url() {
        assert_eq!(
            Iri::parse_str("url(#bar)").unwrap(),
            Iri::Resource(Box::new(NodeId::Internal("bar".to_string())))
        );

        assert_eq!(
            Iri::parse_str("url(foo#bar)").unwrap(),
            Iri::Resource(Box::new(NodeId::External(
                "foo".to_string(),
                "bar".to_string()
            )))
        );

        // be permissive if the closing ) is missing
        assert_eq!(
            Iri::parse_str("url(#bar").unwrap(),
            Iri::Resource(Box::new(NodeId::Internal("bar".to_string())))
        );
        assert_eq!(
            Iri::parse_str("url(foo#bar").unwrap(),
            Iri::Resource(Box::new(NodeId::External(
                "foo".to_string(),
                "bar".to_string()
            )))
        );

        assert!(Iri::parse_str("").is_err());
        assert!(Iri::parse_str("foo").is_err());
        assert!(Iri::parse_str("url(foo)bar").is_err());
    }
}
<commit_msg>Iri does not need to implement Default<commit_after>//! CSS funciri values.

use cssparser::Parser;

use crate::document::NodeId;
use crate::error::*;
use crate::parsers::Parse;

/// Used where style properties take a funciri or "none"
///
/// This is not to be used for values which don't come from properties.
/// For example, the `xlink:href` attribute in the `<image>` element
/// does not take a funciri value (which looks like `url(...)`), but rather
/// it takes a plain URL.
#[derive(Debug, Clone, PartialEq)]
pub enum Iri {
    None,
    Resource(Box<NodeId>),
}

impl Iri {
    /// Returns the contents of an `IRI::Resource`, or `None`
    pub fn get(&self) -> Option<&NodeId> {
        match *self {
            Iri::None => None,
            Iri::Resource(ref f) => Some(&*f),
        }
    }
}

impl Parse for Iri {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Iri, ParseError<'i>> {
        if parser
            .try_parse(|i| i.expect_ident_matching("none"))
            .is_ok()
        {
            Ok(Iri::None)
        } else {
            let loc = parser.current_source_location();
            let url = parser.expect_url()?;
            let node_id =
                NodeId::parse(&url).map_err(|e| loc.new_custom_error(ValueErrorKind::from(e)))?;

            Ok(Iri::Resource(Box::new(node_id)))
        }
    }
}

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

    #[test]
    fn parses_none() {
        assert_eq!(Iri::parse_str("none").unwrap(), Iri::None);
    }

    #[test]
    fn parses_url() {
        assert_eq!(
            Iri::parse_str("url(#bar)").unwrap(),
            Iri::Resource(Box::new(NodeId::Internal("bar".to_string())))
        );

        assert_eq!(
            Iri::parse_str("url(foo#bar)").unwrap(),
            Iri::Resource(Box::new(NodeId::External(
                "foo".to_string(),
                "bar".to_string()
            )))
        );

        // be permissive if the closing ) is missing
        assert_eq!(
            Iri::parse_str("url(#bar").unwrap(),
            Iri::Resource(Box::new(NodeId::Internal("bar".to_string())))
        );
        assert_eq!(
            Iri::parse_str("url(foo#bar").unwrap(),
            Iri::Resource(Box::new(NodeId::External(
                "foo".to_string(),
                "bar".to_string()
            )))
        );

        assert!(Iri::parse_str("").is_err());
        assert!(Iri::parse_str("foo").is_err());
        assert!(Iri::parse_str("url(foo)bar").is_err());
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[deny(missing_docs)]

extern crate gfx;
extern crate gfx_device_gl;
extern crate glutin;

use gfx::tex::Size;

/// A wrapper around the window that implements `Output`.
pub struct Wrap<R: gfx::Resources> {
    /// Glutin window in the open.
    pub window: glutin::Window,
    frame: gfx::FrameBufferHandle<R>,
    mask: gfx::Mask,
    gamma: gfx::Gamma,
}

impl<R: gfx::Resources> gfx::Output<R> for Wrap<R> {
    fn get_handle(&self) -> Option<&gfx::FrameBufferHandle<R>> {
        Some(&self.frame)
    }

    fn get_size(&self) -> (Size, Size) {
        let (w, h) = self.window.get_inner_size().unwrap_or((0, 0));
        (w as Size, h as Size)
    }

    fn get_mask(&self) -> gfx::Mask {
        self.mask
    }

    fn get_gamma(&self) -> gfx::Gamma {
        self.gamma
    }
}

/// Result of successful context initialization.
pub type Success = (
    Wrap<gfx_device_gl::Resources>,
    gfx_device_gl::Device,
    gfx_device_gl::Factory,
);

/// Initialize with a window builder.
pub fn init<'a>(builder: glutin::WindowBuilder<'a>)
            -> Result<Success, glutin::CreationError>
{
    let (mask, srgb) = {
        let attribs = builder.get_attributes();
        //let mut mask = gfx::Mask::empty(); // need Glutin to really expose defaults
        let mut mask = gfx::COLOR | gfx::DEPTH | gfx::STENCIL;
        match attribs.color_bits {
            Some(b) if b>0 => mask.insert(gfx::COLOR),
            _ => (),
        }
        match attribs.depth_bits {
            Some(b) if b>0 => mask.insert(gfx::DEPTH),
            _ => (),
        }
        match attribs.stencil_bits {
            Some(b) if b>0 => mask.insert(gfx::STENCIL),
            _ => (),
        }
        (mask, attribs.srgb == Some(true))
    };
    // create window
    builder.build().map(|window| {
        unsafe { window.make_current() };
        let (device, factory) = gfx_device_gl::create(|s| window.get_proc_address(s));
        let wrap = Wrap {
            window: window,
            frame: factory.get_main_frame_buffer(),
            mask: mask,
            gamma: if srgb {gfx::Gamma::Convert} else {gfx::Gamma::Original},
        };
        (wrap, device, factory)
    })
}

/// Initialize with just a title string.
pub fn init_titled(title: &str) -> Result<Success, glutin::CreationError>
{
    let builder = glutin::WindowBuilder::new()
        .with_title(title.to_string());
    init(builder)
}
<commit_msg>Changed to work with Glutin Window instead of WindowBuilder<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[deny(missing_docs)]

extern crate gfx;
extern crate gfx_device_gl;
extern crate glutin;

use gfx::tex::Size;

/// A wrapper around the window that implements `Output`.
pub struct Wrap<R: gfx::Resources> {
    /// Glutin window in the open.
    pub window: glutin::Window,
    frame: gfx::FrameBufferHandle<R>,
    mask: gfx::Mask,
    gamma: gfx::Gamma,
}

impl<R: gfx::Resources> gfx::Output<R> for Wrap<R> {
    fn get_handle(&self) -> Option<&gfx::FrameBufferHandle<R>> {
        Some(&self.frame)
    }

    fn get_size(&self) -> (Size, Size) {
        let (w, h) = self.window.get_inner_size().unwrap_or((0, 0));
        (w as Size, h as Size)
    }

    fn get_mask(&self) -> gfx::Mask {
        self.mask
    }

    fn get_gamma(&self) -> gfx::Gamma {
        self.gamma
    }
}

/// Result of successful context initialization.
pub type Success = (
    Wrap<gfx_device_gl::Resources>,
    gfx_device_gl::Device,
    gfx_device_gl::Factory,
);

/// Initialize with a window.
pub fn init(window: glutin::Window) -> Success {
    // actual queries are WIP: https://github.com/tomaka/glutin/pull/372
    unsafe { window.make_current() };
    let (device, factory) = gfx_device_gl::create(|s| window.get_proc_address(s));
    let wrap = Wrap {
        window: window,
        frame: factory.get_main_frame_buffer(),
        mask: gfx::COLOR | gfx::DEPTH | gfx::STENCIL, //TODO
        gamma: gfx::Gamma::Original, //TODO
    };
    (wrap, device, factory)
}
<|endoftext|>


<commit_before>//! Point ABSTraction library in Rust.
//!
//! This library is inspired by [PDAL](http://www.pdal.io/), which provides both point abstraction
//! and a wide range of other abilitiles. **Pabst** hopes to keep its focus more narrow. We provide
//! source and sink abstractions for LiDAR point cloud file and stream formats. Other libraries
//! should be used to provide intermediate functionality.

extern crate las;
#[cfg(feature = "rxp")]
extern crate rivlib;

pub mod error;
pub mod point;
pub mod source;
pub mod sink;

use std::result;

pub type Result<T> = result::Result<T, error::Error>;
<commit_msg>Re-export source, sink, point, and error<commit_after>//! Point ABSTraction library in Rust.
//!
//! This library is inspired by [PDAL](http://www.pdal.io/), which provides both point abstraction
//! and a wide range of other abilitiles. **Pabst** hopes to keep its focus more narrow. We provide
//! source and sink abstractions for LiDAR point cloud file and stream formats. Other libraries
//! should be used to provide intermediate functionality.

extern crate las;
#[cfg(feature = "rxp")]
extern crate rivlib;

pub mod error;
pub mod point;
pub mod source;
pub mod sink;

pub use error::Error;
pub use point::Point;
pub use source::Source;
pub use sink::Sink;

use std::result;

pub type Result<T> = result::Result<T, error::Error>;
<|endoftext|>


<commit_before>extern crate fixedbitset;
extern crate rand;

use fixedbitset::FixedBitSet;
use rand::Rng;
use std::collections::BTreeMap;
use std::fmt::Debug;

pub trait NodeType: Clone + Debug {
    /// If the node allows incoming connections
    fn accept_incoming_links(&self) -> bool;

    /// If the node allows outgoing connections
    fn accept_outgoing_links(&self) -> bool;
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
/// New type wrapping a node index.
pub struct NodeIndex(usize);

impl NodeIndex {
    pub fn new(idx: usize) -> NodeIndex {
        NodeIndex(idx)
    }

    pub fn index(&self) -> usize {
        self.0
    }
}

#[derive(Clone, Debug)]
pub struct Link<W: Clone + Debug> {
    pub node_idx: NodeIndex,
    pub weight: W,
}

#[derive(Clone, Debug)]
pub struct Node<NT: NodeType, N: Clone + Debug, W: Clone + Debug> {
    pub node_type: NT,
    pub node_data: N,
    pub input_links: Vec<Link<W>>,
    pub output_links: Vec<Link<W>>,
}

struct CycleDetector<'a, NT: NodeType + 'a, N: Clone + Debug + 'a, W: Clone + Debug + 'a> {
    nodes: &'a [Node<NT, N, W>],
    nodes_to_visit: Vec<usize>,
    seen_nodes: FixedBitSet,
    dirty: bool,
}

impl<'a, NT: NodeType + 'a, N: Clone + Debug + 'a, W: Clone + Debug + 'a> CycleDetector<'a,
                                                                                NT,
                                                                                N,
                                                                                W>
    {
    fn new(network: &'a Network<NT, N, W>) -> CycleDetector<'a, NT, N, W> {
        CycleDetector {
            nodes: &network.nodes,
            nodes_to_visit: Vec::new(),
            seen_nodes: FixedBitSet::with_capacity(network.nodes.len()),
            dirty: false,
        }
    }

    // The algorithm used in `Network.link_would_cycle` and
    // `Network.find_random_unconnected_link_no_cycle`.  This is mostly extracted to avoid
    // repetetive memory allocations in `find_random_unconnected_link_no_cycle`.
    fn link_would_cycle(&mut self, source_node_idx: NodeIndex, target_node_idx: NodeIndex) -> bool {
        let path_from = target_node_idx.index();
        let path_to = source_node_idx.index();

        assert!(path_from != path_to);

        let nodes = self.nodes;
        let mut nodes_to_visit = &mut self.nodes_to_visit;
        let mut seen_nodes = &mut self.seen_nodes;

        if self.dirty {
            nodes_to_visit.clear();
            seen_nodes.clear();
        }
        self.dirty = true;

        // We start at the from the target_node and iterate all paths from there. If we hit the source node,
        // the addition of this link would lead towards a cycle. Otherwise not.
        nodes_to_visit.push(path_from);
        seen_nodes.insert(path_from);

        while let Some(visit_node) = nodes_to_visit.pop() {
            for out_link in &nodes[visit_node].output_links {
                let next_node = out_link.node_idx.index();
                if !seen_nodes.contains(next_node) {
                    if next_node == path_to {
                        // We found a path to `path_to`. We have found a cycle.
                        return true;
                    }

                    seen_nodes.insert(next_node);
                    nodes_to_visit.push(next_node)
                }
            }
        }

        // We haven't found a cycle.
        return false;
    }
}

#[derive(Clone, Debug)]
pub struct Network<NT: NodeType, N: Clone + Debug, W: Clone + Debug> {
    nodes: Vec<Node<NT, N, W>>,
}

impl<NT: NodeType, N: Clone + Debug, W: Clone + Debug> Network<NT, N, W> {
    pub fn new() -> Network<NT, N, W> {
        Network { nodes: Vec::new() }
    }

    pub fn nodes(&self) -> &[Node<NT, N, W>] {
        &self.nodes
    }

    pub fn add_node(&mut self, node_type: NT, node_data: N) -> NodeIndex {
        let idx = NodeIndex(self.nodes.len());
        self.nodes.push(Node {
            node_type: node_type,
            node_data: node_data,
            input_links: Vec::new(),
            output_links: Vec::new(),
        });
        return idx;
    }

    /// Returns a random link between two unconnected nodes, which would not introduce
    /// a cycle. Return None is no such exists.
    pub fn find_random_unconnected_link_no_cycle<R: Rng>(&self,
                                                         rng: &mut R)
                                                         -> Option<(NodeIndex, NodeIndex)> {

        let n = self.nodes.len();

        let idx = &|i, j| i * n + j;

        let mut adj_matrix = FixedBitSet::with_capacity(n * n);

        // Build up a binary, undirected adjacency matrix of the graph.
        // Every unset bit in the adj_matrix will be a potential link.
        for (i, node) in self.nodes.iter().enumerate() {
            for link in node.output_links.iter() {
                let j = link.node_idx.index();
                adj_matrix.insert(idx(i, j));
                // include the link of reverse direction, because this would
                // create a cycle anyway.
                adj_matrix.insert(idx(j, i));
            }
        }

        let adj_matrix = adj_matrix; // make immutable

        // We now test all potential links of every node in the graph, if it would
        // introduce a cycle. For that, we shuffle the node indices (`node_order`).
        // in random order.
        let mut node_order: Vec<_> = (0..n).into_iter().collect();
        let mut edge_order: Vec<_> = (0..n).into_iter().collect();
        rng.shuffle(&mut node_order);

        let node_order = node_order; // make immutable

        let mut cycler = CycleDetector::new(self);
        for &i in &node_order {
            rng.shuffle(&mut edge_order);
            for &j in &edge_order {
                if i != j && !adj_matrix.contains(idx(i, j)) {
                    // The link (i, j) neither is reflexive, nor exists.
                    let ni = NodeIndex(i);
                    let nj = NodeIndex(j);
                    if self.valid_link(ni, nj).is_ok() && !cycler.link_would_cycle(ni, nj) {
                        // If the link is valid and does not create a cycle, we are done!
                        return Some((ni, nj));
                    }
                }
            }
        }

        return None;
    }

    /// Returns true if the introduction of this directed link would lead towards a cycle.
    pub fn link_would_cycle(&self, source_node_idx: NodeIndex, target_node_idx: NodeIndex) -> bool {
        if source_node_idx == target_node_idx {
            return true;
        }

        CycleDetector::new(self).link_would_cycle(source_node_idx, target_node_idx)
    }

    // Check if the link is valid. Doesn't check for cycles.
    pub fn valid_link(&self,
                      source_node_idx: NodeIndex,
                      target_node_idx: NodeIndex)
                      -> Result<(), &'static str> {
        if source_node_idx == target_node_idx {
            return Err("Loops are not allowed");
        }

        if !self.nodes[source_node_idx.index()].node_type.accept_outgoing_links() {
            return Err("Node does not allow outgoing links");
        }

        if !self.nodes[target_node_idx.index()].node_type.accept_incoming_links() {
            return Err("Node does not allow incoming links");
        }

        Ok(())
    }

    // Note: Doesn't check for cycles (except in the simple reflexive case).
    pub fn add_link(&mut self, source_node_idx: NodeIndex, target_node_idx: NodeIndex, weight: W) {
        if let Err(err) = self.valid_link(source_node_idx, target_node_idx) {
            panic!(err);
        }

        self.nodes[source_node_idx.index()].output_links.push(Link {
            node_idx: target_node_idx,
            weight: weight.clone(),
        });

        self.nodes[target_node_idx.index()].input_links.push(Link {
            node_idx: source_node_idx,
            weight: weight,
        });
    }
}

#[derive(Clone, Debug)]
pub struct NetworkMap<NKEY: Ord + Clone + Debug, NT: NodeType, N: Clone + Debug, W: Clone + Debug> {
    network: Network<NT, N, W>,
    node_map: BTreeMap<NKEY, NodeIndex>,
    node_map_rev: BTreeMap<NodeIndex, NKEY>,
}

impl<NKEY: Ord + Clone + Debug, NT: NodeType, N: Clone + Debug, W: Clone + Debug> NetworkMap<NKEY,
                                                                                NT,
                                                                                N,
                                                                                W>
    {
    pub fn new() -> NetworkMap<NKEY, NT, N, W> {
        NetworkMap {
            network: Network::new(),
            node_map: BTreeMap::new(),
            node_map_rev: BTreeMap::new(),
        }
    }

    pub fn nodes(&self) -> &[Node<NT, N, W>] {
        self.network.nodes()
    }

    /// Registers/creates a new node under the external key `node_key`.
    /// Panics if a node with `node_key` already exists.
    pub fn add_node(&mut self, node_key: NKEY, node_type: NT, node_data: N) {
        // XXX: Use node_map.entry()
        if self.node_map.contains_key(&node_key) {
            panic!("Duplicate node index");
        }
        let idx = self.network.add_node(node_type, node_data);
        self.node_map.insert(node_key.clone(), idx);
        // self.node_map_rev.insert(idx, node_key);
    }

    /// Returns a random link between two unconnected nodes, which would not introduce
    /// a cycle. Return None is no such exists.
    pub fn find_random_unconnected_link_no_cycle<R: Rng>(&self,
                                                         rng: &mut R)
                                                         -> Option<(&NKEY, &NKEY)> {
        match self.network.find_random_unconnected_link_no_cycle(rng) {
            Some((a, b)) => Some((&self.node_map_rev[&a], &self.node_map_rev[&b])),
            None => None,
        }
    }

    /// Returns true if the introduction of this directed link would lead towards a cycle.
    pub fn link_would_cycle(&self, source_node_key: NKEY, target_node_key: NKEY) -> bool {
        self.network.link_would_cycle(self.node_map[&source_node_key],
                                      self.node_map[&target_node_key])
    }

    // Check if the link is valid. Doesn't check for cycles.
    pub fn valid_link(&self,
                      source_node_key: NKEY,
                      target_node_key: NKEY)
                      -> Result<(), &'static str> {
        self.network.valid_link(self.node_map[&source_node_key],
                                self.node_map[&target_node_key])
    }

    // Note: Doesn't check for cycles (except in the simple reflexive case).
    pub fn add_link(&mut self, source_node_key: NKEY, target_node_key: NKEY, weight: W) {
        self.network.add_link(self.node_map[&source_node_key],
                              self.node_map[&target_node_key],
                              weight)
    }
}

#[cfg(test)]
mod tests {
    use rand;
    use super::{NodeType, Network};

    #[derive(Clone, Debug)]
    enum NodeT {
        Input,
        Hidden,
        Output,
    }

    impl NodeType for NodeT {
        fn accept_incoming_links(&self) -> bool {
            match *self {
                NodeT::Input => false,
                _ => true,
            }
        }
        fn accept_outgoing_links(&self) -> bool {
            match *self {
                NodeT::Output => false,
                _ => true,
            }
        }
    }

    #[test]
    fn test_cycle() {
        let mut g = Network::new();
        let i1 = g.add_node(NodeT::Input, ());
        let h1 = g.add_node(NodeT::Hidden, ());
        let h2 = g.add_node(NodeT::Hidden, ());
        assert_eq!(true, g.valid_link(i1, i1).is_err());
        assert_eq!(true, g.valid_link(h1, h1).is_err());

        assert_eq!(true, g.valid_link(h1, i1).is_err());
        assert_eq!(Ok(()), g.valid_link(i1, h1));
        assert_eq!(Ok(()), g.valid_link(i1, h2));
        assert_eq!(Ok(()), g.valid_link(h1, h2));

        g.add_link(i1, h1, 0.0);
        assert_eq!(true, g.link_would_cycle(h1, i1));
        assert_eq!(false, g.link_would_cycle(i1, h1));
        assert_eq!(false, g.link_would_cycle(i1, h2));
        assert_eq!(true, g.link_would_cycle(i1, i1));
        assert_eq!(false, g.link_would_cycle(h1, h2));
        assert_eq!(false, g.link_would_cycle(h2, h1));
        assert_eq!(false, g.link_would_cycle(h2, i1));

        g.add_link(h1, h2, 0.0);
        assert_eq!(true, g.link_would_cycle(h2, i1));
        assert_eq!(true, g.link_would_cycle(h1, i1));
        assert_eq!(true, g.link_would_cycle(h2, h1));
        assert_eq!(false, g.link_would_cycle(i1, h2));
    }

    #[test]
    fn test_find_random_unconnected_link_no_cycle() {
        let mut g = Network::new();
        let i1 = g.add_node(NodeT::Input, ());
        let o1 = g.add_node(NodeT::Output, ());
        let o2 = g.add_node(NodeT::Output, ());

        let mut rng = rand::thread_rng();

        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(true, link.is_some());
        let l = link.unwrap();
        assert!((i1, o1) == l || (i1, o2) == l);

        g.add_link(i1, o2, 0.0);
        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(true, link.is_some());
        assert_eq!((i1, o1), link.unwrap());

        g.add_link(i1, o1, 0.0);
        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(false, link.is_some());
    }
}
<commit_msg>Add missing node_map_rev entry<commit_after>extern crate fixedbitset;
extern crate rand;

use fixedbitset::FixedBitSet;
use rand::Rng;
use std::collections::BTreeMap;
use std::fmt::Debug;

pub trait NodeType: Clone + Debug {
    /// If the node allows incoming connections
    fn accept_incoming_links(&self) -> bool;

    /// If the node allows outgoing connections
    fn accept_outgoing_links(&self) -> bool;
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
/// New type wrapping a node index.
pub struct NodeIndex(usize);

impl NodeIndex {
    pub fn new(idx: usize) -> NodeIndex {
        NodeIndex(idx)
    }

    pub fn index(&self) -> usize {
        self.0
    }
}

#[derive(Clone, Debug)]
pub struct Link<W: Clone + Debug> {
    pub node_idx: NodeIndex,
    pub weight: W,
}

#[derive(Clone, Debug)]
pub struct Node<NT: NodeType, N: Clone + Debug, W: Clone + Debug> {
    pub node_type: NT,
    pub node_data: N,
    pub input_links: Vec<Link<W>>,
    pub output_links: Vec<Link<W>>,
}

struct CycleDetector<'a, NT: NodeType + 'a, N: Clone + Debug + 'a, W: Clone + Debug + 'a> {
    nodes: &'a [Node<NT, N, W>],
    nodes_to_visit: Vec<usize>,
    seen_nodes: FixedBitSet,
    dirty: bool,
}

impl<'a, NT: NodeType + 'a, N: Clone + Debug + 'a, W: Clone + Debug + 'a> CycleDetector<'a,
                                                                                NT,
                                                                                N,
                                                                                W>
    {
    fn new(network: &'a Network<NT, N, W>) -> CycleDetector<'a, NT, N, W> {
        CycleDetector {
            nodes: &network.nodes,
            nodes_to_visit: Vec::new(),
            seen_nodes: FixedBitSet::with_capacity(network.nodes.len()),
            dirty: false,
        }
    }

    // The algorithm used in `Network.link_would_cycle` and
    // `Network.find_random_unconnected_link_no_cycle`.  This is mostly extracted to avoid
    // repetetive memory allocations in `find_random_unconnected_link_no_cycle`.
    fn link_would_cycle(&mut self, source_node_idx: NodeIndex, target_node_idx: NodeIndex) -> bool {
        let path_from = target_node_idx.index();
        let path_to = source_node_idx.index();

        assert!(path_from != path_to);

        let nodes = self.nodes;
        let mut nodes_to_visit = &mut self.nodes_to_visit;
        let mut seen_nodes = &mut self.seen_nodes;

        if self.dirty {
            nodes_to_visit.clear();
            seen_nodes.clear();
        }
        self.dirty = true;

        // We start at the from the target_node and iterate all paths from there. If we hit the source node,
        // the addition of this link would lead towards a cycle. Otherwise not.
        nodes_to_visit.push(path_from);
        seen_nodes.insert(path_from);

        while let Some(visit_node) = nodes_to_visit.pop() {
            for out_link in &nodes[visit_node].output_links {
                let next_node = out_link.node_idx.index();
                if !seen_nodes.contains(next_node) {
                    if next_node == path_to {
                        // We found a path to `path_to`. We have found a cycle.
                        return true;
                    }

                    seen_nodes.insert(next_node);
                    nodes_to_visit.push(next_node)
                }
            }
        }

        // We haven't found a cycle.
        return false;
    }
}

#[derive(Clone, Debug)]
pub struct Network<NT: NodeType, N: Clone + Debug, W: Clone + Debug> {
    nodes: Vec<Node<NT, N, W>>,
}

impl<NT: NodeType, N: Clone + Debug, W: Clone + Debug> Network<NT, N, W> {
    pub fn new() -> Network<NT, N, W> {
        Network { nodes: Vec::new() }
    }

    pub fn nodes(&self) -> &[Node<NT, N, W>] {
        &self.nodes
    }

    pub fn add_node(&mut self, node_type: NT, node_data: N) -> NodeIndex {
        let idx = NodeIndex(self.nodes.len());
        self.nodes.push(Node {
            node_type: node_type,
            node_data: node_data,
            input_links: Vec::new(),
            output_links: Vec::new(),
        });
        return idx;
    }

    /// Returns a random link between two unconnected nodes, which would not introduce
    /// a cycle. Return None is no such exists.
    pub fn find_random_unconnected_link_no_cycle<R: Rng>(&self,
                                                         rng: &mut R)
                                                         -> Option<(NodeIndex, NodeIndex)> {

        let n = self.nodes.len();

        let idx = &|i, j| i * n + j;

        let mut adj_matrix = FixedBitSet::with_capacity(n * n);

        // Build up a binary, undirected adjacency matrix of the graph.
        // Every unset bit in the adj_matrix will be a potential link.
        for (i, node) in self.nodes.iter().enumerate() {
            for link in node.output_links.iter() {
                let j = link.node_idx.index();
                adj_matrix.insert(idx(i, j));
                // include the link of reverse direction, because this would
                // create a cycle anyway.
                adj_matrix.insert(idx(j, i));
            }
        }

        let adj_matrix = adj_matrix; // make immutable

        // We now test all potential links of every node in the graph, if it would
        // introduce a cycle. For that, we shuffle the node indices (`node_order`).
        // in random order.
        let mut node_order: Vec<_> = (0..n).into_iter().collect();
        let mut edge_order: Vec<_> = (0..n).into_iter().collect();
        rng.shuffle(&mut node_order);

        let node_order = node_order; // make immutable

        let mut cycler = CycleDetector::new(self);
        for &i in &node_order {
            rng.shuffle(&mut edge_order);
            for &j in &edge_order {
                if i != j && !adj_matrix.contains(idx(i, j)) {
                    // The link (i, j) neither is reflexive, nor exists.
                    let ni = NodeIndex(i);
                    let nj = NodeIndex(j);
                    if self.valid_link(ni, nj).is_ok() && !cycler.link_would_cycle(ni, nj) {
                        // If the link is valid and does not create a cycle, we are done!
                        return Some((ni, nj));
                    }
                }
            }
        }

        return None;
    }

    /// Returns true if the introduction of this directed link would lead towards a cycle.
    pub fn link_would_cycle(&self, source_node_idx: NodeIndex, target_node_idx: NodeIndex) -> bool {
        if source_node_idx == target_node_idx {
            return true;
        }

        CycleDetector::new(self).link_would_cycle(source_node_idx, target_node_idx)
    }

    // Check if the link is valid. Doesn't check for cycles.
    pub fn valid_link(&self,
                      source_node_idx: NodeIndex,
                      target_node_idx: NodeIndex)
                      -> Result<(), &'static str> {
        if source_node_idx == target_node_idx {
            return Err("Loops are not allowed");
        }

        if !self.nodes[source_node_idx.index()].node_type.accept_outgoing_links() {
            return Err("Node does not allow outgoing links");
        }

        if !self.nodes[target_node_idx.index()].node_type.accept_incoming_links() {
            return Err("Node does not allow incoming links");
        }

        Ok(())
    }

    // Note: Doesn't check for cycles (except in the simple reflexive case).
    pub fn add_link(&mut self, source_node_idx: NodeIndex, target_node_idx: NodeIndex, weight: W) {
        if let Err(err) = self.valid_link(source_node_idx, target_node_idx) {
            panic!(err);
        }

        self.nodes[source_node_idx.index()].output_links.push(Link {
            node_idx: target_node_idx,
            weight: weight.clone(),
        });

        self.nodes[target_node_idx.index()].input_links.push(Link {
            node_idx: source_node_idx,
            weight: weight,
        });
    }
}

#[derive(Clone, Debug)]
pub struct NetworkMap<NKEY: Ord + Clone + Debug, NT: NodeType, N: Clone + Debug, W: Clone + Debug> {
    network: Network<NT, N, W>,
    node_map: BTreeMap<NKEY, NodeIndex>,
    node_map_rev: BTreeMap<NodeIndex, NKEY>,
}

impl<NKEY: Ord + Clone + Debug, NT: NodeType, N: Clone + Debug, W: Clone + Debug> NetworkMap<NKEY,
                                                                                NT,
                                                                                N,
                                                                                W>
    {
    pub fn new() -> NetworkMap<NKEY, NT, N, W> {
        NetworkMap {
            network: Network::new(),
            node_map: BTreeMap::new(),
            node_map_rev: BTreeMap::new(),
        }
    }

    pub fn nodes(&self) -> &[Node<NT, N, W>] {
        self.network.nodes()
    }

    /// Registers/creates a new node under the external key `node_key`.
    /// Panics if a node with `node_key` already exists.
    pub fn add_node(&mut self, node_key: NKEY, node_type: NT, node_data: N) {
        // XXX: Use node_map.entry()
        if self.node_map.contains_key(&node_key) {
            panic!("Duplicate node index");
        }
        let idx = self.network.add_node(node_type, node_data);
        self.node_map.insert(node_key.clone(), idx);
        self.node_map_rev.insert(idx, node_key);
    }

    /// Returns a random link between two unconnected nodes, which would not introduce
    /// a cycle. Return None is no such exists.
    pub fn find_random_unconnected_link_no_cycle<R: Rng>(&self,
                                                         rng: &mut R)
                                                         -> Option<(&NKEY, &NKEY)> {
        match self.network.find_random_unconnected_link_no_cycle(rng) {
            Some((a, b)) => Some((&self.node_map_rev[&a], &self.node_map_rev[&b])),
            None => None,
        }
    }

    /// Returns true if the introduction of this directed link would lead towards a cycle.
    pub fn link_would_cycle(&self, source_node_key: NKEY, target_node_key: NKEY) -> bool {
        self.network.link_would_cycle(self.node_map[&source_node_key],
                                      self.node_map[&target_node_key])
    }

    // Check if the link is valid. Doesn't check for cycles.
    pub fn valid_link(&self,
                      source_node_key: NKEY,
                      target_node_key: NKEY)
                      -> Result<(), &'static str> {
        self.network.valid_link(self.node_map[&source_node_key],
                                self.node_map[&target_node_key])
    }

    // Note: Doesn't check for cycles (except in the simple reflexive case).
    pub fn add_link(&mut self, source_node_key: NKEY, target_node_key: NKEY, weight: W) {
        self.network.add_link(self.node_map[&source_node_key],
                              self.node_map[&target_node_key],
                              weight)
    }
}

#[cfg(test)]
mod tests {
    use rand;
    use super::{NodeType, Network};

    #[derive(Clone, Debug)]
    enum NodeT {
        Input,
        Hidden,
        Output,
    }

    impl NodeType for NodeT {
        fn accept_incoming_links(&self) -> bool {
            match *self {
                NodeT::Input => false,
                _ => true,
            }
        }
        fn accept_outgoing_links(&self) -> bool {
            match *self {
                NodeT::Output => false,
                _ => true,
            }
        }
    }

    #[test]
    fn test_cycle() {
        let mut g = Network::new();
        let i1 = g.add_node(NodeT::Input, ());
        let h1 = g.add_node(NodeT::Hidden, ());
        let h2 = g.add_node(NodeT::Hidden, ());
        assert_eq!(true, g.valid_link(i1, i1).is_err());
        assert_eq!(true, g.valid_link(h1, h1).is_err());

        assert_eq!(true, g.valid_link(h1, i1).is_err());
        assert_eq!(Ok(()), g.valid_link(i1, h1));
        assert_eq!(Ok(()), g.valid_link(i1, h2));
        assert_eq!(Ok(()), g.valid_link(h1, h2));

        g.add_link(i1, h1, 0.0);
        assert_eq!(true, g.link_would_cycle(h1, i1));
        assert_eq!(false, g.link_would_cycle(i1, h1));
        assert_eq!(false, g.link_would_cycle(i1, h2));
        assert_eq!(true, g.link_would_cycle(i1, i1));
        assert_eq!(false, g.link_would_cycle(h1, h2));
        assert_eq!(false, g.link_would_cycle(h2, h1));
        assert_eq!(false, g.link_would_cycle(h2, i1));

        g.add_link(h1, h2, 0.0);
        assert_eq!(true, g.link_would_cycle(h2, i1));
        assert_eq!(true, g.link_would_cycle(h1, i1));
        assert_eq!(true, g.link_would_cycle(h2, h1));
        assert_eq!(false, g.link_would_cycle(i1, h2));
    }

    #[test]
    fn test_find_random_unconnected_link_no_cycle() {
        let mut g = Network::new();
        let i1 = g.add_node(NodeT::Input, ());
        let o1 = g.add_node(NodeT::Output, ());
        let o2 = g.add_node(NodeT::Output, ());

        let mut rng = rand::thread_rng();

        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(true, link.is_some());
        let l = link.unwrap();
        assert!((i1, o1) == l || (i1, o2) == l);

        g.add_link(i1, o2, 0.0);
        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(true, link.is_some());
        assert_eq!((i1, o1), link.unwrap());

        g.add_link(i1, o1, 0.0);
        let link = g.find_random_unconnected_link_no_cycle(&mut rng);
        assert_eq!(false, link.is_some());
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Benjamin Fry <benjaminfry@me.com>

use std::ascii::AsciiExt;

/// returns true if and only if the phrase is a palindrome
///
/// # Arguments
///
/// * `phrase` - the phrase to inspect
///
/// This is just to be fun with iterators...
/// This should be O(2n), and would be fewer lines without all the comments.
pub fn is_palindrome(phrase: &str) -> bool {
    // remove all none alphabetic characters
    let chars: Vec<char> = phrase.chars().filter(|c| c.is_alphabetic()).collect();
    let half = (chars.len() as f32 / 2f32).ceil() as usize;

    // take the first half
    chars.iter().take(half)
                // zip with the second half...
                .zip(chars.iter()
                          // which needs to be reversed...
                          .rev()
                          // take the last half
                          .take(half))
                // check that all the chars from the begining and end match
                .all(|(first_char, last_char)| {
                    first_char.to_ascii_lowercase() == last_char.to_ascii_lowercase()
                })
}

/// this is a class array implementation (for comparison)
///
/// # Arguments
///
/// * `phrase` - the phrase to inspect
///
/// This is definitely not the most efficient, but is meant show the difference to above. And be
///  close to the semantics used in C/C++, with the exception of the chars().collect() this should
///  be O(2n) like above.
pub fn is_palindrome_classic(phrase: &str) -> bool {
    // remove all none alphabetic characters
    let mut chars: Vec<char> = Vec::with_capacity(phrase.len());

    // specifically not using some of Rust's nice features for this copy
    //  but need to use the iterator b/c the std library is removing direct access to the chars
    //  i.e. there are better ways to do this ;)
    let phrase: Vec<char> = phrase.chars().collect();
    for i in 0..phrase.len() {
        // annoyingly traking a separate index
        let c = phrase[i];
        // ok, using push, but still...
        if c.is_alphabetic() { chars.push(c) }
    }

    let half = (chars.len() as f32 / 2f32).ceil() as usize;

    // now do the looping comparison
    for i in 0..half {
        // ug, indexes
        if chars[i].to_ascii_lowercase() !=
           // here's a classic off by one error you don't get in the iterator model
           chars[chars.len() - i - 1].to_ascii_lowercase() { return false }
    }

    // is this actually simpler or more readable? I don't think so...

    true
}

#[test]
fn test_is_palindrome() {
    test_is_palindrome_base(is_palindrome);
}

#[test]
fn test_palindrome_classic() {
    test_is_palindrome_base(is_palindrome_classic);
}

#[cfg(test)]
fn test_is_palindrome_base<F>(is_palindrome: F) where F: Fn(&str) -> bool {
    assert!(is_palindrome(""));
    assert!(is_palindrome("A man, a plan, a canal, Panama!"));
    assert!(is_palindrome("Amor, Roma"));
    assert!(is_palindrome("race car"));
    assert!(is_palindrome("stack cats"));
    assert!(is_palindrome("step on no pets"));
    assert!(is_palindrome("taco cat"));
    assert!(is_palindrome("put it up"));
    assert!(is_palindrome("Was it a car or a cat I saw?"));
    assert!(is_palindrome("No ‘x’ in Nixon"));

    // negative for good messure
    assert!(!is_palindrome("Not a palindrome"))
}
<commit_msg>got rid of the initial filter<commit_after>// Copyright (C) 2016 Benjamin Fry <benjaminfry@me.com>

use std::ascii::AsciiExt;

/// returns true if and only if the phrase is a palindrome
///
/// # Arguments
///
/// * `phrase` - the phrase to inspect
///
/// This is just to be fun with iterators...
/// This should be O(n/2), and would be fewer lines without all the comments.
pub fn is_palindrome(phrase: &str) -> bool {
    let length = phrase.len();

    // get the chars iterator and associated index
    phrase.char_indices().filter(|&(_,c)| c.is_alphabetic())
                // zip with the second half...
                .zip(phrase.char_indices()
                           // which needs to be reversed...
                           .rev()
                           // and filter out bad cars
                           .filter(|&(_,c)| c.is_alphabetic()))
                // accept all input until the indexes have crossed
                .take_while(|&((first_count, _), (last_count, _))| first_count < length - last_count)
                // check that all the chars from the begining and end match
                .all(|((_, first_char), (_, last_char))| {
                    first_char.to_ascii_lowercase() == last_char.to_ascii_lowercase()
                })
}

/// this is a class array implementation (for comparison)
///
/// # Arguments
///
/// * `phrase` - the phrase to inspect
///
/// This is definitely not the most efficient, but is meant show the difference to above. And be
///  close to the semantics used in C/C++, with the exception of the chars().collect() this should
///  be O(n/2).
pub fn is_palindrome_classic(phrase: &str) -> bool {
    // need to do this because Rust is rightly trying to force you away from treating strs as
    //  arrays
    let phrase: Vec<char> = phrase.chars().collect();

    // start from the beginning
    let mut first_idx = 0;

    // and the end, btw, don't forget the off-by-one b/c of the
    let mut last_idx = phrase.len() - 1;
    // loop and guard that we don't go too far
    while first_idx < last_idx {
        // filter out non-alphabetics
        if !phrase[first_idx].is_alphabetic() { first_idx += 1; continue }
        if !phrase[last_idx].is_alphabetic() { last_idx -= 1; continue }

        // compare the values
        if phrase[first_idx].to_ascii_lowercase() != phrase[last_idx].to_ascii_lowercase() {
            return false;
        }

        first_idx += 1;
        last_idx -= 1;
    }

    // is this actually simpler or more readable? I don't think so...

    true
}

#[test]
fn test_is_palindrome() {
    test_is_palindrome_base(is_palindrome);
}

#[test]
fn test_palindrome_classic() {
    test_is_palindrome_base(is_palindrome_classic);
}

#[cfg(test)]
fn test_is_palindrome_base<F>(is_palindrome: F) where F: Fn(&str) -> bool {
    //assert!(is_palindrome(""));
    assert!(is_palindrome("race car"));
    assert!(is_palindrome("racecar"));
    assert!(is_palindrome("raccar"));
    assert!(is_palindrome("A man, a plan, a canal, Panama!"));
    assert!(is_palindrome("Amor, Roma"));
    assert!(is_palindrome("stack cats"));
    assert!(is_palindrome("step on no pets"));
    assert!(is_palindrome("taco cat"));
    assert!(is_palindrome("put it up"));
    assert!(is_palindrome("Was it a car or a cat I saw?"));
    assert!(is_palindrome("No ‘x’ in Nixon"));

    // negative for good messure
    assert!(!is_palindrome("Not a palindrome"))
}
<|endoftext|>


<commit_before>#![feature(net,io)]
extern crate time;
extern crate byteorder;

mod ntp;

use std::net::{UdpSocket, lookup_host, SocketAddr};
use time::Timespec;

const NTP_PORT: u16 = 123;
const UDP_LOCAL: &'static str = "0.0.0.0:35000";

/// `retrieve_ntp_timestamp` retrieves the current time from a NTP server.
///
/// # Arguments
///
/// * `host` - The NTP server (i.e. sundial.columbia.edu).
pub fn retrieve_ntp_timestamp(host: &str) -> Result<Timespec, std::io::Error> {
    let host = try!(lookup_host(host)).next().unwrap();
    let addr = SocketAddr::new(try!(host).ip(), NTP_PORT);
    let header = ntp::NTPHeader::new();
    let message = header.encode();

    let socket = try!(UdpSocket::bind(UDP_LOCAL));

    try!(socket.send_to(&message[..], &addr));

    let mut buf = [0u8; 1000];

    // TODO: Rust doesn't support timeouts yet
    let (amt, _) = try!(socket.recv_from(buf.as_mut_slice()));

    drop(socket);

    let header = ntp::NTPHeader::decode(amt, &buf);

    Ok(header.transmit_timestamp.as_timespec())
}

#[test]
fn receive_timestamp() {
    const NTP_SERVER: &'static str = "sundial.columbia.edu";

    let t1 = retrieve_ntp_timestamp(NTP_SERVER).unwrap();
    let t2 = retrieve_ntp_timestamp(NTP_SERVER).unwrap();

    assert!(t2 > t1);
}
<commit_msg>Rustup<commit_after>#![feature(net)]
extern crate time;
extern crate byteorder;

mod ntp;

use std::net::{UdpSocket, lookup_host, SocketAddr};
use time::Timespec;

const NTP_PORT: u16 = 123;
const UDP_LOCAL: &'static str = "0.0.0.0:35000";

/// `retrieve_ntp_timestamp` retrieves the current time from a NTP server.
///
/// # Arguments
///
/// * `host` - The NTP server (i.e. sundial.columbia.edu).
pub fn retrieve_ntp_timestamp(host: &str) -> Result<Timespec, std::io::Error> {
    let host = try!(lookup_host(host)).next().unwrap();
    let addr = SocketAddr::new(try!(host).ip(), NTP_PORT);
    let header = ntp::NTPHeader::new();
    let message = header.encode();

    let socket = try!(UdpSocket::bind(UDP_LOCAL));

    try!(socket.send_to(&message[..], &addr));

    let mut buf = [0u8; 1000];

    // TODO: Rust doesn't support timeouts yet
    let (amt, _) = try!(socket.recv_from(buf.as_mut_slice()));

    drop(socket);

    let header = ntp::NTPHeader::decode(amt, &buf);

    Ok(header.transmit_timestamp.as_timespec())
}

#[test]
fn receive_timestamp() {
    const NTP_SERVER: &'static str = "sundial.columbia.edu";

    let t1 = retrieve_ntp_timestamp(NTP_SERVER).unwrap();
    let t2 = retrieve_ntp_timestamp(NTP_SERVER).unwrap();

    assert!(t2 > t1);
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Claxon, a FLAC decoding library.
//!
//! TODO: Add some examples here.

#![warn(missing_docs)]
#![feature(iter_arith, zero_one)]

use std::io;
use std::mem;
use error::fmt_err;
use frame::FrameReader;
use input::ReadExt;
use metadata::{MetadataBlock, MetadataBlockReader, StreamInfo};

mod crc;
mod input;
mod error;
pub mod frame;
pub mod sample;
pub mod subframe;
pub mod metadata;

pub use error::{Error, Result};

/// A FLAC decoder that can decode the stream from the underlying reader.
///
/// TODO: Is stream a good name? Should it be called reader/decoder?
/// TODO: Add an example.
pub struct FlacReader<R: io::Read> {
    streaminfo: StreamInfo,
    #[allow(dead_code)] // TODO: Expose metadata nicely.
    metadata_blocks: Vec<MetadataBlock>,
    input: R,
}

/// An iterator that yields samples of type `S` read from a `FlacReader`.
///
/// The type `S` must have at least as many bits as the bits per sample of the
/// stream, otherwise every iteration will return an error.
pub struct FlacSamples<'fr, R: 'fr + io::Read, S: sample::Sample> {
    frame_reader: FrameReader<&'fr mut R, S>,
    block: frame::Block<S>,
    sample: u16,
    channel: u8,

    /// If reading ever failed, this flag is set, so that the iterator knows not
    /// to return any new values.
    has_failed: bool,
}

// TODO: Add a `FlacIntoSamples`.

fn read_stream_header<R: io::Read>(input: &mut R) -> Result<()> {
    // A FLAC stream starts with a 32-bit header 'fLaC' (big endian).
    const HEADER: u32 = 0x66_4c_61_43;
    let header = try!(input.read_be_u32());
    if header != HEADER {
        fmt_err("invalid stream header")
    } else {
        Ok(())
    }
}

impl<R: io::Read> FlacReader<R> {
    /// Attempts to create a reader that reads the FLAC format.
    ///
    /// The header and metadata blocks are read immediately. Audio frames will
    /// be read on demand.
    pub fn new(mut reader: R) -> Result<FlacReader<R>> {
        // A flac stream first of all starts with a stream header.
        try!(read_stream_header(&mut reader));

        // Start a new scope, because the input reader must be available again
        // for the frame reader next.
        let (streaminfo, metadata_blocks) = {
            // Next are one or more metadata blocks. The flac specification
            // dictates that the streaminfo block is the first block. The metadata
            // block reader will yield at least one element, so the unwrap is safe.
            let mut metadata_iter = MetadataBlockReader::new(&mut reader);
            let streaminfo_block = try!(metadata_iter.next().unwrap());
            let streaminfo = match streaminfo_block {
                MetadataBlock::StreamInfo(info) => info,
                _ => return fmt_err("streaminfo block missing"),
            };

            // There might be more metadata blocks, read and store them.
            let mut metadata_blocks = Vec::new();
            for block_result in metadata_iter {
                match block_result {
                    Err(error) => return Err(error),
                    Ok(block) => metadata_blocks.push(block),
                }
            }

            (streaminfo, metadata_blocks)
        };

        // The flac reader will contain the reader that will read frames.
        let flac_reader = FlacReader {
            streaminfo: streaminfo,
            metadata_blocks: metadata_blocks,
            input: reader,
        };

        Ok(flac_reader)
    }

    /// Returns the streaminfo metadata.
    ///
    /// This contains information like the sample rate and number of channels.
    pub fn streaminfo(&self) -> StreamInfo {
        self.streaminfo
    }

    /// Returns an iterator that decodes a single frame on every iteration.
    /// TODO: It is not an iterator.
    ///
    /// This is a low-level primitive that gives you control over when decoding
    /// happens. The representation of the decoded audio is somewhat specific to
    /// the FLAC format. For a higher-level interface, see `samples()`.
    pub fn blocks<'r, S: sample::Sample>(&'r mut self) -> FrameReader<&'r mut R, S> {
        FrameReader::new(&mut self.input)
    }

    /// Returns an iterator over all samples.
    ///
    /// The channel data is is interleaved. The iterator is streaming. That is,
    /// if you call this method once, read a few samples, and call this method
    /// again, the second iterator will not start again from the beginning of
    /// the file. It will continue somewhere after where the first iterator
    /// stopped, and it might skip some samples. (This is because FLAC divides
    /// a stream into blocks, which have to be decoded entirely. If you drop the
    /// iterator, you lose the unread samples in that block.)
    ///
    /// The type `S` must have at least `streaminfo().bits_per_sample` bits,
    /// otherwise iteration will return an error. All bit depths up to 32 bits
    /// per sample can be decoded into an `i32`, but if you know beforehand that
    /// you will be reading a file with 16 bits per sample, you can save memory
    /// by decoding into an `i16`.
    ///
    /// This is a high-level interface to the decoder. The cost of retrieving
    /// the next sample can vary significantly, as sometimes a new block has to
    /// be decoded. For more control over when decoding happens, use `blocks()`.
    pub fn samples<'r, S: sample::Sample>(&'r mut self) -> FlacSamples<'r, R, S> {
        FlacSamples {
            frame_reader: frame::FrameReader::new(&mut self.input),
            block: frame::Block::empty(),
            sample: 0,
            channel: 0,
            has_failed: false,
        }
    }
}

impl<'fr, R: 'fr + io::Read, S: sample::Sample> Iterator for FlacSamples<'fr, R, S> {
    type Item = Result<S>;

    fn next(&mut self) -> Option<Result<S>> {
        // If the previous read failed, end iteration.
        if self.has_failed {
            return None;
        }

        // Iterate the samples channel interleaved, so first increment the
        // channel.
        self.channel += 1;

        // If that was the last channel, increment the sample number.
        if self.channel >= self.block.channels() {
            self.channel = 0;
            self.sample += 1;

            // If that was the last sample in the block, decode the next block.
            if self.sample >= self.block.len() {
                self.sample = 0;

                // Replace the current block with an empty one so that we may
                // reuse the current buffer to decode again.
                let current_block = mem::replace(&mut self.block, frame::Block::empty());

                match self.frame_reader.read_next(current_block.into_buffer()) {
                    Ok(next_block) => {
                        self.block = next_block;
                    }
                    Err(error) => {
                        self.has_failed = true;
                        // block = frame::Block::empty();
                        return Some(Err(error));
                    }
                }
            }
        }

        Some(Ok(self.block.sample(self.channel, self.sample)))
    }
}
<commit_msg>add convenience constructor to FlacReader<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Claxon, a FLAC decoding library.
//!
//! TODO: Add some examples here.

#![warn(missing_docs)]
#![feature(iter_arith, zero_one)]

use std::fs;
use std::io;
use std::mem;
use std::path;
use error::fmt_err;
use frame::FrameReader;
use input::ReadExt;
use metadata::{MetadataBlock, MetadataBlockReader, StreamInfo};

mod crc;
mod input;
mod error;
pub mod frame;
pub mod sample;
pub mod subframe;
pub mod metadata;

pub use error::{Error, Result};

/// A FLAC decoder that can decode the stream from the underlying reader.
///
/// TODO: Is stream a good name? Should it be called reader/decoder?
/// TODO: Add an example.
pub struct FlacReader<R: io::Read> {
    streaminfo: StreamInfo,
    #[allow(dead_code)] // TODO: Expose metadata nicely.
    metadata_blocks: Vec<MetadataBlock>,
    input: R,
}

/// An iterator that yields samples of type `S` read from a `FlacReader`.
///
/// The type `S` must have at least as many bits as the bits per sample of the
/// stream, otherwise every iteration will return an error.
pub struct FlacSamples<'fr, R: 'fr + io::Read, S: sample::Sample> {
    frame_reader: FrameReader<&'fr mut R, S>,
    block: frame::Block<S>,
    sample: u16,
    channel: u8,

    /// If reading ever failed, this flag is set, so that the iterator knows not
    /// to return any new values.
    has_failed: bool,
}

// TODO: Add a `FlacIntoSamples`.

fn read_stream_header<R: io::Read>(input: &mut R) -> Result<()> {
    // A FLAC stream starts with a 32-bit header 'fLaC' (big endian).
    const HEADER: u32 = 0x66_4c_61_43;
    let header = try!(input.read_be_u32());
    if header != HEADER {
        fmt_err("invalid stream header")
    } else {
        Ok(())
    }
}

impl<R: io::Read> FlacReader<R> {
    /// Attempts to create a reader that reads the FLAC format.
    ///
    /// The header and metadata blocks are read immediately. Audio frames will
    /// be read on demand.
    pub fn new(mut reader: R) -> Result<FlacReader<R>> {
        // A flac stream first of all starts with a stream header.
        try!(read_stream_header(&mut reader));

        // Start a new scope, because the input reader must be available again
        // for the frame reader next.
        let (streaminfo, metadata_blocks) = {
            // Next are one or more metadata blocks. The flac specification
            // dictates that the streaminfo block is the first block. The metadata
            // block reader will yield at least one element, so the unwrap is safe.
            let mut metadata_iter = MetadataBlockReader::new(&mut reader);
            let streaminfo_block = try!(metadata_iter.next().unwrap());
            let streaminfo = match streaminfo_block {
                MetadataBlock::StreamInfo(info) => info,
                _ => return fmt_err("streaminfo block missing"),
            };

            // There might be more metadata blocks, read and store them.
            let mut metadata_blocks = Vec::new();
            for block_result in metadata_iter {
                match block_result {
                    Err(error) => return Err(error),
                    Ok(block) => metadata_blocks.push(block),
                }
            }

            (streaminfo, metadata_blocks)
        };

        // The flac reader will contain the reader that will read frames.
        let flac_reader = FlacReader {
            streaminfo: streaminfo,
            metadata_blocks: metadata_blocks,
            input: reader,
        };

        Ok(flac_reader)
    }

    /// Returns the streaminfo metadata.
    ///
    /// This contains information like the sample rate and number of channels.
    pub fn streaminfo(&self) -> StreamInfo {
        self.streaminfo
    }

    /// Returns an iterator that decodes a single frame on every iteration.
    /// TODO: It is not an iterator.
    ///
    /// This is a low-level primitive that gives you control over when decoding
    /// happens. The representation of the decoded audio is somewhat specific to
    /// the FLAC format. For a higher-level interface, see `samples()`.
    pub fn blocks<'r, S: sample::Sample>(&'r mut self) -> FrameReader<&'r mut R, S> {
        FrameReader::new(&mut self.input)
    }

    /// Returns an iterator over all samples.
    ///
    /// The channel data is is interleaved. The iterator is streaming. That is,
    /// if you call this method once, read a few samples, and call this method
    /// again, the second iterator will not start again from the beginning of
    /// the file. It will continue somewhere after where the first iterator
    /// stopped, and it might skip some samples. (This is because FLAC divides
    /// a stream into blocks, which have to be decoded entirely. If you drop the
    /// iterator, you lose the unread samples in that block.)
    ///
    /// The type `S` must have at least `streaminfo().bits_per_sample` bits,
    /// otherwise iteration will return an error. All bit depths up to 32 bits
    /// per sample can be decoded into an `i32`, but if you know beforehand that
    /// you will be reading a file with 16 bits per sample, you can save memory
    /// by decoding into an `i16`.
    ///
    /// This is a high-level interface to the decoder. The cost of retrieving
    /// the next sample can vary significantly, as sometimes a new block has to
    /// be decoded. For more control over when decoding happens, use `blocks()`.
    pub fn samples<'r, S: sample::Sample>(&'r mut self) -> FlacSamples<'r, R, S> {
        FlacSamples {
            frame_reader: frame::FrameReader::new(&mut self.input),
            block: frame::Block::empty(),
            sample: 0,
            channel: 0,
            has_failed: false,
        }
    }
}

impl FlacReader<io::BufReader<fs::File>> {
    /// Attempts to create a reader that reads from the specified file.
    ///
    /// This is a convenience constructor that opens a `File`, wraps it in a
    /// `BufReader` and then constructs a `FlacReader` from it.
    pub fn open<P: AsRef<path::Path>>(filename: P)
                -> Result<FlacReader<io::BufReader<fs::File>>> {
        let file = try!(fs::File::open(filename));
        let buf_reader = io::BufReader::new(file);
        FlacReader::new(buf_reader)
    }
}

impl<'fr, R: 'fr + io::Read, S: sample::Sample> Iterator for FlacSamples<'fr, R, S> {
    type Item = Result<S>;

    fn next(&mut self) -> Option<Result<S>> {
        // If the previous read failed, end iteration.
        if self.has_failed {
            return None;
        }

        // Iterate the samples channel interleaved, so first increment the
        // channel.
        self.channel += 1;

        // If that was the last channel, increment the sample number.
        if self.channel >= self.block.channels() {
            self.channel = 0;
            self.sample += 1;

            // If that was the last sample in the block, decode the next block.
            if self.sample >= self.block.len() {
                self.sample = 0;

                // Replace the current block with an empty one so that we may
                // reuse the current buffer to decode again.
                let current_block = mem::replace(&mut self.block, frame::Block::empty());

                match self.frame_reader.read_next(current_block.into_buffer()) {
                    Ok(next_block) => {
                        self.block = next_block;
                    }
                    Err(error) => {
                        self.has_failed = true;
                        // block = frame::Block::empty();
                        return Some(Err(error));
                    }
                }
            }
        }

        Some(Ok(self.block.sample(self.channel, self.sample)))
    }
}
<|endoftext|>