<commit_before>//! Defines the Whitted integrator which implements Whitted recursive ray tracing

use std::num::Float;

use scene::Scene;
use linalg;
use linalg::{Point, Ray};
use geometry::Intersection;
use film::Colorf;
use integrator::Integrator;
use bxdf::BxDFType;
use light::{Light, OcclusionTester};

/// The Whitted integrator implementing the Whitted recursive ray tracing algorithm
/// See [An improved illumination model for shaded display](http://dl.acm.org/citation.cfm?id=358882)
#[derive(Copy, Debug)]
pub struct Whitted {
    /// The maximum recursion depth for rays
    max_depth: u32,
}

impl Whitted {
    /// Create a new Whitted integrator with the desired maximum recursion depth for rays
    pub fn new(max_depth: u32) -> Whitted { Whitted { max_depth: max_depth } }
}

impl Integrator for Whitted {
    fn illumination(&self, scene: &Scene, ray: &Ray, hit: &Intersection) -> Colorf {
        let bsdf = hit.instance.material.bsdf(hit);
        let w_o = -ray.d;
        // Should we just return this in the tuple as well?
        // TODO: When we add support for multiple lights, iterate over all of them
        let mut occlusion = OcclusionTester::test_points(&Point::origin(), &Point::origin());
        let (li, w_i) = scene.light.sample_incident(&hit.dg.p, &mut occlusion);
        let f = bsdf.eval(&w_o, &w_i, BxDFType::all());
        let mut illum = Colorf::broadcast(0.0);
        if !li.is_black() && !f.is_black() && !occlusion.occluded(scene) {
            // TODO: Divide by pdf once we add that to lights
            illum = f * li * Float::abs(linalg::dot(&w_i, &bsdf.n));
        }
        if ray.depth < self.max_depth {
            // TODO: How to overload +=?
            illum = illum + self.specular_reflection(scene, ray, &bsdf);
            illum = illum + self.specular_transmission(scene, ray, &bsdf);
        }
        illum
    }
}

<commit_msg>Clean up some comments in whitted<commit_after>//! Defines the Whitted integrator which implements Whitted recursive ray tracing

use std::num::Float;

use scene::Scene;
use linalg;
use linalg::{Point, Ray};
use geometry::Intersection;
use film::Colorf;
use integrator::Integrator;
use bxdf::BxDFType;
use light::{Light, OcclusionTester};

/// The Whitted integrator implementing the Whitted recursive ray tracing algorithm
/// See [Whitted, An improved illumination model for shaded display](http://dl.acm.org/citation.cfm?id=358882)
#[derive(Copy, Debug)]
pub struct Whitted {
    /// The maximum recursion depth for rays
    max_depth: u32,
}

impl Whitted {
    /// Create a new Whitted integrator with the desired maximum recursion depth for rays
    pub fn new(max_depth: u32) -> Whitted { Whitted { max_depth: max_depth } }
}

impl Integrator for Whitted {
    fn illumination(&self, scene: &Scene, ray: &Ray, hit: &Intersection) -> Colorf {
        let bsdf = hit.instance.material.bsdf(hit);
        let w_o = -ray.d;
        // Should we just return this in the tuple as well?
        // TODO: When we add support for multiple lights, iterate over all of them
        let mut occlusion = OcclusionTester::test_points(&Point::origin(), &Point::origin());
        let (li, w_i) = scene.light.sample_incident(&hit.dg.p, &mut occlusion);
        let f = bsdf.eval(&w_o, &w_i, BxDFType::all());
        let mut illum = Colorf::broadcast(0.0);
        if !li.is_black() && !f.is_black() && !occlusion.occluded(scene) {
            // TODO: Divide by pdf once we add that to lights
            illum = f * li * Float::abs(linalg::dot(&w_i, &bsdf.n));
        }
        if ray.depth < self.max_depth {
            illum = illum + self.specular_reflection(scene, ray, &bsdf);
            illum = illum + self.specular_transmission(scene, ray, &bsdf);
        }
        illum
    }
}

<|endoftext|>


<commit_before>use std::cell::Cell;
use std::collections::HashMap;
use std::fmt;
use std::fmt::Debug;
use std::rc::Rc;
use std::rc::Weak;

/**
 * A trait for all values that can be handled by Operation
 */
pub trait Value: Clone + Debug {

}

/// Represents the "meat" of a partially-evaluated expression
pub struct PartialExpression<V: Value + 'static> {
    operation: Operation<V>,
    operands: Vec<Rc<Expression<V>>>,
    parent_expression: Cell<Option<Weak<Expression<V>>>>,
    num_incomplete: usize,
}

impl<V: Value + 'static> Debug for PartialExpression<V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "PartialExpression({}, {:?})", self.operation.name, self.operands)
    }
}

pub struct PendingOp<V: Value + 'static> {
    operation: Operation<V>,
    operands: Vec<V>,
    parent_expression: Cell<Option<Weak<Expression<V>>>>,
}

impl<V: Value + 'static> Debug for PendingOp<V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "PendingOp({}, {:?})", self.operation.name, self.operands)

    }
}

/**
 * An expression is either a value or an operation applied to a set of expressions.
 */
#[derive(Debug)]
pub enum Expression<V: Value + 'static> {
    /// An expression that has been totally evaluated
    Total(V),
    /**
     * An expression whose evaluation is waiting on an external trigger
     *
     * When an Expression is in this state, all of its operands are Total, but there
     * is not yet enough information to evaluate the operation.
     */
    Pending(PendingOp<V>),
    /// An expression whose operands are not yet Total
    Partial(PartialExpression<V>),
}

impl<V: Value + 'static> Expression<V> {
    pub fn from_op(op: Operation<V>, mut operands: Vec<Rc<Expression<V>>>) -> Rc<Expression<V>> {
        let num_incomplete = operands.iter().filter(|child| {
            match *Rc::as_ref(child) {
                Expression::Total(_) => false,
                _ => true
            }
        }).count();

        if num_incomplete == 0 {
            let operand_values = operands.iter().map(|o| {
                match *Rc::as_ref(o) {
                    Expression::Total(ref value) => value.clone(),
                    _ => unreachable!()
                }
            }).collect::<Vec<_>>();

            let eval_result = op.evaluate(&operand_values);

            match eval_result {
                EvaluationResult::Total(val) => {
                    return Rc::new(Expression::Total(val));
                }
                EvaluationResult::Pending => {
                    return Rc::new(Expression::Pending(
                        PendingOp {
                            operation: op,
                            operands: operand_values,
                            parent_expression: Cell::new(None),
                        }
                    ));
                }
            }
        }

        let mut expression = Rc::new(Expression::Partial(
            PartialExpression {
                operation: op,
                operands: vec!(),
                parent_expression: Cell::new(None),
                num_incomplete: num_incomplete
            }
        ));

        // TODO: implement.
        for child in operands.iter_mut() {
            if let Expression::Partial(ref oi) = *Rc::as_ref(child) {
                oi.parent_expression.set(Some(Rc::downgrade(&expression)));
            }
        }

        match *Rc::get_mut(&mut expression).unwrap() {
            Expression::Partial(ref mut oi) => {
                oi.operands = operands;
            },
            _ => unreachable!()
        }

        expression
    }

    pub fn from_value(value: V) -> Rc<Expression<V>> {
        Rc::new(Expression::Total(value))
    }

    // Called when an operand becomes complete
    // TODO: implement.
    fn on_child_complete(&mut self) {
        match *self {
            Expression::Total(_) => panic!("Invalid call to on_child_complete"),
            Expression::Pending(_) => panic!("Invalid call to on_child_complete"),
            Expression::Partial(ref mut oi) => {
                assert!(oi.num_incomplete > 0);
                oi.num_incomplete -= 1;
                // TODO: evaluate if num_incomplete hits 0.
            }
        }
    }

    //TODO: create a function that produces an Iterator<Item=V>, but only when all arguments
    // are complete?
}

pub enum EvaluationResult<V: Value + 'static> {
    Total(V),
    Pending
}

// TODO: remove this type?
pub type Evaluator<V: Value + 'static> = fn(&[V]) -> EvaluationResult<V>;

// TODO: create an Arguments type? (useful for eager ops)
// TODO: handle lazy ops. (Consuming a stream of ProtoNodes *might* be a workable solution).
#[derive(Copy)]
pub struct Operation<V: Value + 'static> {
    name: &'static str,
    evaluator: Evaluator<V>,
}

impl<V: Value + 'static> Debug for Operation<V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Operation {{ name: {} }}", self.name)
    }
}

impl<V: Value + 'static> Operation<V> {
    pub const fn new(name: &'static str, evaluator: Evaluator<V>) -> Operation<V> {
        Operation { name: name, evaluator: evaluator }
    }

    pub fn evaluate(&self, operands: &Vec<V>) -> EvaluationResult<V> {
        (self.evaluator)(operands)
    }
}

// Manual implementation required to get around Rust bug #28229
impl<V: Value + 'static> Clone for Operation<V> {
    fn clone(&self) -> Operation<V> {
        Operation {
            name: self.name,
            evaluator: self.evaluator
        }
    }
}

pub struct OperationGroup<V: Value + 'static> {
    map: HashMap<Box<str>, Operation<V>>,
}

impl<V: Value + 'static> OperationGroup<V> {
    pub const fn new(map: HashMap<Box<str>, Operation<V>>) -> OperationGroup<V> {
        OperationGroup { map: map }
    }

    pub fn get(&self, name: &str) -> Option<&Operation<V>> {
        self.map.get(name)
    }
}
<commit_msg>Make Expression work as a value type<commit_after>use std;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::rc::{Rc, Weak};

/**
 * A trait for all values that can be handled by Operation
 */
pub trait Value: Clone + Debug {}

// TODO: use this.
pub trait ExpressionContext<V: Value + 'static> {
}

/**
 * Responds to expressions becoming total
 */
pub trait EvaluationListener<V: Value + 'static> : Debug {
    fn on_evaluated(&mut self, partial: &PartialExpression<V>, value: V);
}

/**
 * A list of operands
 */
#[derive(Debug)]
pub enum OperandList<V: Value + 'static> {
    Total(Vec<V>),
    Partial(Vec<Expression<V>>, usize)
}

impl<V: Value + 'static> OperandList<V> {
    pub fn new(operands: Vec<Expression<V>>) -> OperandList<V> {
        let num_partial = operands.iter().filter(|operand| {
            match *operand {
                &Expression::Total(_) => false,
                &Expression::Partial(_) => true,
            }
        }).count();

        if num_partial == 0 {
            OperandList::Total(operands.into_iter().map(|operand| {
                match operand {
                    Expression::Total(ref value) => value.clone(),
                    Expression::Partial(_) => unreachable!()
                }
            }).collect::<Vec<_>>())
        } else {
            OperandList::Partial(operands, num_partial)
        }

        // TODO: set child indices?
    }

    pub fn total_operands(&self) -> Option<Vec<V>> {
        match self {
            &OperandList::Total(ref v) => Some(v.clone()),
            &OperandList::Partial(ref operands, num_partial) => {
                if num_partial == 0 {
                    Some(operands.iter().map(|o| {
                        match o {
                            &Expression::Total(ref value) => value.clone(),
                            _ => unreachable!()
                        }
                    }).collect::<Vec<_>>())
                } else {
                    None
                }
            }
        }
    }
}

/**
 * Represents the "meat" of a partially-evaluated expression
 */
pub struct PartialExpression<V: Value + 'static> {
    operation: Operation<V>,
    operands: RefCell<OperandList<V>>,
    listener: Cell<Option<Weak<EvaluationListener<V>>>>,
    /// The operand's index in the parent expression
    index: usize,
}

// Since we can't derive Debug for Cell<Option<Weak<...>>>, we have to implement it manually.
impl<V: Value + 'static> Debug for PartialExpression<V> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
        // TODO: implement properly.
        write!(f, "PartialExpression")
    }
}

impl<V: Value + 'static> PartialExpression<V> {
    pub fn new(op: Operation<V>, operands: OperandList<V>) -> Rc<PartialExpression<V>> {
        let exp = Rc::new(PartialExpression {
            operation: op,
            operands: RefCell::new(operands),
            listener: Cell::new(None),
            index: 0,
        });

        // Set operands' listeners.
        {
            let operands = &*exp.operands.borrow();
            if let &OperandList::Partial(ref operands, _) = operands {
                for operand in operands.iter() {
                    if let &Expression::Partial(ref oi) = operand {
                        oi.listener.set(Some(Rc::<PartialExpression<V>>::downgrade(&exp)));
                    }
                }
            }
        }

        exp
    }
}

impl<V: Value + 'static> EvaluationListener<V> for PartialExpression<V> {
    fn on_evaluated(&mut self, partial: &PartialExpression<V>, value: V) {
        let operands = &mut *self.operands.borrow_mut();
        if let &mut OperandList::Partial(ref mut operands, ref mut num_partial) = operands {
            if let Expression::Partial(_) = operands[partial.index] {
                operands[partial.index] = Expression::Total(value);
                *num_partial -= 1;
                // TODO: do something when we have no partials left.
            }
        }
    }
}

/**
 * An expression is either a value or an operation applied to a list of expressions.
 */
#[derive(Debug)]
pub enum Expression<V: Value + 'static> {
    /// An expression that has been totally evaluated
    Total(V),
    /// An expression which has not been totally evaluated
    Partial(Rc<PartialExpression<V>>),
}

impl<V: Value + 'static> Expression<V> {
    /**
     * Builds an Expression from an Operation and a list of Operands
     */
    pub fn from_op(op: Operation<V>, operands: Vec<Expression<V>>) -> Expression<V> {
        let op_list = OperandList::new(operands);

        if let OperandList::Total(operand_values) = op_list {
            let eval_result = op.evaluate(&operand_values);

            return match eval_result {
                EvaluationResult::Total(val) => {
                    Expression::Total(val)
                }
                EvaluationResult::Pending => {
                    let partial = PartialExpression::new(op, OperandList::Total(operand_values));
                    Expression::Partial(partial)
                }
            }
        }

        Expression::Partial(PartialExpression::new(op, op_list))
    }

    pub fn from_value(value: V) -> Rc<Expression<V>> {
        Rc::new(Expression::Total(value))
    }
}

pub enum EvaluationResult<V: Value + 'static> {
    Total(V),
    Pending
}

// TODO: remove this type?
pub type Evaluator<V: Value + 'static> = fn(&[V]) -> EvaluationResult<V>;

// TODO: create an Arguments type? (useful for eager ops)
// TODO: handle lazy ops. (Consuming a stream of ProtoNodes *might* be a workable solution).
#[derive(Copy)]
pub struct Operation<V: Value + 'static> {
    name: &'static str,
    evaluator: Evaluator<V>,
}

impl<V: Value + 'static> Debug for Operation<V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Operation {{ name: {} }}", self.name)
    }
}

impl<V: Value + 'static> Operation<V> {
    pub const fn new(name: &'static str, evaluator: Evaluator<V>) -> Operation<V> {
        Operation { name: name, evaluator: evaluator }
    }

    pub fn evaluate(&self, operands: &Vec<V>) -> EvaluationResult<V> {
        (self.evaluator)(operands)
    }
}

// Manual implementation required to get around Rust bug #28229
impl<V: Value + 'static> Clone for Operation<V> {
    fn clone(&self) -> Operation<V> {
        Operation {
            name: self.name,
            evaluator: self.evaluator
        }
    }
}

pub struct OperationGroup<V: Value + 'static> {
    map: HashMap<Box<str>, Operation<V>>,
}

impl<V: Value + 'static> OperationGroup<V> {
    pub const fn new(map: HashMap<Box<str>, Operation<V>>) -> OperationGroup<V> {
        OperationGroup { map: map }
    }

    pub fn get(&self, name: &str) -> Option<&Operation<V>> {
        self.map.get(name)
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate glm;
extern crate moho;

use std::time::{Instant, Duration};

use self::moho::resource_manager::ResourceManager;
use self::moho::resource_manager::Renderer;

use sprite_strip::SpriteStrip;

pub struct Animation<R: Renderer> {
    sprite: SpriteStrip<R>,
    num_frames: u32,
    current_frame: u32,
    frame_duration: Duration,
    frame_instant: Option<Instant>,
    repeat: bool,
}

impl<R: Renderer> Animation<R> {
    pub fn new(sprite: SpriteStrip<R>,
               num_frames: u32,
               repeat: bool,
               frame_duration_ms: u16)
               -> Self {
        Animation {
            sprite: sprite,
            num_frames: num_frames,
            repeat: repeat,
            frame_duration: Duration::from_millis(frame_duration_ms as u64),
            current_frame: 0,
            frame_instant: None,
        }
    }

    pub fn update(&mut self) -> bool {
        self.current_frame = match self.frame_instant {
            None => {
                self.frame_instant = Some(Instant::now());
                0
            }
            Some(instant) => {
                if instant.elapsed() >= self.frame_duration {
                    self.frame_instant = Some(instant + self.frame_duration);
                    self.current_frame + 1
                } else {
                    self.current_frame
                }
            }
        };

        if self.current_frame > self.num_frames {
            if self.repeat {
                self.current_frame -= self.num_frames;
                true
            } else {
                self.frame_instant = None;
                false
            }
        } else {
            true
        }
    }

    pub fn draw(&self,
                renderer: &mut ResourceManager<R>,
                center: glm::IVec2)
                -> Result<(), String> {
        self.sprite.draw(renderer, center, self.current_frame)
    }
}
<commit_msg>small bug fix on animation<commit_after>extern crate sdl2;
extern crate glm;
extern crate moho;

use std::time::{Instant, Duration};

use self::moho::resource_manager::ResourceManager;
use self::moho::resource_manager::Renderer;

use sprite_strip::SpriteStrip;

pub struct Animation<R: Renderer> {
    sprite: SpriteStrip<R>,
    num_frames: u32,
    current_frame: u32,
    frame_duration: Duration,
    frame_instant: Option<Instant>,
    repeat: bool,
}

impl<R: Renderer> Animation<R> {
    pub fn new(sprite: SpriteStrip<R>,
               num_frames: u32,
               repeat: bool,
               frame_duration_ms: u16)
               -> Self {
        Animation {
            sprite: sprite,
            num_frames: num_frames,
            repeat: repeat,
            frame_duration: Duration::from_millis(frame_duration_ms as u64),
            current_frame: 0,
            frame_instant: None,
        }
    }

    pub fn update(&mut self) -> bool {
        self.current_frame = match self.frame_instant {
            None => {
                self.frame_instant = Some(Instant::now());
                0
            }
            Some(instant) => {
                if instant.elapsed() >= self.frame_duration {
                    self.frame_instant = Some(instant + self.frame_duration);
                    self.current_frame + 1
                } else {
                    self.current_frame
                }
            }
        };

        if self.current_frame >= self.num_frames {
            if self.repeat {
                self.current_frame -= self.num_frames;
                true
            } else {
                self.frame_instant = None;
                false
            }
        } else {
            true
        }
    }

    pub fn draw(&self,
                renderer: &mut ResourceManager<R>,
                center: glm::IVec2)
                -> Result<(), String> {
        self.sprite.draw(renderer, center, self.current_frame)
    }
}
<|endoftext|>


<commit_before>extern crate onmf;
use onmf::helpers::{ToImage, Normalize, magnify};
use onmf::testimage_generator;

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng, ChaChaRng};

extern crate num;
use num::{Float};

extern crate ndarray;
use ndarray::ArrayBase;

type FloatT = f32;

fn main() {
    let mag_factor = 10;

    let seed: &[_] = &[1, 2, 3, 4];
    // let mut rng: ChaChaRng = ChaChaRng::from_seed(seed);
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let steps = 12;
    let per_step = 1000;
    let nsamples = steps * per_step;
    let nobserved = 10 * 10;
    // let nhidden = 20 + steps;
    let nhidden = 40;

    let mut data: ArrayBase<Vec<FloatT>, (usize, usize)> =
        ArrayBase::zeros((nsamples, nobserved));

    // write one testimage into each row of data
    for (horizontal, vertical, i, factor) in testimage_generator::testimages::<FloatT, _>(per_step, &mut rng) {
        let row = (horizontal + vertical) * i;
        for (col, val) in factor.as_vec().iter().enumerate() {
            data[(row, col)] = val.clone();
        }
    }

    // let mut ortho_nmf = onmf::OrthogonalNMF::<f64>::init_random01(
    let mut ortho_nmf = onmf::OrthogonalNMFBlas::new_random01(
        nhidden, nobserved, nsamples, &mut rng);

    let mut iteration: i32 = 0;
    loop {
        // alpha gets larger and larger with each iteration
        // 0.1, 0.101, 0.102, 0.103, ...
        // at iteration 232 alpha first goes above 1.0
        // iteration = 232 -> alpha = 1.005
        let alpha = 0.1 * 1.01.powi(iteration);

        // this does not converge:
        // let alpha = 0.1 * 1.0001.powi(iteration);

        ortho_nmf.iterate(alpha, &mut data);

        if iteration % 10 == 0 {
            println!("iteration = {} alpha = {}", iteration, alpha);

            // read testimage out of each row of nmf.hidden
            for irow in 0..nhidden {
                let mut column = Vec::<FloatT>::new();
                for icol in 0..nobserved {
                    column.push(ortho_nmf.hidden[(irow, icol)]);
                }
                let image = DMat::<FloatT>::from_col_vec(10, 10, &column[..]);
                // println!("image {}", irow);
                // println!("{:?}", image);
                magnify(image.normalize(), mag_factor).save_to_png(&format!("orthogonal-nmf-hidden-{}.png", irow)[..]).unwrap();
            }
        }

        iteration += 1;
    }
}
<commit_msg>adapt to refactored NMF<commit_after>extern crate onmf;
use onmf::helpers::{ToImage, Normalize, magnify};
use onmf::testimage_generator;

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng, ChaChaRng};

extern crate num;
use num::{Float};

extern crate ndarray;
use ndarray::ArrayBase;

type FloatT = f32;

fn main() {
    let mag_factor = 10;

    let seed: &[_] = &[1, 2, 3, 4];
    // let mut rng: ChaChaRng = ChaChaRng::from_seed(seed);
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let steps = 12;
    let per_step = 1000;
    let nsamples = steps * per_step;
    let nobserved = 10 * 10;
    // let nhidden = 20 + steps;
    let nhidden = 40;

    let mut data: ArrayBase<Vec<FloatT>, (usize, usize)> =
        ArrayBase::zeros((nsamples, nobserved));

    // write one testimage into each row of data
    for (horizontal, vertical, i, factor) in testimage_generator::testimages::<FloatT, _>(per_step, &mut rng) {
        let row = (horizontal + vertical) * i;
        for (col, val) in factor.as_vec().iter().enumerate() {
            data[(row, col)] = val.clone();
        }
    }

    let mut nmf = onmf::NMFBlas::new_random01(
        nhidden, nobserved, nsamples, &mut rng);

    let mut iteration: i32 = 0;
    loop {
        // alpha gets larger and larger with each iteration
        // 0.1, 0.101, 0.102, 0.103, ...
        // at iteration 232 alpha first goes above 1.0
        // iteration = 232 -> alpha = 1.005
        let alpha = 0.1 * 1.01.powi(iteration);

        // this does not converge:
        // let alpha = 0.1 * 1.0001.powi(iteration);

        nmf.iterate(&mut data, Some(alpha));

        if iteration % 10 == 0 {
            println!("iteration = {} alpha = {}", iteration, alpha);

            // read testimage out of each row of nmf.hidden
            for irow in 0..nhidden {
                let mut column = Vec::<FloatT>::new();
                for icol in 0..nobserved {
                    column.push(nmf.hidden[(irow, icol)]);
                }
                let image = DMat::<FloatT>::from_col_vec(10, 10, &column[..]);
                // println!("image {}", irow);
                // println!("{:?}", image);
                magnify(image.normalize(), mag_factor).save_to_png(&format!("orthogonal-nmf-hidden-{}.png", irow)[..]).unwrap();
            }
        }

        iteration += 1;
    }
}
<|endoftext|>


<commit_before>#![cfg(target_os = "linux")]

use std::fs;
use std::mem::size_of;
use std::path::Path;
use std::thread;
use std::time::Duration;

use rand::Rng;

use pagecache::{Config, ConfigBuilder};

const CYCLE: usize = 256;

/// Verifies that the keys in the tree are correctly recovered.
/// Panics if they are incorrect.
/// Returns the key that should be resumed at, and the current cycle value.
fn verify(tree: &sled::Tree) -> (u32, u32) {
    // key 0 should always be the highest value, as that's where we increment
    // at some point, it might go down by one
    // it should never return, or go down again after that
    let mut iter = tree.iter();
    let highest = match iter.next() {
        Some(Ok((_k, v))) => slice_to_u32(&*v),
        Some(Err(e)) => panic!("{:?}", e),
        None => return (0, 0),
    };

    let highest_vec = u32_to_vec(highest);

    // find how far we got
    let mut contiguous: u32 = 0;
    let mut lowest = 0;
    for res in iter {
        let (_k, v) = res.unwrap();
        if &v[..4] == &highest_vec[..4] {
            contiguous += 1;
        } else {
            let expected = if highest == 0 {
                CYCLE as u32 - 1
            } else {
                (highest - 1) % CYCLE as u32
            };
            let actual = slice_to_u32(&*v);
            assert_eq!(expected, actual);
            lowest = actual;
            break;
        }
    }

    // ensure nothing changes after this point
    let low_beginning = u32_to_vec(contiguous + 1);

    for res in tree.range(&*low_beginning..) {
        let (k, v): (sled::IVec, _) = res.unwrap();
        assert_eq!(
            slice_to_u32(&*v),
            lowest,
            "expected key {} to have value {}, instead it had value {} in db: {:?}",
            slice_to_u32(&*k),
            lowest,
            slice_to_u32(&*v),
            tree
        );
    }

    (contiguous, highest)
}

fn u32_to_vec(u: u32) -> Vec<u8> {
    let buf: [u8; size_of::<u32>()] = u.to_be_bytes();
    buf.to_vec()
}

fn slice_to_u32(b: &[u8]) -> u32 {
    let mut buf = [0u8; size_of::<u32>()];
    buf.copy_from_slice(&b[..size_of::<u32>()]);

    u32::from_be_bytes(buf)
}

fn spawn_killah() {
    thread::spawn(|| {
        let runtime = rand::thread_rng().gen_range(0, 200);
        thread::sleep(Duration::from_millis(runtime));
        unsafe {
            libc::raise(9);
        }
    });
}

fn run(config: Config) {
    tests::setup_logger();
    let crash_during_initialization = rand::thread_rng().gen_bool(0.1);

    if crash_during_initialization {
        spawn_killah();
    }

    let tree = sled::Db::start(config).unwrap();

    if !crash_during_initialization {
        spawn_killah();
    }

    let (key, highest) = verify(&tree);

    let mut hu = ((highest as usize) * CYCLE) + key as usize;
    assert_eq!(hu % CYCLE, key as usize);
    assert_eq!(hu / CYCLE, highest as usize);

    loop {
        hu += 1;

        if hu / CYCLE >= CYCLE {
            hu = 0;
        }

        let key = u32_to_vec((hu % CYCLE) as u32);

        let mut value = u32_to_vec((hu / CYCLE) as u32);
        let additional_len = rand::thread_rng().gen_range(0, 1000);
        value.append(&mut vec![0u8; additional_len]);

        tree.insert(&key, value).unwrap();
    }
}

fn run_without_snapshot() {
    let config = ConfigBuilder::new()
        .page_consolidation_threshold(10)
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .io_buf_size(1_000)
        .path("test_crashes".to_string())
        .snapshot_after_ops(1 << 56)
        .build();

    match thread::spawn(|| run(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

fn run_with_snapshot() {
    let config = ConfigBuilder::new()
        .page_consolidation_threshold(10)
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .io_buf_size(1_000)
        .path("test_crashes_with_snapshot".to_string())
        .snapshot_after_ops(5000)
        .build();

    match thread::spawn(|| run(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

#[test]
fn test_crash_recovery_with_runtime_snapshot() {
    cleanup_with_snapshots();
    for _ in 0..100 {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_with_snapshot()
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup();
                panic!("child exited abnormally");
            }
        }
    }
    cleanup_with_snapshots();
}

#[test]
fn test_crash_recovery_no_runtime_snapshot() {
    cleanup();
    for _ in 0..100 {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_without_snapshot()
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup();
                panic!("child exited abnormally");
            }
        }
    }
    cleanup();
}

fn cleanup_with_snapshots() {
    let dir = Path::new("test_crashes_with_snapshot");
    if dir.exists() {
        fs::remove_dir_all(dir).unwrap();
    }
}

fn cleanup() {
    let dir = Path::new("test_crashes");
    if dir.exists() {
        fs::remove_dir_all(dir).unwrap();
    }
}
<commit_msg>Fix imports in crash test<commit_after>#![cfg(target_os = "linux")]

use std::fs;
use std::mem::size_of;
use std::path::Path;
use std::thread;
use std::time::Duration;

use rand::Rng;

use sled::{Db, Config, ConfigBuilder};

const CYCLE: usize = 256;

/// Verifies that the keys in the tree are correctly recovered.
/// Panics if they are incorrect.
/// Returns the key that should be resumed at, and the current cycle value.
fn verify(tree: &sled::Tree) -> (u32, u32) {
    // key 0 should always be the highest value, as that's where we increment
    // at some point, it might go down by one
    // it should never return, or go down again after that
    let mut iter = tree.iter();
    let highest = match iter.next() {
        Some(Ok((_k, v))) => slice_to_u32(&*v),
        Some(Err(e)) => panic!("{:?}", e),
        None => return (0, 0),
    };

    let highest_vec = u32_to_vec(highest);

    // find how far we got
    let mut contiguous: u32 = 0;
    let mut lowest = 0;
    for res in iter {
        let (_k, v) = res.unwrap();
        if &v[..4] == &highest_vec[..4] {
            contiguous += 1;
        } else {
            let expected = if highest == 0 {
                CYCLE as u32 - 1
            } else {
                (highest - 1) % CYCLE as u32
            };
            let actual = slice_to_u32(&*v);
            assert_eq!(expected, actual);
            lowest = actual;
            break;
        }
    }

    // ensure nothing changes after this point
    let low_beginning = u32_to_vec(contiguous + 1);

    for res in tree.range(&*low_beginning..) {
        let (k, v): (sled::IVec, _) = res.unwrap();
        assert_eq!(
            slice_to_u32(&*v),
            lowest,
            "expected key {} to have value {}, instead it had value {} in db: {:?}",
            slice_to_u32(&*k),
            lowest,
            slice_to_u32(&*v),
            tree
        );
    }

    (contiguous, highest)
}

fn u32_to_vec(u: u32) -> Vec<u8> {
    let buf: [u8; size_of::<u32>()] = u.to_be_bytes();
    buf.to_vec()
}

fn slice_to_u32(b: &[u8]) -> u32 {
    let mut buf = [0u8; size_of::<u32>()];
    buf.copy_from_slice(&b[..size_of::<u32>()]);

    u32::from_be_bytes(buf)
}

fn spawn_killah() {
    thread::spawn(|| {
        let runtime = rand::thread_rng().gen_range(0, 200);
        thread::sleep(Duration::from_millis(runtime));
        unsafe {
            libc::raise(9);
        }
    });
}

fn run(config: Config) {
    tests::setup_logger();
    let crash_during_initialization = rand::thread_rng().gen_bool(0.1);

    if crash_during_initialization {
        spawn_killah();
    }

    let tree = Db::start(config).unwrap();

    if !crash_during_initialization {
        spawn_killah();
    }

    let (key, highest) = verify(&tree);

    let mut hu = ((highest as usize) * CYCLE) + key as usize;
    assert_eq!(hu % CYCLE, key as usize);
    assert_eq!(hu / CYCLE, highest as usize);

    loop {
        hu += 1;

        if hu / CYCLE >= CYCLE {
            hu = 0;
        }

        let key = u32_to_vec((hu % CYCLE) as u32);

        let mut value = u32_to_vec((hu / CYCLE) as u32);
        let additional_len = rand::thread_rng().gen_range(0, 1000);
        value.append(&mut vec![0u8; additional_len]);

        tree.insert(&key, value).unwrap();
    }
}

fn run_without_snapshot() {
    let config = ConfigBuilder::new()
        .page_consolidation_threshold(10)
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .io_buf_size(1_000)
        .path("test_crashes".to_string())
        .snapshot_after_ops(1 << 56)
        .build();

    match thread::spawn(|| run(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

fn run_with_snapshot() {
    let config = ConfigBuilder::new()
        .page_consolidation_threshold(10)
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .io_buf_size(1_000)
        .path("test_crashes_with_snapshot".to_string())
        .snapshot_after_ops(5000)
        .build();

    match thread::spawn(|| run(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

#[test]
fn test_crash_recovery_with_runtime_snapshot() {
    cleanup_with_snapshots();
    for _ in 0..100 {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_with_snapshot()
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup();
                panic!("child exited abnormally");
            }
        }
    }
    cleanup_with_snapshots();
}

#[test]
fn test_crash_recovery_no_runtime_snapshot() {
    cleanup();
    for _ in 0..100 {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_without_snapshot()
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup();
                panic!("child exited abnormally");
            }
        }
    }
    cleanup();
}

fn cleanup_with_snapshots() {
    let dir = Path::new("test_crashes_with_snapshot");
    if dir.exists() {
        fs::remove_dir_all(dir).unwrap();
    }
}

fn cleanup() {
    let dir = Path::new("test_crashes");
    if dir.exists() {
        fs::remove_dir_all(dir).unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate bincode;
extern crate rustc_serialize;
extern crate rpsrtsrs;
extern crate docopt;

use std::net::TcpStream;
use std::ops::Deref;

use rpsrtsrs::state::GameState;
use rpsrtsrs::network::{Command, Message};

use docopt::Docopt;

use bincode::SizeLimit;
use bincode::rustc_serialize::{decode_from, encode_into};
use bincode::rustc_serialize::DecodingResult;

static USAGE: &'static str = "
Usage: cli_client [-p PORT] [-i IP] [-r ID] (read|move <id> <x> <y>)

Options:
    -p PORT  The port to connect to [default: 8080].
    -i IP    The ipv4 address to connect to [default: 127.0.0.1].
    -r ID    Reconnect with the given ID
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_p: u16,
    flag_i: String,
    flag_r: Option<u32>,

    cmd_read: bool,
    arg_id: Option<u32>,
    arg_x: Option<f64>,
    arg_y: Option<f64>,
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode())
                                       .unwrap_or_else(|e| e.exit());
    println!("{:?}", args);
    let host = args.flag_i;
    let port = args.flag_p;
    let reconnect = args.flag_r;
    let cmd_read = args.cmd_read;

    println!("connecting to host: {:?}:{:?} reconnect? {:?}", host, port, reconnect);

    let mut stream = TcpStream::connect((host.deref(), port)).unwrap();

    match reconnect {
        Some(id) => {
            encode_into(&Message::ClientReconnect(id.into()),
                        &mut stream,
                        SizeLimit::Infinite)
                .unwrap();
        }
        None => {
            encode_into(&Message::ClientHello, &mut stream, SizeLimit::Infinite).unwrap();
        }
    }
    let server_hello: DecodingResult<Message> = decode_from(&mut stream, SizeLimit::Infinite);
    println!("{:?}", server_hello);

    if cmd_read {
        loop {
            let game_state: DecodingResult<GameState> = decode_from(&mut stream,
                                                                    SizeLimit::Infinite);
            match game_state {
                Ok(game) => println!("{:?}", game),
                Err(e) => {
                    println!("{:?}", e);
                    return;
                }
            }
        }
    } else {
        let id = args.arg_id.expect("<id> missing");
        let x = args.arg_x.expect("<x> missing");
        let y = args.arg_y.expect("<y> missing");
        encode_into(&Message::Command(Command::Move(id.into(), [x, y])),
                    &mut stream,
                    SizeLimit::Infinite)
            .unwrap();
    }
}
<commit_msg>Work around cli_client exiting before sending the move command<commit_after>extern crate bincode;
extern crate rustc_serialize;
extern crate rpsrtsrs;
extern crate docopt;

use std::net::TcpStream;
use std::ops::Deref;
use std::io::Write;
use std::thread;

use rpsrtsrs::state::GameState;
use rpsrtsrs::network::{Command, Message};

use docopt::Docopt;

use bincode::SizeLimit;
use bincode::rustc_serialize::{decode_from, encode_into};
use bincode::rustc_serialize::DecodingResult;

static USAGE: &'static str = "
Usage: cli_client [-p PORT] [-i IP] [-r ID] (read|move <id> <x> <y>)

Options:
    -p PORT  The port to connect to [default: 8080].
    -i IP    The ipv4 address to connect to [default: 127.0.0.1].
    -r ID    Reconnect with the given ID
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_p: u16,
    flag_i: String,
    flag_r: Option<u32>,

    cmd_read: bool,
    arg_id: Option<u32>,
    arg_x: Option<f64>,
    arg_y: Option<f64>,
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode())
                                       .unwrap_or_else(|e| e.exit());
    println!("{:?}", args);
    let host = args.flag_i;
    let port = args.flag_p;
    let reconnect = args.flag_r;
    let cmd_read = args.cmd_read;

    println!("connecting to host: {:?}:{:?} reconnect? {:?}", host, port, reconnect);

    let mut stream = TcpStream::connect((host.deref(), port)).unwrap();

    match reconnect {
        Some(id) => {
            encode_into(&Message::ClientReconnect(id.into()),
                        &mut stream,
                        SizeLimit::Infinite)
                .unwrap();
        }
        None => {
            encode_into(&Message::ClientHello, &mut stream, SizeLimit::Infinite).unwrap();
        }
    }
    let server_hello: DecodingResult<Message> = decode_from(&mut stream, SizeLimit::Infinite);
    println!("{:?}", server_hello);

    if cmd_read {
        loop {
            let game_state: DecodingResult<GameState> = decode_from(&mut stream,
                                                                    SizeLimit::Infinite);
            match game_state {
                Ok(game) => println!("{:?}", game),
                Err(e) => {
                    println!("{:?}", e);
                    return;
                }
            }
        }
    } else {
        let id = args.arg_id.expect("<id> missing");
        let x = args.arg_x.expect("<x> missing");
        let y = args.arg_y.expect("<y> missing");
        encode_into(&Message::Command(Command::Move(id.into(), [x, y])),
                    &mut stream,
                    SizeLimit::Infinite)
            .unwrap();
        stream.flush().unwrap();
    }

    thread::sleep_ms(100);
}
<|endoftext|>


<commit_before>extern crate sdl = "sdl2";
use sdl::{video, event, keycode, timer, render};

use game::Loop;
mod game;

static MS_PER_FRAME : uint = 16; // About 60fps

fn main() {
    sdl::init(sdl::InitAudio | sdl::InitVideo);

    let window = video::Window::new("Asteroids Plus",
                                    video::PosCentered, video::PosCentered,
                                    512, 512,
                                    video::WindowFlags::empty()).unwrap();
    let renderer = render::Renderer::from_window(window,
                                                 render::DriverAuto,
                                                 render::Accelerated).unwrap();
    let mut game_loop = Loop::new(renderer);

    let mut previousTime = timer::get_ticks();
    'main : loop {
        'event : loop {
            match event::poll_event() {
                event::QuitEvent(_) => break 'main,
                event::KeyDownEvent(_, _, key, _, _) => match key {
                    keycode::EscapeKey => break 'main,
                    _ => game_loop.handlekey(true, key)
                },
                event::KeyUpEvent(_, _, key, _, _) => match key {
                    _ => game_loop.handlekey(false, key)
                },
                event::NoEvent => break 'event,
                _ => ()
            }
        }

        game_loop.update();

        let time_taken = timer::get_ticks() - previousTime;
        if time_taken > MS_PER_FRAME {
            continue;
        }
        timer::delay(MS_PER_FRAME - time_taken);
        previousTime = timer::get_ticks();
    }

    sdl::quit();
}
<commit_msg>Fix the game loop code. (Still needs work)<commit_after>extern crate libc;
extern crate sdl = "sdl2";
use sdl::{video, event, keycode, timer, render};

use std::io::BufWriter;

use game::Loop;
mod game;

static MS_PER_FRAME : uint = 15; // About 60fps

fn main() {
    sdl::init(sdl::InitAudio | sdl::InitVideo);

    let window = video::Window::new("Asteroids Plus",
                                    video::PosCentered, video::PosCentered,
                                    512, 512,
                                    video::WindowFlags::empty()).unwrap();
    let renderer = render::Renderer::from_window(window,
                                                 render::DriverAuto,
                                                 render::Accelerated).unwrap();
    let mut game_loop = Loop::new(renderer);
    let mut previous_time = timer::get_ticks();
    let mut sample_time = timer::get_ticks();
    let mut count = 0u;

    'main : loop {
        'event : loop {
            match event::poll_event() {
                event::QuitEvent(_) => break 'main,
                event::KeyDownEvent(_, _, key, _, _) => match key {
                    keycode::EscapeKey => break 'main,
                    _ => game_loop.handlekey(true, key)
                },
                event::KeyUpEvent(_, _, key, _, _) => match key {
                    _ => game_loop.handlekey(false, key)
                },
                event::NoEvent => break 'event,
                _ => (),
            }
        }

        game_loop.update();

        let current_time = timer::get_ticks();
        let time_taken = current_time - previous_time;
        previous_time = current_time;
        if count == 0 {
            println!("FPS: {}", 64000/(current_time - sample_time));
            count = 128;
            sample_time = current_time;
        } else { count -= 1; }
        if time_taken < MS_PER_FRAME {
            timer::delay(MS_PER_FRAME - time_taken);
        }
    }

    println!("Test!");
    sdl::quit();
}
<|endoftext|>


<commit_before>//! Graph algorithms.
//!
//! It is a goal to gradually migrate the algorithms to be based on graph traits
//! so that they are generally applicable. For now, most of these use only the
//! **Graph** type.

use std::collections::BinaryHeap;
use std::borrow::{Borrow};
use std::cmp::min;

use super::{
    Graph,
    Undirected,
    EdgeType,
    Outgoing,
    Incoming,
    Dfs,
};
use scored::MinScored;
use super::visit::{
    GraphRef,
    Visitable,
    VisitMap,
    IntoNeighbors,
    IntoNeighborsDirected,
    IntoNodeIdentifiers,
    IntoExternals,
    NodeIndexable,
    NodeCompactIndexable,
    IntoEdgeReferences,
    EdgeRef,
    DfsPostOrder,
    Reversed,
};
use super::unionfind::UnionFind;
use super::graph::{
    IndexType,
    NodeIndex,
};

pub use super::isomorphism::{
    is_isomorphic,
    is_isomorphic_matching,
};
pub use super::dijkstra::dijkstra;

/// [Generic] Return the number of connected components of the graph.
///
/// For a directed graph, this is the *weakly* connected components.
pub fn connected_components<G>(g: G) -> usize
    where G: NodeCompactIndexable + IntoEdgeReferences,
{
    let mut vertex_sets = UnionFind::new(g.node_bound());
    for edge in g.edge_references() {
        let (a, b) = (edge.source(), edge.target());

        // union the two vertices of the edge
        vertex_sets.union(G::to_index(a), G::to_index(b));
    }
    let mut labels = vertex_sets.into_labeling();
    labels.sort();
    labels.dedup();
    labels.len()
}

/// [Generic] Return `true` if the input graph contains a cycle.
///
/// Always treats the input graph as if undirected.
pub fn is_cyclic_undirected<G>(g: G) -> bool
    where G: NodeIndexable + IntoEdgeReferences
{
    let mut edge_sets = UnionFind::new(g.node_bound());
    for edge in g.edge_references() {
        let (a, b) = (edge.source(), edge.target());

        // union the two vertices of the edge
        //  -- if they were already the same, then we have a cycle
        if !edge_sets.union(G::to_index(a), G::to_index(b)) {
            return true
        }
    }
    false
}

/*
/// **Deprecated: Renamed to `is_cyclic_undirected`.**
pub fn is_cyclic<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>) -> bool
    where Ty: EdgeType,
          Ix: IndexType,
{
    is_cyclic_undirected(g)
}
*/

/// [Generic] Perform a topological sort of a directed graph `g`.
///
/// Visit each node in order (if it is part of a topological order).
///
/// You can pass `g` as either **&Graph** or **&mut Graph**, and it
/// will be passed on to the visitor closure.
#[inline]
fn toposort_generic<G, F>(g: G, mut visit: F)
    where G: IntoNeighborsDirected + IntoExternals + Visitable,
          F: FnMut(G, G::NodeId),
{
    let mut ordered = g.borrow().visit_map();
    let mut tovisit = Vec::new();

    // find all initial nodes
    tovisit.extend(g.externals(Incoming));

    // Take an unvisited element and find which of its neighbors are next
    while let Some(nix) = tovisit.pop() {
        if ordered.is_visited(&nix) {
            continue;
        }
        visit(g, nix.clone());
        ordered.visit(nix.clone());
        for neigh in g.neighbors_directed(nix, Outgoing) {
            // Look at each neighbor, and those that only have incoming edges
            // from the already ordered list, they are the next to visit.
            if g.neighbors_directed(neigh.clone(), Incoming)
                .all(|b| ordered.is_visited(&b)) {
                tovisit.push(neigh);
            }
        }
    }
}

/// [Generic] Return `true` if the input directed graph contains a cycle.
///
/// Using the topological sort algorithm.
pub fn is_cyclic_directed<G>(g: G) -> bool
    where G: IntoNodeIdentifiers + IntoNeighborsDirected + IntoExternals + Visitable,
{
    let mut n_ordered = 0;
    toposort_generic(g, |_, _| n_ordered += 1);
    n_ordered != g.node_count()
}

#[derive(Clone, Debug)]
pub struct HasPathState<N, VM> {
    dfs: Dfs<N, VM>,
}

impl<N, VM> HasPathState<N, VM>
    where N: Copy,
          VM: VisitMap<N>,
{
    /// Create a new `HasPathState`
    pub fn new<G>(graph: G) -> Self
        where G: GraphRef + Visitable<NodeId=N, Map=VM>,
    {
        HasPathState {
            dfs: Dfs::empty(graph)
        }
    }
}

/// [Generic] Check if there exists a path starting at `from` and reaching `to`.
///
/// `from` and `to` are equal, this function returns true.
pub fn has_path_connecting<G>(g: G, from: G::NodeId, to: G::NodeId,
                              state: Option<&mut HasPathState<G::NodeId, G::Map>>)
    -> bool
    where G: IntoNeighbors + Visitable,
          G::NodeId: PartialEq,
{
    let mut local_visitor;
    let dfs = if let Some(v) = state { &mut v.dfs } else {
        local_visitor = Dfs::empty(g);
        &mut local_visitor
    };
    dfs.reset(g);
    dfs.move_to(from);
    while let Some(x) = dfs.next(g) {
        if x == to {
            return true;
        }
    }
    false
}

/// [Generic] Perform a topological sort of a directed graph.
///
/// Return a vector of nodes in topological order: each node is ordered
/// before its successors.
///
/// If the returned vec contains less than all the nodes of the graph, then
/// the graph was cyclic.
pub fn toposort<G>(g: G) -> Vec<G::NodeId>
    where G: IntoNodeIdentifiers + IntoNeighborsDirected + IntoExternals + Visitable,
{
    let mut order = Vec::with_capacity(g.node_count());
    toposort_generic(g, |_, ix| order.push(ix));
    order
}

/// [Generic] Compute the *strongly connected components* using Kosaraju's algorithm.
///
/// Return a vector where each element is a strongly connected component (scc).
///
/// The order of `NodeId` within each scc is arbitrary, but the order of
/// the sccs is their postorder (reverse topological sort).
///
/// This implementation is iterative and does two passes over the nodes.
///
/// For an undirected graph, the sccs are simply the connected components.
pub fn scc<G>(g: G) -> Vec<Vec<G::NodeId>>
    where G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
{
    let mut dfs = DfsPostOrder::empty(g);

    // First phase, reverse dfs pass, compute finishing times.
    // http://stackoverflow.com/a/26780899/161659
    let mut finish_order = Vec::with_capacity(g.node_count());
    for i in g.node_identifiers() {
        if dfs.discovered.is_visited(&i) {
            continue
        }

        dfs.move_to(i);
        while let Some(nx) = dfs.next(Reversed(g)) {
            finish_order.push(nx);
        }
    }

    let mut dfs = Dfs::from_parts(dfs.stack, dfs.discovered);
    dfs.reset(g);
    let mut sccs = Vec::new();

    // Second phase
    // Process in decreasing finishing time order
    for i in finish_order.into_iter().rev() {
        if dfs.discovered.is_visited(&i) {
            continue;
        }
        // Move to the leader node `i`.
        dfs.move_to(i);
        let mut scc = Vec::new();
        while let Some(nx) = dfs.next(g) {
            scc.push(nx);
        }
        sccs.push(scc);
    }
    sccs
}

/// [Generic] Compute the *strongly connected components* using Tarjan's algorithm.
///
/// Return a vector where each element is a strongly connected component (scc).
///
/// The order of `NodeId` within each scc is arbitrary, but the order of
/// the sccs is their postorder (reverse topological sort).
///
/// This implementation is recursive and does one pass over the nodes.
///
/// For an undirected graph, the sccs are simply the connected components.
pub fn tarjan_scc<G>(g: G) -> Vec<Vec<G::NodeId>>
    where G: IntoNodeIdentifiers + IntoNeighbors + NodeIndexable
{
    #[derive(Copy, Clone)]
    #[derive(Debug)]
    struct NodeData {
        index: Option<usize>,
        lowlink: usize,
        on_stack: bool,
    }

    #[derive(Debug)]
    struct Data<'a, G>
        where G: NodeIndexable,
          G::NodeId: 'a
    {
        index: usize,
        nodes: Vec<NodeData>,
        stack: Vec<G::NodeId>,
        sccs: &'a mut Vec<Vec<G::NodeId>>,
    }

    fn scc_visit<G>(v: G::NodeId, g: G, data: &mut Data<G>)
        where G: IntoNeighbors + NodeIndexable
    {
        macro_rules! node {
            ($node:expr) => (data.nodes[G::to_index($node)])
        }

        if node![v].index.is_some() {
            // already visited
            return;
        }

        let v_index = data.index;
        node![v].index = Some(v_index);
        node![v].lowlink = v_index;
        node![v].on_stack = true;
        data.stack.push(v);
        data.index += 1;

        for w in g.neighbors(v) {
            match node![w].index {
                None => {
                    scc_visit(w, g, data);
                    node![v].lowlink = min(node![v].lowlink, node![w].lowlink);
                }
                Some(w_index) => {
                    if node![w].on_stack {
                        // Successor w is in stack S and hence in the current SCC
                        let v_lowlink = &mut node![v].lowlink;
                        *v_lowlink = min(*v_lowlink, w_index);
                    }
                }
            }
        }

        // If v is a root node, pop the stack and generate an SCC
        if let Some(v_index) = node![v].index {
            if node![v].lowlink == v_index {
                let mut cur_scc = Vec::new();
                loop {
                    let w = data.stack.pop().unwrap();
                    node![w].on_stack = false;
                    cur_scc.push(w);
                    if G::to_index(w) == G::to_index(v) { break; }
                }
                data.sccs.push(cur_scc);
            }
        }
    }

    let mut sccs = Vec::new();
    {
        let map = (0..g.node_bound()).map(|_| {
            NodeData { index: None, lowlink: !0, on_stack: false }
        }).collect();

        let mut data = Data {
            index: 0,
            nodes: map,
            stack: Vec::new(),
            sccs: &mut sccs,
        };

        for n in g.node_identifiers() {
            scc_visit(n, g, &mut data);
        }
    }
    sccs
}

/// [Graph] Condense every strongly connected component into a single node and return the result.
///
/// If `make_acyclic` is true, self-loops and multi edges are ignored, guaranteeing that
/// the output is acyclic.
pub fn condensation<N, E, Ty, Ix>(g: Graph<N, E, Ty, Ix>, make_acyclic: bool) -> Graph<Vec<N>, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType,
{
    let sccs = scc(&g);
    let mut condensed: Graph<Vec<N>, E, Ty, Ix> = Graph::with_capacity(sccs.len(), g.edge_count());

    // Build a map from old indices to new ones.
    let mut node_map = vec![NodeIndex::end(); g.node_count()];
    for comp in sccs {
        let new_nix = condensed.add_node(Vec::new());
        for nix in comp {
            node_map[nix.index()] = new_nix;
        }
    }

    // Consume nodes and edges of the old graph and insert them into the new one.
    let (nodes, edges) = g.into_nodes_edges();
    for (nix, node) in nodes.into_iter().enumerate() {
        condensed[node_map[nix]].push(node.weight);
    }
    for edge in edges {
        let source = node_map[edge.source().index()];
        let target = node_map[edge.target().index()];
        if make_acyclic {
            if source != target {
                condensed.update_edge(source, target, edge.weight);
            }
        } else {
            condensed.add_edge(source, target, edge.weight);
        }
    }
    condensed
}

/// [Graph] Compute a *minimum spanning tree* of a graph.
///
/// Treat the input graph as undirected.
///
/// Using Kruskal's algorithm with runtime **O(|E| log |E|)**. We actually
/// return a minimum spanning forest, i.e. a minimum spanning tree for each connected
/// component of the graph.
///
/// The resulting graph has all the vertices of the input graph (with identical node indices),
/// and **|V| - c** edges, where **c** is the number of connected components in `g`.
pub fn min_spanning_tree<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>)
    -> Graph<N, E, Undirected, Ix>
    where N: Clone,
          E: Clone + PartialOrd,
          Ty: EdgeType,
          Ix: IndexType,
{
    if g.node_count() == 0 {
        return Graph::with_capacity(0, 0)
    }

    // Create a mst skeleton by copying all nodes
    let mut mst = Graph::with_capacity(g.node_count(), g.node_count() - 1);
    for node in g.raw_nodes() {
        mst.add_node(node.weight.clone());
    }

    // Initially each vertex is its own disjoint subgraph, track the connectedness
    // of the pre-MST with a union & find datastructure.
    let mut subgraphs = UnionFind::new(g.node_count());

    let mut sort_edges = BinaryHeap::with_capacity(g.edge_count());
    for edge in g.edge_references() {
        sort_edges.push(MinScored(edge.weight().clone(), (edge.source(), edge.target())));
    }

    // Kruskal's algorithm.
    // Algorithm is this:
    //
    // 1. Create a pre-MST with all the vertices and no edges.
    // 2. Repeat:
    //
    //  a. Remove the shortest edge from the original graph.
    //  b. If the edge connects two disjoint trees in the pre-MST,
    //     add the edge.
    while let Some(MinScored(score, (a, b))) = sort_edges.pop() {
        // check if the edge would connect two disjoint parts
        if subgraphs.union(a.index(), b.index()) {
            mst.add_edge(a, b, score);
        }
    }

    debug_assert!(mst.node_count() == g.node_count());
    debug_assert!(mst.edge_count() < g.node_count());
    mst
}
<commit_msg>tarjan_scc: Use vec-repeat macro<commit_after>//! Graph algorithms.
//!
//! It is a goal to gradually migrate the algorithms to be based on graph traits
//! so that they are generally applicable. For now, most of these use only the
//! **Graph** type.

use std::collections::BinaryHeap;
use std::borrow::{Borrow};
use std::cmp::min;

use super::{
    Graph,
    Undirected,
    EdgeType,
    Outgoing,
    Incoming,
    Dfs,
};
use scored::MinScored;
use super::visit::{
    GraphRef,
    Visitable,
    VisitMap,
    IntoNeighbors,
    IntoNeighborsDirected,
    IntoNodeIdentifiers,
    IntoExternals,
    NodeIndexable,
    NodeCompactIndexable,
    IntoEdgeReferences,
    EdgeRef,
    DfsPostOrder,
    Reversed,
};
use super::unionfind::UnionFind;
use super::graph::{
    IndexType,
    NodeIndex,
};

pub use super::isomorphism::{
    is_isomorphic,
    is_isomorphic_matching,
};
pub use super::dijkstra::dijkstra;

/// [Generic] Return the number of connected components of the graph.
///
/// For a directed graph, this is the *weakly* connected components.
pub fn connected_components<G>(g: G) -> usize
    where G: NodeCompactIndexable + IntoEdgeReferences,
{
    let mut vertex_sets = UnionFind::new(g.node_bound());
    for edge in g.edge_references() {
        let (a, b) = (edge.source(), edge.target());

        // union the two vertices of the edge
        vertex_sets.union(G::to_index(a), G::to_index(b));
    }
    let mut labels = vertex_sets.into_labeling();
    labels.sort();
    labels.dedup();
    labels.len()
}

/// [Generic] Return `true` if the input graph contains a cycle.
///
/// Always treats the input graph as if undirected.
pub fn is_cyclic_undirected<G>(g: G) -> bool
    where G: NodeIndexable + IntoEdgeReferences
{
    let mut edge_sets = UnionFind::new(g.node_bound());
    for edge in g.edge_references() {
        let (a, b) = (edge.source(), edge.target());

        // union the two vertices of the edge
        //  -- if they were already the same, then we have a cycle
        if !edge_sets.union(G::to_index(a), G::to_index(b)) {
            return true
        }
    }
    false
}

/*
/// **Deprecated: Renamed to `is_cyclic_undirected`.**
pub fn is_cyclic<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>) -> bool
    where Ty: EdgeType,
          Ix: IndexType,
{
    is_cyclic_undirected(g)
}
*/

/// [Generic] Perform a topological sort of a directed graph `g`.
///
/// Visit each node in order (if it is part of a topological order).
///
/// You can pass `g` as either **&Graph** or **&mut Graph**, and it
/// will be passed on to the visitor closure.
#[inline]
fn toposort_generic<G, F>(g: G, mut visit: F)
    where G: IntoNeighborsDirected + IntoExternals + Visitable,
          F: FnMut(G, G::NodeId),
{
    let mut ordered = g.borrow().visit_map();
    let mut tovisit = Vec::new();

    // find all initial nodes
    tovisit.extend(g.externals(Incoming));

    // Take an unvisited element and find which of its neighbors are next
    while let Some(nix) = tovisit.pop() {
        if ordered.is_visited(&nix) {
            continue;
        }
        visit(g, nix.clone());
        ordered.visit(nix.clone());
        for neigh in g.neighbors_directed(nix, Outgoing) {
            // Look at each neighbor, and those that only have incoming edges
            // from the already ordered list, they are the next to visit.
            if g.neighbors_directed(neigh.clone(), Incoming)
                .all(|b| ordered.is_visited(&b)) {
                tovisit.push(neigh);
            }
        }
    }
}

/// [Generic] Return `true` if the input directed graph contains a cycle.
///
/// Using the topological sort algorithm.
pub fn is_cyclic_directed<G>(g: G) -> bool
    where G: IntoNodeIdentifiers + IntoNeighborsDirected + IntoExternals + Visitable,
{
    let mut n_ordered = 0;
    toposort_generic(g, |_, _| n_ordered += 1);
    n_ordered != g.node_count()
}

#[derive(Clone, Debug)]
pub struct HasPathState<N, VM> {
    dfs: Dfs<N, VM>,
}

impl<N, VM> HasPathState<N, VM>
    where N: Copy,
          VM: VisitMap<N>,
{
    /// Create a new `HasPathState`
    pub fn new<G>(graph: G) -> Self
        where G: GraphRef + Visitable<NodeId=N, Map=VM>,
    {
        HasPathState {
            dfs: Dfs::empty(graph)
        }
    }
}

/// [Generic] Check if there exists a path starting at `from` and reaching `to`.
///
/// `from` and `to` are equal, this function returns true.
pub fn has_path_connecting<G>(g: G, from: G::NodeId, to: G::NodeId,
                              state: Option<&mut HasPathState<G::NodeId, G::Map>>)
    -> bool
    where G: IntoNeighbors + Visitable,
          G::NodeId: PartialEq,
{
    let mut local_visitor;
    let dfs = if let Some(v) = state { &mut v.dfs } else {
        local_visitor = Dfs::empty(g);
        &mut local_visitor
    };
    dfs.reset(g);
    dfs.move_to(from);
    while let Some(x) = dfs.next(g) {
        if x == to {
            return true;
        }
    }
    false
}

/// [Generic] Perform a topological sort of a directed graph.
///
/// Return a vector of nodes in topological order: each node is ordered
/// before its successors.
///
/// If the returned vec contains less than all the nodes of the graph, then
/// the graph was cyclic.
pub fn toposort<G>(g: G) -> Vec<G::NodeId>
    where G: IntoNodeIdentifiers + IntoNeighborsDirected + IntoExternals + Visitable,
{
    let mut order = Vec::with_capacity(g.node_count());
    toposort_generic(g, |_, ix| order.push(ix));
    order
}

/// [Generic] Compute the *strongly connected components* using Kosaraju's algorithm.
///
/// Return a vector where each element is a strongly connected component (scc).
///
/// The order of `NodeId` within each scc is arbitrary, but the order of
/// the sccs is their postorder (reverse topological sort).
///
/// This implementation is iterative and does two passes over the nodes.
///
/// For an undirected graph, the sccs are simply the connected components.
pub fn scc<G>(g: G) -> Vec<Vec<G::NodeId>>
    where G: IntoNeighborsDirected + Visitable + IntoNodeIdentifiers,
{
    let mut dfs = DfsPostOrder::empty(g);

    // First phase, reverse dfs pass, compute finishing times.
    // http://stackoverflow.com/a/26780899/161659
    let mut finish_order = Vec::with_capacity(g.node_count());
    for i in g.node_identifiers() {
        if dfs.discovered.is_visited(&i) {
            continue
        }

        dfs.move_to(i);
        while let Some(nx) = dfs.next(Reversed(g)) {
            finish_order.push(nx);
        }
    }

    let mut dfs = Dfs::from_parts(dfs.stack, dfs.discovered);
    dfs.reset(g);
    let mut sccs = Vec::new();

    // Second phase
    // Process in decreasing finishing time order
    for i in finish_order.into_iter().rev() {
        if dfs.discovered.is_visited(&i) {
            continue;
        }
        // Move to the leader node `i`.
        dfs.move_to(i);
        let mut scc = Vec::new();
        while let Some(nx) = dfs.next(g) {
            scc.push(nx);
        }
        sccs.push(scc);
    }
    sccs
}

/// [Generic] Compute the *strongly connected components* using Tarjan's algorithm.
///
/// Return a vector where each element is a strongly connected component (scc).
///
/// The order of `NodeId` within each scc is arbitrary, but the order of
/// the sccs is their postorder (reverse topological sort).
///
/// This implementation is recursive and does one pass over the nodes.
///
/// For an undirected graph, the sccs are simply the connected components.
pub fn tarjan_scc<G>(g: G) -> Vec<Vec<G::NodeId>>
    where G: IntoNodeIdentifiers + IntoNeighbors + NodeIndexable
{
    #[derive(Copy, Clone)]
    #[derive(Debug)]
    struct NodeData {
        index: Option<usize>,
        lowlink: usize,
        on_stack: bool,
    }

    #[derive(Debug)]
    struct Data<'a, G>
        where G: NodeIndexable,
          G::NodeId: 'a
    {
        index: usize,
        nodes: Vec<NodeData>,
        stack: Vec<G::NodeId>,
        sccs: &'a mut Vec<Vec<G::NodeId>>,
    }

    fn scc_visit<G>(v: G::NodeId, g: G, data: &mut Data<G>)
        where G: IntoNeighbors + NodeIndexable
    {
        macro_rules! node {
            ($node:expr) => (data.nodes[G::to_index($node)])
        }

        if node![v].index.is_some() {
            // already visited
            return;
        }

        let v_index = data.index;
        node![v].index = Some(v_index);
        node![v].lowlink = v_index;
        node![v].on_stack = true;
        data.stack.push(v);
        data.index += 1;

        for w in g.neighbors(v) {
            match node![w].index {
                None => {
                    scc_visit(w, g, data);
                    node![v].lowlink = min(node![v].lowlink, node![w].lowlink);
                }
                Some(w_index) => {
                    if node![w].on_stack {
                        // Successor w is in stack S and hence in the current SCC
                        let v_lowlink = &mut node![v].lowlink;
                        *v_lowlink = min(*v_lowlink, w_index);
                    }
                }
            }
        }

        // If v is a root node, pop the stack and generate an SCC
        if let Some(v_index) = node![v].index {
            if node![v].lowlink == v_index {
                let mut cur_scc = Vec::new();
                loop {
                    let w = data.stack.pop().unwrap();
                    node![w].on_stack = false;
                    cur_scc.push(w);
                    if G::to_index(w) == G::to_index(v) { break; }
                }
                data.sccs.push(cur_scc);
            }
        }
    }

    let mut sccs = Vec::new();
    {
        let map = vec![NodeData { index: None, lowlink: !0, on_stack: false }; g.node_bound()];

        let mut data = Data {
            index: 0,
            nodes: map,
            stack: Vec::new(),
            sccs: &mut sccs,
        };

        for n in g.node_identifiers() {
            scc_visit(n, g, &mut data);
        }
    }
    sccs
}

/// [Graph] Condense every strongly connected component into a single node and return the result.
///
/// If `make_acyclic` is true, self-loops and multi edges are ignored, guaranteeing that
/// the output is acyclic.
pub fn condensation<N, E, Ty, Ix>(g: Graph<N, E, Ty, Ix>, make_acyclic: bool) -> Graph<Vec<N>, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType,
{
    let sccs = scc(&g);
    let mut condensed: Graph<Vec<N>, E, Ty, Ix> = Graph::with_capacity(sccs.len(), g.edge_count());

    // Build a map from old indices to new ones.
    let mut node_map = vec![NodeIndex::end(); g.node_count()];
    for comp in sccs {
        let new_nix = condensed.add_node(Vec::new());
        for nix in comp {
            node_map[nix.index()] = new_nix;
        }
    }

    // Consume nodes and edges of the old graph and insert them into the new one.
    let (nodes, edges) = g.into_nodes_edges();
    for (nix, node) in nodes.into_iter().enumerate() {
        condensed[node_map[nix]].push(node.weight);
    }
    for edge in edges {
        let source = node_map[edge.source().index()];
        let target = node_map[edge.target().index()];
        if make_acyclic {
            if source != target {
                condensed.update_edge(source, target, edge.weight);
            }
        } else {
            condensed.add_edge(source, target, edge.weight);
        }
    }
    condensed
}

/// [Graph] Compute a *minimum spanning tree* of a graph.
///
/// Treat the input graph as undirected.
///
/// Using Kruskal's algorithm with runtime **O(|E| log |E|)**. We actually
/// return a minimum spanning forest, i.e. a minimum spanning tree for each connected
/// component of the graph.
///
/// The resulting graph has all the vertices of the input graph (with identical node indices),
/// and **|V| - c** edges, where **c** is the number of connected components in `g`.
pub fn min_spanning_tree<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>)
    -> Graph<N, E, Undirected, Ix>
    where N: Clone,
          E: Clone + PartialOrd,
          Ty: EdgeType,
          Ix: IndexType,
{
    if g.node_count() == 0 {
        return Graph::with_capacity(0, 0)
    }

    // Create a mst skeleton by copying all nodes
    let mut mst = Graph::with_capacity(g.node_count(), g.node_count() - 1);
    for node in g.raw_nodes() {
        mst.add_node(node.weight.clone());
    }

    // Initially each vertex is its own disjoint subgraph, track the connectedness
    // of the pre-MST with a union & find datastructure.
    let mut subgraphs = UnionFind::new(g.node_count());

    let mut sort_edges = BinaryHeap::with_capacity(g.edge_count());
    for edge in g.edge_references() {
        sort_edges.push(MinScored(edge.weight().clone(), (edge.source(), edge.target())));
    }

    // Kruskal's algorithm.
    // Algorithm is this:
    //
    // 1. Create a pre-MST with all the vertices and no edges.
    // 2. Repeat:
    //
    //  a. Remove the shortest edge from the original graph.
    //  b. If the edge connects two disjoint trees in the pre-MST,
    //     add the edge.
    while let Some(MinScored(score, (a, b))) = sort_edges.pop() {
        // check if the edge would connect two disjoint parts
        if subgraphs.union(a.index(), b.index()) {
            mst.add_edge(a, b, score);
        }
    }

    debug_assert!(mst.node_count() == g.node_count());
    debug_assert!(mst.edge_count() < g.node_count());
    mst
}
<|endoftext|>


<commit_before>use super::*;

use std::iter;

/// Doc-comments are promoted to attributes that have `is_sugared_doc` = true
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Attribute {
    pub style: AttrStyle,

    /// The path of the attribute.
    ///
    /// E.g. `derive` in `#[derive(Copy)]`
    /// E.g. `crate::precondition` in `#[crate::precondition x < 5]`
    pub path: Path,

    /// Any tokens after the path.
    ///
    /// E.g. `( Copy )` in `#[derive(Copy)]`
    /// E.g. `x < 5` in `#[crate::precondition x < 5]`
    pub tts: Vec<TokenTree>,

    pub is_sugared_doc: bool,
}

impl Attribute {
    /// Parses the tokens after the path as a [`MetaItem`](enum.MetaItem.html) if possible.
    pub fn meta_item(&self) -> Option<MetaItem> {
        if self.tts.is_empty() {
            return Some(MetaItem::Word);
        }

        if self.tts.len() == 1 {
            if let TokenTree::Delimited(Delimited { delim: DelimToken::Paren, ref tts }) = self.tts[0] {
                fn nested_meta_item_from_tokens(tts: &[TokenTree]) -> Option<(NestedMetaItem, &[TokenTree])> {
                    assert!(!tts.is_empty());

                    match tts[0] {
                        TokenTree::Token(Token::Literal(ref lit)) => {
                            Some((NestedMetaItem::Literal(lit.clone()), &tts[1..]))
                        }

                        TokenTree::Token(Token::Ident(ref ident)) => {
                            if tts.len() >= 3 {
                                match (&tts[1], &tts[2]) {
                                    (&TokenTree::Token(Token::Eq), &TokenTree::Token(Token::Literal(ref lit))) => {
                                        return Some((NestedMetaItem::MetaItem(ident.clone(), MetaItem::NameValue(lit.clone())), &tts[3..]));
                                    }

                                    _ => {}
                                }
                            }

                            if tts.len() >= 2 {
                                if let TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: ref inner_tts }) = tts[1] {
                                    return match list_of_nested_meta_items_from_tokens(vec![], inner_tts) {
                                        Some(nested_meta_items) => {
                                            Some((NestedMetaItem::MetaItem(ident.clone(), MetaItem::List(nested_meta_items)), &tts[2..]))
                                        }

                                        None => None
                                    };
                                }
                            }

                            Some((NestedMetaItem::MetaItem(ident.clone(), MetaItem::Word), &tts[1..]))
                        }

                        _ => None
                    }
                }

                fn list_of_nested_meta_items_from_tokens(mut result: Vec<NestedMetaItem>, tts: &[TokenTree]) -> Option<Vec<NestedMetaItem>> {
                    if tts.is_empty() {
                        return Some(result);
                    }

                    match nested_meta_item_from_tokens(tts) {
                        Some((nested_meta_item, rest)) => {
                            result.push(nested_meta_item);
                            if rest.is_empty() {
                                list_of_nested_meta_items_from_tokens(result, rest)
                            }
                            else if let TokenTree::Token(Token::Comma) = rest[0] {
                                list_of_nested_meta_items_from_tokens(result, &rest[1..])
                            }
                            else {
                                None
                            }
                        }

                        None => None
                    }
                }

                if let Some(nested_meta_items) = list_of_nested_meta_items_from_tokens(vec![], tts) {
                    return Some(MetaItem::List(nested_meta_items));
                }
            }
        }

        if self.tts.len() == 2 {
            match (&self.tts[0], &self.tts[1]) {
                (&TokenTree::Token(Token::Eq), &TokenTree::Token(Token::Literal(ref lit))) => {
                    return Some(MetaItem::NameValue(lit.clone()));
                }

                _ => {}
            }
        }

        None
    }
}

/// Distinguishes between Attributes that decorate items and Attributes that
/// are contained as statements within items. These two cases need to be
/// distinguished for pretty-printing.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum AttrStyle {
    /// Attribute of the form `#![...]`.
    Outer,

    /// Attribute of the form `#[...]`.
    Inner,
}

/// A compile-time attribute item.
///
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum MetaItem {
    /// Word meta item.
    ///
    /// E.g. `test` as in `#[test]`
    Word,

    /// List meta item.
    ///
    /// E.g. `derive(..)` as in `#[derive(..)]`
    List(Vec<NestedMetaItem>),

    /// Name-value meta item.
    ///
    /// E.g. `feature = "foo"` as in `#[feature = "foo"]`
    NameValue(Lit),
}

/// Possible values inside of compile-time attribute lists.
///
/// E.g. the '..' in `#[name(..)]`.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum NestedMetaItem {
    /// A full `MetaItem`.
    ///
    /// E.g. `Copy` in `#[derive(Copy)]` would be a `(Ident::from("Copy"), MetaItem::Word)`.
    MetaItem(Ident, MetaItem),

    /// A Rust literal.
    ///
    /// E.g. `"name"` in `#[rename("name")]`.
    Literal(Lit),
}

pub trait FilterAttrs<'a> {
    type Ret: Iterator<Item = &'a Attribute>;

    fn outer(self) -> Self::Ret;
    fn inner(self) -> Self::Ret;
}

impl<'a, T> FilterAttrs<'a> for T
    where T: IntoIterator<Item = &'a Attribute>
{
    type Ret = iter::Filter<T::IntoIter, fn(&&Attribute) -> bool>;

    fn outer(self) -> Self::Ret {
        fn is_outer(attr: &&Attribute) -> bool {
            attr.style == AttrStyle::Outer
        }
        self.into_iter().filter(is_outer)
    }

    fn inner(self) -> Self::Ret {
        fn is_inner(attr: &&Attribute) -> bool {
            attr.style == AttrStyle::Inner
        }
        self.into_iter().filter(is_inner)
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use lit::{Lit, StrStyle};
    use mac::{Token, TokenTree};
    use mac::parsing::token_trees;
    use synom::space::{block_comment, whitespace};
    use ty::parsing::path;

    #[cfg(feature = "full")]
    named!(pub inner_attr -> Attribute, alt!(
        do_parse!(
            punct!("#") >>
            punct!("!") >>
            path_and_tts: delimited!(
                punct!("["),
                tuple!(path, token_trees),
                punct!("]")
            ) >>
            ({
                let (path, tts) = path_and_tts;

                Attribute {
                    style: AttrStyle::Inner,
                    path: path,
                    tts: tts,
                    is_sugared_doc: false,
                }
            })
        )
        |
        do_parse!(
            punct!("//!") >>
            content: take_until!("\n") >>
            (Attribute {
                style: AttrStyle::Inner,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(format!("//!{}", content).into(), StrStyle::Cooked))),
                ],
                is_sugared_doc: true,
            })
        )
        |
        do_parse!(
            option!(whitespace) >>
            peek!(tag!("/*!")) >>
            com: block_comment >>
            (Attribute {
                style: AttrStyle::Inner,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(com.into(), StrStyle::Cooked))),
                ],
                is_sugared_doc: true,
            })
        )
    ));

    named!(pub outer_attr -> Attribute, alt!(
        do_parse!(
            punct!("#") >>
            path_and_tts: delimited!(
                punct!("["),
                tuple!(path, token_trees),
                punct!("]")
            ) >>
            ({
                let (path, tts) = path_and_tts;

                Attribute {
                    style: AttrStyle::Outer,
                    path: path,
                    tts: tts,
                    is_sugared_doc: false,
                }
            })
        )
        |
        do_parse!(
            punct!("///") >>
            not!(tag!("/")) >>
            content: take_until!("\n") >>
            (Attribute {
                style: AttrStyle::Outer,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(format!("///{}", content).into(), StrStyle::Cooked))),
                ],
                is_sugared_doc: true,
            })
        )
        |
        do_parse!(
            option!(whitespace) >>
            peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
            com: block_comment >>
            (Attribute {
                style: AttrStyle::Outer,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(com.into(), StrStyle::Cooked))),
                ],
                is_sugared_doc: true,
            })
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use lit::{Lit, StrStyle};
    use mac::{Token, TokenTree};
    use quote::{Tokens, ToTokens};

    impl ToTokens for Attribute {
        fn to_tokens(&self, tokens: &mut Tokens) {
            // If this was a sugared doc, emit it in its original form instead of `#[doc = "..."]`
            match *self {
                Attribute {
                    style,
                    path: Path { global: false, ref segments },
                    ref tts,
                    is_sugared_doc: true,
                } if segments.len() == 1 &&
                     segments[0].ident == "doc" &&
                     segments[0].parameters.is_empty() &&
                     tts.len() == 2 =>
                {
                    match (&self.tts[0], &self.tts[1]) {
                        (&TokenTree::Token(Token::Eq),
                         &TokenTree::Token(Token::Literal(Lit::Str(ref value, StrStyle::Cooked)))) =>
                        {
                            match style {
                                AttrStyle::Inner if value.starts_with("//!") => {
                                    tokens.append(&format!("{}\n", value));
                                    return;
                                }
                                AttrStyle::Inner if value.starts_with("/*!") => {
                                    tokens.append(value);
                                    return;
                                }
                                AttrStyle::Outer if value.starts_with("///") => {
                                    tokens.append(&format!("{}\n", value));
                                    return;
                                }
                                AttrStyle::Outer if value.starts_with("/**") => {
                                    tokens.append(value);
                                    return;
                                }
                                _ => {}
                            }
                        }

                        _ => {}
                    }
                }

                _ => {}
            }

            tokens.append("#");
            if let AttrStyle::Inner = self.style {
                tokens.append("!");
            }
            tokens.append("[");
            self.path.to_tokens(tokens);
            tokens.append_all(&self.tts);
            tokens.append("]");
        }
    }

    impl ToTokens for MetaItem {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                MetaItem::Word => {}
                MetaItem::List(ref inner) => {
                    tokens.append("(");
                    tokens.append_separated(inner, ",");
                    tokens.append(")");
                }
                MetaItem::NameValue(ref value) => {
                    tokens.append("=");
                    value.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for NestedMetaItem {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                NestedMetaItem::MetaItem(ref ident, ref nested) => {
                    ident.to_tokens(tokens);
                    nested.to_tokens(tokens);
                }
                NestedMetaItem::Literal(ref lit) => {
                    lit.to_tokens(tokens);
                }
            }
        }
    }
}
<commit_msg>fixup! Fix old rust again.<commit_after>use super::*;

use std::iter;

/// Doc-comments are promoted to attributes that have `is_sugared_doc` = true
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Attribute {
    pub style: AttrStyle,

    /// The path of the attribute.
    ///
    /// E.g. `derive` in `#[derive(Copy)]`
    /// E.g. `crate::precondition` in `#[crate::precondition x < 5]`
    pub path: Path,

    /// Any tokens after the path.
    ///
    /// E.g. `( Copy )` in `#[derive(Copy)]`
    /// E.g. `x < 5` in `#[crate::precondition x < 5]`
    pub tts: Vec<TokenTree>,

    pub is_sugared_doc: bool,
}

impl Attribute {
    /// Parses the tokens after the path as a [`MetaItem`](enum.MetaItem.html) if possible.
    pub fn meta_item(&self) -> Option<MetaItem> {
        if self.tts.is_empty() {
            return Some(MetaItem::Word);
        }

        if self.tts.len() == 1 {
            if let TokenTree::Delimited(Delimited { delim: DelimToken::Paren, ref tts }) = self.tts[0] {
                fn nested_meta_item_from_tokens(tts: &[TokenTree]) -> Option<(NestedMetaItem, &[TokenTree])> {
                    assert!(!tts.is_empty());

                    match tts[0] {
                        TokenTree::Token(Token::Literal(ref lit)) => {
                            Some((NestedMetaItem::Literal(lit.clone()), &tts[1..]))
                        }

                        TokenTree::Token(Token::Ident(ref ident)) => {
                            if tts.len() >= 3 {
                                match (&tts[1], &tts[2]) {
                                    (&TokenTree::Token(Token::Eq), &TokenTree::Token(Token::Literal(ref lit))) => {
                                        return Some((NestedMetaItem::MetaItem(ident.clone(), MetaItem::NameValue(lit.clone())), &tts[3..]));
                                    }

                                    _ => {}
                                }
                            }

                            if tts.len() >= 2 {
                                if let TokenTree::Delimited(Delimited { delim: DelimToken::Paren, tts: ref inner_tts }) = tts[1] {
                                    return match list_of_nested_meta_items_from_tokens(vec![], inner_tts) {
                                        Some(nested_meta_items) => {
                                            Some((NestedMetaItem::MetaItem(ident.clone(), MetaItem::List(nested_meta_items)), &tts[2..]))
                                        }

                                        None => None
                                    };
                                }
                            }

                            Some((NestedMetaItem::MetaItem(ident.clone(), MetaItem::Word), &tts[1..]))
                        }

                        _ => None
                    }
                }

                fn list_of_nested_meta_items_from_tokens(mut result: Vec<NestedMetaItem>, tts: &[TokenTree]) -> Option<Vec<NestedMetaItem>> {
                    if tts.is_empty() {
                        return Some(result);
                    }

                    match nested_meta_item_from_tokens(tts) {
                        Some((nested_meta_item, rest)) => {
                            result.push(nested_meta_item);
                            if rest.is_empty() {
                                list_of_nested_meta_items_from_tokens(result, rest)
                            }
                            else if let TokenTree::Token(Token::Comma) = rest[0] {
                                list_of_nested_meta_items_from_tokens(result, &rest[1..])
                            }
                            else {
                                None
                            }
                        }

                        None => None
                    }
                }

                if let Some(nested_meta_items) = list_of_nested_meta_items_from_tokens(vec![], tts) {
                    return Some(MetaItem::List(nested_meta_items));
                }
            }
        }

        if self.tts.len() == 2 {
            match (&self.tts[0], &self.tts[1]) {
                (&TokenTree::Token(Token::Eq), &TokenTree::Token(Token::Literal(ref lit))) => {
                    return Some(MetaItem::NameValue(lit.clone()));
                }

                _ => {}
            }
        }

        None
    }
}

/// Distinguishes between Attributes that decorate items and Attributes that
/// are contained as statements within items. These two cases need to be
/// distinguished for pretty-printing.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum AttrStyle {
    /// Attribute of the form `#![...]`.
    Outer,

    /// Attribute of the form `#[...]`.
    Inner,
}

/// A compile-time attribute item.
///
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum MetaItem {
    /// Word meta item.
    ///
    /// E.g. `test` as in `#[test]`
    Word,

    /// List meta item.
    ///
    /// E.g. `derive(..)` as in `#[derive(..)]`
    List(Vec<NestedMetaItem>),

    /// Name-value meta item.
    ///
    /// E.g. `feature = "foo"` as in `#[feature = "foo"]`
    NameValue(Lit),
}

/// Possible values inside of compile-time attribute lists.
///
/// E.g. the '..' in `#[name(..)]`.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum NestedMetaItem {
    /// A full `MetaItem`.
    ///
    /// E.g. `Copy` in `#[derive(Copy)]` would be a `(Ident::from("Copy"), MetaItem::Word)`.
    MetaItem(Ident, MetaItem),

    /// A Rust literal.
    ///
    /// E.g. `"name"` in `#[rename("name")]`.
    Literal(Lit),
}

pub trait FilterAttrs<'a> {
    type Ret: Iterator<Item = &'a Attribute>;

    fn outer(self) -> Self::Ret;
    fn inner(self) -> Self::Ret;
}

impl<'a, T> FilterAttrs<'a> for T
    where T: IntoIterator<Item = &'a Attribute>
{
    type Ret = iter::Filter<T::IntoIter, fn(&&Attribute) -> bool>;

    fn outer(self) -> Self::Ret {
        fn is_outer(attr: &&Attribute) -> bool {
            attr.style == AttrStyle::Outer
        }
        self.into_iter().filter(is_outer)
    }

    fn inner(self) -> Self::Ret {
        fn is_inner(attr: &&Attribute) -> bool {
            attr.style == AttrStyle::Inner
        }
        self.into_iter().filter(is_inner)
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use lit::{Lit, StrStyle};
    use mac::{Token, TokenTree};
    use mac::parsing::token_trees;
    use synom::space::{block_comment, whitespace};
    use ty::parsing::path;

    #[cfg(feature = "full")]
    named!(pub inner_attr -> Attribute, alt!(
        do_parse!(
            punct!("#") >>
            punct!("!") >>
            path_and_tts: delimited!(
                punct!("["),
                tuple!(path, token_trees),
                punct!("]")
            ) >>
            ({
                let (path, tts) = path_and_tts;

                Attribute {
                    style: AttrStyle::Inner,
                    path: path,
                    tts: tts,
                    is_sugared_doc: false,
                }
            })
        )
        |
        do_parse!(
            punct!("//!") >>
            content: take_until!("\n") >>
            (Attribute {
                style: AttrStyle::Inner,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(format!("//!{}", content).into(), StrStyle::Cooked))),
                ],
                is_sugared_doc: true,
            })
        )
        |
        do_parse!(
            option!(whitespace) >>
            peek!(tag!("/*!")) >>
            com: block_comment >>
            (Attribute {
                style: AttrStyle::Inner,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(com.into(), StrStyle::Cooked))),
                ],
                is_sugared_doc: true,
            })
        )
    ));

    named!(pub outer_attr -> Attribute, alt!(
        do_parse!(
            punct!("#") >>
            path_and_tts: delimited!(
                punct!("["),
                tuple!(path, token_trees),
                punct!("]")
            ) >>
            ({
                let (path, tts) = path_and_tts;

                Attribute {
                    style: AttrStyle::Outer,
                    path: path,
                    tts: tts,
                    is_sugared_doc: false,
                }
            })
        )
        |
        do_parse!(
            punct!("///") >>
            not!(tag!("/")) >>
            content: take_until!("\n") >>
            (Attribute {
                style: AttrStyle::Outer,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(format!("///{}", content).into(), StrStyle::Cooked))),
                ],
                is_sugared_doc: true,
            })
        )
        |
        do_parse!(
            option!(whitespace) >>
            peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
            com: block_comment >>
            (Attribute {
                style: AttrStyle::Outer,
                path: "doc".into(),
                tts: vec![
                    TokenTree::Token(Token::Eq),
                    TokenTree::Token(Token::Literal(Lit::Str(com.into(), StrStyle::Cooked))),
                ],
                is_sugared_doc: true,
            })
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use lit::{Lit, StrStyle};
    use mac::{Token, TokenTree};
    use quote::{Tokens, ToTokens};
    use ty::Path;

    impl ToTokens for Attribute {
        fn to_tokens(&self, tokens: &mut Tokens) {
            // If this was a sugared doc, emit it in its original form instead of `#[doc = "..."]`
            match *self {
                Attribute {
                    style,
                    path: Path { global: false, ref segments },
                    ref tts,
                    is_sugared_doc: true,
                } if segments.len() == 1 &&
                     segments[0].ident == "doc" &&
                     segments[0].parameters.is_empty() &&
                     tts.len() == 2 =>
                {
                    match (&self.tts[0], &self.tts[1]) {
                        (&TokenTree::Token(Token::Eq),
                         &TokenTree::Token(Token::Literal(Lit::Str(ref value, StrStyle::Cooked)))) =>
                        {
                            match style {
                                AttrStyle::Inner if value.starts_with("//!") => {
                                    tokens.append(&format!("{}\n", value));
                                    return;
                                }
                                AttrStyle::Inner if value.starts_with("/*!") => {
                                    tokens.append(value);
                                    return;
                                }
                                AttrStyle::Outer if value.starts_with("///") => {
                                    tokens.append(&format!("{}\n", value));
                                    return;
                                }
                                AttrStyle::Outer if value.starts_with("/**") => {
                                    tokens.append(value);
                                    return;
                                }
                                _ => {}
                            }
                        }

                        _ => {}
                    }
                }

                _ => {}
            }

            tokens.append("#");
            if let AttrStyle::Inner = self.style {
                tokens.append("!");
            }
            tokens.append("[");
            self.path.to_tokens(tokens);
            tokens.append_all(&self.tts);
            tokens.append("]");
        }
    }

    impl ToTokens for MetaItem {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                MetaItem::Word => {}
                MetaItem::List(ref inner) => {
                    tokens.append("(");
                    tokens.append_separated(inner, ",");
                    tokens.append(")");
                }
                MetaItem::NameValue(ref value) => {
                    tokens.append("=");
                    value.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for NestedMetaItem {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                NestedMetaItem::MetaItem(ref ident, ref nested) => {
                    ident.to_tokens(tokens);
                    nested.to_tokens(tokens);
                }
                NestedMetaItem::Literal(ref lit) => {
                    lit.to_tokens(tokens);
                }
            }
        }
    }
}
<|endoftext|>