<commit_before>//! This abstract syntax tree is *really* abstract.
//! By necessity, it's not tied to any specific language.
//! "Normal" language forms all correspond to `Node`, and their meaning comes from their `Form`.

#![macro_use]

use beta::{Beta, ExportBeta};
use name::*;
use std::{fmt, iter};
use util::mbe::EnvMBE;

// TODO: This really ought to be an `Rc` around an `enum`
#[derive(Clone, PartialEq)]
pub enum Ast {
    Trivial,
    /// Typically, a binder
    Atom(Name),
    VariableReference(Name),

    /// Shift environment to quote (a pos/neg piece of syntax) more
    QuoteMore(Box<Ast>, bool),
    /// Shift environment (by some amount) to quote less
    QuoteLess(Box<Ast>, u8),

    /// A meaningful chunk of syntax, governed by a form, containing an environment,
    ///  potentially exporting some names.
    Node(::std::rc::Rc<::form::Form>, EnvMBE<Ast>, ExportBeta),

    /// For parsing purposes.
    IncompleteNode(EnvMBE<Ast>),
    /// For parsing purposes. Is this used for anything other than writing simple tests?
    Shape(Vec<Ast>),

    /// Variable binding
    ExtendEnv(Box<Ast>, Beta),
}

// Reification macros would totally work for this,
//  but it's worth having a special case in `Value` in order to make this faster.
impl ::runtime::reify::Reifiable for Ast {
    fn ty_name() -> Name { n("Ast") }

    fn reify(&self) -> ::runtime::eval::Value {
        ::runtime::eval::Value::AbstractSyntax(self.clone())
    }

    fn reflect(v: &::runtime::eval::Value) -> Ast {
        extract!((v) ::runtime::eval::Value::AbstractSyntax = (ref ast) => (ast.clone()))
    }
}

pub use self::Ast::*;

impl fmt::Debug for Ast {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Trivial => write!(f, "⨉"),
            Atom(ref n) => write!(f, "∘{}∘", n.print()),
            VariableReference(ref v) => write!(f, "{}", v.print()),
            Shape(ref v) => {
                write!(f, "(")?;
                let mut first = true;
                for elt in v {
                    if !first {
                        write!(f, " ")?
                    }
                    elt.fmt(f)?;
                    first = false;
                }
                write!(f, ")")
            }
            Node(ref form, ref body, ref export) => {
                write!(f, "{{ ({}); {:#?}", form.name.sp(), body)?;
                match *export {
                    ::beta::ExportBeta::Nothing => {}
                    _ => write!(f, " ⇑{:#?}", export)?,
                }
                write!(f, "}}")
            }
            QuoteMore(ref body, pos) => {
                if pos {
                    write!(f, "pos``{:#?}``", body)
                } else {
                    write!(f, "neg``{:#?}``", body)
                }
            }
            QuoteLess(ref body, depth) => write!(f, ",,({}){:#?},,", depth, body),
            IncompleteNode(ref body) => write!(f, "{{ INCOMPLETE; {:#?} }}", body),
            ExtendEnv(ref body, ref beta) => write!(f, "{:#?}↓{:#?}", body, beta),
        }
    }
}

// Warning: this assumes the core language! To properly display an `Ast`, you need the `SynEnv`.
impl fmt::Display for Ast {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Atom(ref n) => write!(f, "{}", n.print()),
            VariableReference(ref v) => write!(f, "{}", v.print()),
            Node(ref form, ref body, _) => {
                let s = ::unparse::unparse_mbe(
                    &form.grammar,
                    self,
                    body,
                    &::core_forms::get_core_forms(),
                );
                write!(f, "{}", s)
            }
            ExtendEnv(ref body, _) => write!(f, "{}↓", body),
            _ => write!(f, "{:#?}", self),
        }
    }
}

impl Ast {
    // TODO: this ought to at least warn if we're losing anything other than `Shape`
    pub fn flatten(&self) -> EnvMBE<Ast> {
        match *self {
            Trivial | Atom(_) => EnvMBE::new(),
            VariableReference(_) => EnvMBE::new(),
            Shape(ref v) => {
                let mut accum = EnvMBE::new();
                for sub_a in v {
                    accum = accum.combine_overriding(&sub_a.flatten())
                }
                accum
            }
            IncompleteNode(ref env) => env.clone(),
            Node(ref _f, ref _body, ref _export) => {
                // TODO: think about what should happen when
                //  `Scope` contains a `Scope` without an intervening `Named`
                panic!("I don't know what to do here!")
            }
            QuoteMore(ref body, _) => body.flatten(),
            QuoteLess(ref body, _) => body.flatten(),
            ExtendEnv(ref body, _) => body.flatten(),
        }
    }

    // TODO: use this more
    pub fn destructure(
        &self,
        expd_form: ::std::rc::Rc<::form::Form>,
    ) -> Option<::util::mbe::EnvMBE<Ast>>
    {
        if let Node(ref f, ref parts, _) = self {
            if f == &expd_form {
                return Some(parts.clone());
            }
        }
        None
    }

    // TODO: I think we have a lot of places where we ought to use this function:
    pub fn node_parts(&self) -> &EnvMBE<Ast> {
        match *self {
            Node(_, ref body, _) => body,
            _ => icp!(),
        }
    }
    pub fn node_form(&self) -> &::form::Form {
        match *self {
            Node(ref form, _, _) => form,
            _ => icp!(),
        }
    }

    pub fn free_vrs(&self) -> Vec<Name> {
        match *self {
            Trivial | Atom(_) => vec![],
            VariableReference(v) => vec![v],
            Shape(_) | IncompleteNode(_) => unimplemented!("TODO"),
            QuoteLess(_, _) | QuoteMore(_, _) => unimplemented!("TODO"),
            // This one is actually encounterable by real-world code
            //  (if a ∀ somehow ends up underneath a `*` in syntax.)
            // And we need to take a LazyWalkReses to do this right.
            ExtendEnv(_, _) => unimplemented!("TODO"),
            Node(_, ref body, _) => body.map_reduce(
                &|a| a.free_vrs(),
                &|v0, v1| {
                    let mut res = v0.clone();
                    res.append(&mut v1.clone());
                    res
                },
                vec![],
            ),
        }
    }
}

// This is used by combine::many, which is used by the Star parser
impl iter::FromIterator<Ast> for Ast {
    fn from_iter<I: IntoIterator<Item = Ast>>(i: I) -> Self {
        IncompleteNode(EnvMBE::new_from_anon_repeat(i.into_iter().map(|a| a.flatten()).collect()))
    }
}

// This is also sort of a test of MBE, since we need `Ast`s to make them with the macros
//
// Suppose we have the following series of `Ast`s:
// [b = 8] [a = [1 2], b = 8] [a = [3 4 5], b = 8]
//
// We should turn them into the following `Ast`
// [a = [[] [1 2] [3 4 5]], b = [8 8 8]]
#[test]
fn combine_from_kleene_star() {
    use std::iter::FromIterator;

    let parse_parts = vec![
        ast!({ - "b" => "8.0"}),
        ast!({ - "a" => ["1", "2"], "b" => "8.1"}),
        ast!({ - "a" => ["1", "2", "3"], "b" => "8.2"}),
    ];
    let parsed = Ast::from_iter(parse_parts);

    let mut expected_mbe = mbe!("a" => [@"triple" [], ["1", "2"], ["1", "2", "3"]],
             "b" => [@"triple" "8.0", "8.1", "8.2"]);
    expected_mbe.anonimize_repeat(n("triple"));

    assert_eq!(parsed, IncompleteNode(expected_mbe));
}

#[test]
fn star_construction() {
    let env = mbe!( "a" => ["1", "2"]);

    assert_eq!(
        ast!( { - "x" => [* env =>("a") env : (, env.get_leaf_or_panic(&n("a")).clone())]} ),
        ast!( { - "x" => ["1", "2"] })
    );

    let env = mbe!( "a" => [@"duo" "1", "2"], "b" => [@"duo" "11", "22"]);

    assert_eq!(
        ast!( { - "x" => [* env =>("a", "b") env :
                            ((, env.get_leaf_or_panic(&n("b")).clone())
                             (, env.get_leaf_or_panic(&n("a")).clone()))]} ),
        ast!( { - "x" => [("11" "1"), ("22" "2")] })
    );
}

#[test]
fn mbe_r_and_r_roundtrip() {
    use runtime::reify::Reifiable;
    let mbe1 = mbe!( "a" => [@"duo" "1", "2"], "b" => [@"duo" "11", "22"]);
    assert_eq!(mbe1, EnvMBE::<Ast>::reflect(&mbe1.reify()));
}
<commit_msg>.Don't fallback to `Debug` when `Display`ing `Shape` ASTs/<commit_after>//! This abstract syntax tree is *really* abstract.
//! By necessity, it's not tied to any specific language.
//! "Normal" language forms all correspond to `Node`, and their meaning comes from their `Form`.

#![macro_use]

use beta::{Beta, ExportBeta};
use name::*;
use std::{fmt, iter};
use util::mbe::EnvMBE;

// TODO: This really ought to be an `Rc` around an `enum`
#[derive(Clone, PartialEq)]
pub enum Ast {
    Trivial,
    /// Typically, a binder
    Atom(Name),
    VariableReference(Name),

    /// Shift environment to quote (a pos/neg piece of syntax) more
    QuoteMore(Box<Ast>, bool),
    /// Shift environment (by some amount) to quote less
    QuoteLess(Box<Ast>, u8),

    /// A meaningful chunk of syntax, governed by a form, containing an environment,
    ///  potentially exporting some names.
    Node(::std::rc::Rc<::form::Form>, EnvMBE<Ast>, ExportBeta),

    /// For parsing purposes.
    IncompleteNode(EnvMBE<Ast>),
    /// For parsing purposes. Is this used for anything other than writing simple tests?
    Shape(Vec<Ast>),

    /// Variable binding
    ExtendEnv(Box<Ast>, Beta),
}

// Reification macros would totally work for this,
//  but it's worth having a special case in `Value` in order to make this faster.
impl ::runtime::reify::Reifiable for Ast {
    fn ty_name() -> Name { n("Ast") }

    fn reify(&self) -> ::runtime::eval::Value {
        ::runtime::eval::Value::AbstractSyntax(self.clone())
    }

    fn reflect(v: &::runtime::eval::Value) -> Ast {
        extract!((v) ::runtime::eval::Value::AbstractSyntax = (ref ast) => (ast.clone()))
    }
}

pub use self::Ast::*;

impl fmt::Debug for Ast {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Trivial => write!(f, "⨉"),
            Atom(ref n) => write!(f, "∘{}∘", n.print()),
            VariableReference(ref v) => write!(f, "{}", v.print()),
            Shape(ref v) => {
                write!(f, "(")?;
                let mut first = true;
                for elt in v {
                    if !first {
                        write!(f, " ")?
                    }
                    elt.fmt(f)?;
                    first = false;
                }
                write!(f, ")")
            }
            Node(ref form, ref body, ref export) => {
                write!(f, "{{ ({}); {:#?}", form.name.sp(), body)?;
                match *export {
                    ::beta::ExportBeta::Nothing => {}
                    _ => write!(f, " ⇑{:#?}", export)?,
                }
                write!(f, "}}")
            }
            QuoteMore(ref body, pos) => {
                if pos {
                    write!(f, "pos``{:#?}``", body)
                } else {
                    write!(f, "neg``{:#?}``", body)
                }
            }
            QuoteLess(ref body, depth) => write!(f, ",,({}){:#?},,", depth, body),
            IncompleteNode(ref body) => write!(f, "{{ INCOMPLETE; {:#?} }}", body),
            ExtendEnv(ref body, ref beta) => write!(f, "{:#?}↓{:#?}", body, beta),
        }
    }
}

// Warning: this assumes the core language! To properly display an `Ast`, you need the `SynEnv`.
impl fmt::Display for Ast {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Atom(ref n) => write!(f, "{}", n.print()),
            VariableReference(ref v) => write!(f, "{}", v.print()),
            Node(ref form, ref body, _) => {
                let s = ::unparse::unparse_mbe(
                    &form.grammar,
                    self,
                    body,
                    &::core_forms::get_core_forms(),
                );
                write!(f, "{}", s)
            }
            Shape(ref v) => {
                write!(f, "(")?;
                let mut first = true;
                for elt in v {
                    if !first {
                        write!(f, " ")?
                    }
                    elt.fmt(f)?;
                    first = false;
                }
                write!(f, ")")
            }
            ExtendEnv(ref body, _) => write!(f, "{}↓", body),
            _ => write!(f, "{:#?}", self),
        }
    }
}

impl Ast {
    // TODO: this ought to at least warn if we're losing anything other than `Shape`
    pub fn flatten(&self) -> EnvMBE<Ast> {
        match *self {
            Trivial | Atom(_) => EnvMBE::new(),
            VariableReference(_) => EnvMBE::new(),
            Shape(ref v) => {
                let mut accum = EnvMBE::new();
                for sub_a in v {
                    accum = accum.combine_overriding(&sub_a.flatten())
                }
                accum
            }
            IncompleteNode(ref env) => env.clone(),
            Node(ref _f, ref _body, ref _export) => {
                // TODO: think about what should happen when
                //  `Scope` contains a `Scope` without an intervening `Named`
                panic!("I don't know what to do here!")
            }
            QuoteMore(ref body, _) => body.flatten(),
            QuoteLess(ref body, _) => body.flatten(),
            ExtendEnv(ref body, _) => body.flatten(),
        }
    }

    // TODO: use this more
    pub fn destructure(
        &self,
        expd_form: ::std::rc::Rc<::form::Form>,
    ) -> Option<::util::mbe::EnvMBE<Ast>>
    {
        if let Node(ref f, ref parts, _) = self {
            if f == &expd_form {
                return Some(parts.clone());
            }
        }
        None
    }

    // TODO: I think we have a lot of places where we ought to use this function:
    pub fn node_parts(&self) -> &EnvMBE<Ast> {
        match *self {
            Node(_, ref body, _) => body,
            _ => icp!(),
        }
    }
    pub fn node_form(&self) -> &::form::Form {
        match *self {
            Node(ref form, _, _) => form,
            _ => icp!(),
        }
    }

    pub fn free_vrs(&self) -> Vec<Name> {
        match *self {
            Trivial | Atom(_) => vec![],
            VariableReference(v) => vec![v],
            Shape(_) | IncompleteNode(_) => unimplemented!("TODO"),
            QuoteLess(_, _) | QuoteMore(_, _) => unimplemented!("TODO"),
            // This one is actually encounterable by real-world code
            //  (if a ∀ somehow ends up underneath a `*` in syntax.)
            // And we need to take a LazyWalkReses to do this right.
            ExtendEnv(_, _) => unimplemented!("TODO"),
            Node(_, ref body, _) => body.map_reduce(
                &|a| a.free_vrs(),
                &|v0, v1| {
                    let mut res = v0.clone();
                    res.append(&mut v1.clone());
                    res
                },
                vec![],
            ),
        }
    }
}

// This is used by combine::many, which is used by the Star parser
impl iter::FromIterator<Ast> for Ast {
    fn from_iter<I: IntoIterator<Item = Ast>>(i: I) -> Self {
        IncompleteNode(EnvMBE::new_from_anon_repeat(i.into_iter().map(|a| a.flatten()).collect()))
    }
}

// This is also sort of a test of MBE, since we need `Ast`s to make them with the macros
//
// Suppose we have the following series of `Ast`s:
// [b = 8] [a = [1 2], b = 8] [a = [3 4 5], b = 8]
//
// We should turn them into the following `Ast`
// [a = [[] [1 2] [3 4 5]], b = [8 8 8]]
#[test]
fn combine_from_kleene_star() {
    use std::iter::FromIterator;

    let parse_parts = vec![
        ast!({ - "b" => "8.0"}),
        ast!({ - "a" => ["1", "2"], "b" => "8.1"}),
        ast!({ - "a" => ["1", "2", "3"], "b" => "8.2"}),
    ];
    let parsed = Ast::from_iter(parse_parts);

    let mut expected_mbe = mbe!("a" => [@"triple" [], ["1", "2"], ["1", "2", "3"]],
             "b" => [@"triple" "8.0", "8.1", "8.2"]);
    expected_mbe.anonimize_repeat(n("triple"));

    assert_eq!(parsed, IncompleteNode(expected_mbe));
}

#[test]
fn star_construction() {
    let env = mbe!( "a" => ["1", "2"]);

    assert_eq!(
        ast!( { - "x" => [* env =>("a") env : (, env.get_leaf_or_panic(&n("a")).clone())]} ),
        ast!( { - "x" => ["1", "2"] })
    );

    let env = mbe!( "a" => [@"duo" "1", "2"], "b" => [@"duo" "11", "22"]);

    assert_eq!(
        ast!( { - "x" => [* env =>("a", "b") env :
                            ((, env.get_leaf_or_panic(&n("b")).clone())
                             (, env.get_leaf_or_panic(&n("a")).clone()))]} ),
        ast!( { - "x" => [("11" "1"), ("22" "2")] })
    );
}

#[test]
fn mbe_r_and_r_roundtrip() {
    use runtime::reify::Reifiable;
    let mbe1 = mbe!( "a" => [@"duo" "1", "2"], "b" => [@"duo" "11", "22"]);
    assert_eq!(mbe1, EnvMBE::<Ast>::reflect(&mbe1.reify()));
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use super::Element;
use super::ElementContent;
use super::parser::SimpleContent;
use super::parser::EventsHandler;
use super::parser::Event;

#[cfg(test)] mod test;

#[derive(Default)]
pub struct Builder {
    ce : Vec<Rc<Element>>, // finished elements
    nb : Option<Box<RefCell<Builder>>>,
    cc : Option<ElementContent>,
    cid : u64,
    in_middle : bool,
}

impl Builder {
    pub fn captured_elements(&self) -> &Vec<Rc<Element>> {
        &self.ce
    }
}

impl EventsHandler for Builder {
    fn event(&mut self, e : Event) {
        use super::parser::Event::*;

        if let Some(nb) = self.nb.take() {
            let terminated = match &e {
                &End(_) if !nb.borrow().in_middle => true,
                _ => false,
            };
            if terminated {
                self.cc = Some(ElementContent::Master(nb.borrow_mut().ce.clone()));
            } else {
                nb.borrow_mut().event(e);
                self.nb = Some(nb);
                return;
            }
        }
        match e {
            Begin(x)    => {
                self.in_middle = true;
                self.cid = x.id;

                let cl = super::database::id_to_class(x.id);
                let typ = super::database::class_to_type(cl);

                if typ == super::Type::Master {
                    assert!(self.nb.is_none());
                    self.nb = Some ( Box::new( RefCell::new(Default::default()) ) );
                };
            },
            Data(ref x) => {
                self.cc = Some(match (*x) {
                    SimpleContent::Unsigned(x) => ElementContent::Unsigned(x),
                    SimpleContent::Signed(x) => ElementContent::Signed(x),
                    SimpleContent::Text(x) => ElementContent::Text(Rc::new(x.to_string())),
                    SimpleContent::Binary(x) => ElementContent::Binary(Rc::new(x.to_vec())),
                    SimpleContent::Float(x) => ElementContent::Float(x),
                    SimpleContent::MatroskaDate(x) => ElementContent::MatroskaDate(x),
                });
            },
            End(x)      => {
                let cl = super::database::id_to_class(self.cid);
                let elc = self.cc.take().unwrap();
                let el = Element {class: cl, content: elc};
                self.ce.push(Rc::new(el));
                self.in_middle = false;
            },
            Resync      => warn!("Error in matroska file. DOM will be garbled."),
        };
    }
}
<commit_msg>into_captured_elements<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use super::Element;
use super::ElementContent;
use super::parser::SimpleContent;
use super::parser::EventsHandler;
use super::parser::Event;

#[cfg(test)] mod test;

#[derive(Default)]
pub struct Builder {
    ce : Vec<Rc<Element>>, // finished elements
    nb : Option<Box<RefCell<Builder>>>,
    cc : Option<ElementContent>,
    cid : u64,
    in_middle : bool,
}

impl Builder {
    pub fn captured_elements(&self) -> &Vec<Rc<Element>> {
        &self.ce
    }

    pub fn into_captured_elements(self) -> Vec<Rc<Element>> {
        self.ce
    }
}

impl EventsHandler for Builder {
    fn event(&mut self, e : Event) {
        use super::parser::Event::*;

        if let Some(nb) = self.nb.take() {
            let terminated = match &e {
                &End(_) if !nb.borrow().in_middle => true,
                _ => false,
            };
            if terminated {
                self.cc = Some(ElementContent::Master(nb.borrow_mut().ce.clone()));
            } else {
                nb.borrow_mut().event(e);
                self.nb = Some(nb);
                return;
            }
        }
        match e {
            Begin(x)    => {
                self.in_middle = true;
                self.cid = x.id;

                let cl = super::database::id_to_class(x.id);
                let typ = super::database::class_to_type(cl);

                if typ == super::Type::Master {
                    assert!(self.nb.is_none());
                    self.nb = Some ( Box::new( RefCell::new(Default::default()) ) );
                };
            },
            Data(ref x) => {
                self.cc = Some(match (*x) {
                    SimpleContent::Unsigned(x) => ElementContent::Unsigned(x),
                    SimpleContent::Signed(x) => ElementContent::Signed(x),
                    SimpleContent::Text(x) => ElementContent::Text(Rc::new(x.to_string())),
                    SimpleContent::Binary(x) => ElementContent::Binary(Rc::new(x.to_vec())),
                    SimpleContent::Float(x) => ElementContent::Float(x),
                    SimpleContent::MatroskaDate(x) => ElementContent::MatroskaDate(x),
                });
            },
            End(x)      => {
                let cl = super::database::id_to_class(self.cid);
                let elc = self.cc.take().unwrap();
                let el = Element {class: cl, content: elc};
                self.ce.push(Rc::new(el));
                self.in_middle = false;
            },
            Resync      => warn!("Error in matroska file. DOM will be garbled."),
        };
    }
}
<|endoftext|>


<commit_before>//! SpriteBatch type.

use context::Context;
use graphics;
use error;
use gfx;
use gfx::Factory;
use GameResult;
use super::pixelshader::BlendMode;

// Owning the given Image is inconvenient because we might want, say,
// the same Rc<Image> shared among many SpriteBatch'es.
//
// But draw() doesn't handle that particularly well...
//
// The right way to fix this might be to have another object that implements
// Drawable that is created from a SpriteBatch and an image reference.
// BoundSpriteBatch or something.  That *feels* like the right way to go...
//
// Or just not implement Drawable and provide your own drawing functions, though
// that's squirrelly.
//
// Oh, or maybe make it take a Cow<Image> ?  that might work.
//
// For now though, let's mess around with the gfx bits rather than the ggez bits.
// We need to be able to, essentially, have an array of RectProperties.

/// A SpriteBatch draws a number of copies of the same image, using a single draw call.
#[derive(Debug)]
pub struct SpriteBatch {
    image: graphics::Image,
    sprites: Vec<graphics::InstanceProperties>,
    blend_mode: Option<BlendMode>,
}

/// An index of a particular sprite in a SpriteBatch.
pub type SpriteIdx = usize;

impl SpriteBatch {
    /// Creates a new `SpriteBatch`, drawing with the given image.
    pub fn new(image: graphics::Image) -> Self {
        Self {
            image: image,
            sprites: vec![],
            blend_mode: None,
        }
    }

    /// Adds a new sprite to the sprite batch.
    ///
    /// Returns a handle with which to modify the sprite using `set()`
    pub fn add(&mut self, param: graphics::DrawParam) -> SpriteIdx {
        let src_width = param.src.w;
        let src_height = param.src.h;
        // We have to mess with the scale to make everything
        // be its-unit-size-in-pixels.
        // We also invert the Y scale if our screen coordinates
        // are "upside down", because by default we present the
        // illusion that the screen is addressed in pixels.
        // BUGGO: Which I rather regret now.
        // let invert_y = if gfx.screen_rect.h < 0.0 { 1.0 } else { -1.0 };
        // TODO: Figure out whether implementing this is needed/how to do it cleanly
        let real_scale = graphics::Point2::new(src_width * param.scale.x * self.image.width as f32,
                                               src_height * param.scale.y *
                                               self.image.height as f32);
        let mut new_param = param;
        new_param.scale = real_scale;
        // Not entirely sure why the inversion is necessary, but oh well.
        new_param.offset.x *= -1.0 * param.scale.x;
        new_param.offset.y *= param.scale.y;
        self.sprites.push(new_param.into());
        self.sprites.len() - 1
    }

    /// Alters a sprite in the batch to use the given draw params
    pub fn set(&mut self, handle: SpriteIdx, param: graphics::DrawParam) -> GameResult<()> {
        if handle < self.sprites.len() - 1 {
            self.sprites[handle] = param.into();
            Ok(())
        } else {
            Err(error::GameError::RenderError(String::from("Provided index is out of bounds.")))
        }
    }

    /// Immediately sends all data in the batch to the graphics card.
    ///
    /// Generally just calling `graphics::draw()` on the `SpriteBatch`
    /// will do this automatically.
    pub fn flush(&self, ctx: &mut Context) -> GameResult<()> {
        let gfx = &mut ctx.gfx_context;
        if gfx.data.rect_instance_properties.len() < self.sprites.len() {
            gfx.data.rect_instance_properties = gfx.factory
                .create_buffer(self.sprites.len(),
                               gfx::buffer::Role::Vertex,
                               gfx::memory::Usage::Dynamic,
                               gfx::TRANSFER_DST)?;
        }
        gfx.encoder
            .update_buffer(&gfx.data.rect_instance_properties, &self.sprites[..], 0)?;
        Ok(())
    }

    /// Removes all data from the sprite batch.
    pub fn clear(&mut self) {
        self.sprites.clear();
    }

    /// Unwraps the contained `Image`
    pub fn into_inner(self) -> graphics::Image {
        self.image
    }

    /// Replaces the contained `Image`, returning the old one.
    pub fn set_image(&mut self, image: graphics::Image) -> graphics::Image {
        use std::mem;
        mem::replace(&mut self.image, image)
    }
}

impl graphics::Drawable for SpriteBatch {
    /// Does not properly work yet, ideally the position, scale, etc. of the given
    /// DrawParam would be added to the DrawParam for each sprite.
    fn draw_ex(&self, ctx: &mut Context, param: graphics::DrawParam) -> GameResult<()> {
        self.flush(ctx)?;
        let gfx = &mut ctx.gfx_context;
        let sampler = gfx.samplers
            .get_or_insert(self.image.sampler_info, gfx.factory.as_mut());
        gfx.data.vbuf = gfx.quad_vertex_buffer.clone();
        gfx.data.tex = (self.image.texture.clone(), sampler);
        let mut slice = gfx.quad_slice.clone();
        slice.instances = Some((self.sprites.len() as u32, 0));
        let curr_transform = gfx.get_transform();
        gfx.push_transform(param.into_matrix() * curr_transform);
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        let previous_mode: Option<BlendMode> = if let Some(mode) = self.blend_mode {
            let current_mode = gfx.get_blend_mode();
            if current_mode != mode {
                gfx.set_blend_mode(mode)?;
                Some(current_mode)
            } else {
                None
            }
        } else {
            None
        };
        gfx.draw(Some(&slice))?;
        if let Some(mode) = previous_mode {
            gfx.set_blend_mode(mode)?;
        }
        gfx.pop_transform();
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        Ok(())
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.blend_mode = mode;
    }
    fn get_blend_mode(&self) -> Option<BlendMode> {
        self.blend_mode
    }
}
<commit_msg>Fix bounds check in Spritebatch::set<commit_after>//! SpriteBatch type.

use context::Context;
use graphics;
use error;
use gfx;
use gfx::Factory;
use GameResult;
use super::pixelshader::BlendMode;

// Owning the given Image is inconvenient because we might want, say,
// the same Rc<Image> shared among many SpriteBatch'es.
//
// But draw() doesn't handle that particularly well...
//
// The right way to fix this might be to have another object that implements
// Drawable that is created from a SpriteBatch and an image reference.
// BoundSpriteBatch or something.  That *feels* like the right way to go...
//
// Or just not implement Drawable and provide your own drawing functions, though
// that's squirrelly.
//
// Oh, or maybe make it take a Cow<Image> ?  that might work.
//
// For now though, let's mess around with the gfx bits rather than the ggez bits.
// We need to be able to, essentially, have an array of RectProperties.

/// A SpriteBatch draws a number of copies of the same image, using a single draw call.
#[derive(Debug)]
pub struct SpriteBatch {
    image: graphics::Image,
    sprites: Vec<graphics::InstanceProperties>,
    blend_mode: Option<BlendMode>,
}

/// An index of a particular sprite in a SpriteBatch.
pub type SpriteIdx = usize;

impl SpriteBatch {
    /// Creates a new `SpriteBatch`, drawing with the given image.
    pub fn new(image: graphics::Image) -> Self {
        Self {
            image: image,
            sprites: vec![],
            blend_mode: None,
        }
    }

    /// Adds a new sprite to the sprite batch.
    ///
    /// Returns a handle with which to modify the sprite using `set()`
    pub fn add(&mut self, param: graphics::DrawParam) -> SpriteIdx {
        let src_width = param.src.w;
        let src_height = param.src.h;
        // We have to mess with the scale to make everything
        // be its-unit-size-in-pixels.
        // We also invert the Y scale if our screen coordinates
        // are "upside down", because by default we present the
        // illusion that the screen is addressed in pixels.
        // BUGGO: Which I rather regret now.
        // let invert_y = if gfx.screen_rect.h < 0.0 { 1.0 } else { -1.0 };
        // TODO: Figure out whether implementing this is needed/how to do it cleanly
        let real_scale = graphics::Point2::new(src_width * param.scale.x * self.image.width as f32,
                                               src_height * param.scale.y *
                                               self.image.height as f32);
        let mut new_param = param;
        new_param.scale = real_scale;
        // Not entirely sure why the inversion is necessary, but oh well.
        new_param.offset.x *= -1.0 * param.scale.x;
        new_param.offset.y *= param.scale.y;
        self.sprites.push(new_param.into());
        self.sprites.len() - 1
    }

    /// Alters a sprite in the batch to use the given draw params
    pub fn set(&mut self, handle: SpriteIdx, param: graphics::DrawParam) -> GameResult<()> {
        if handle < self.sprites.len() {
            self.sprites[handle] = param.into();
            Ok(())
        } else {
            Err(error::GameError::RenderError(String::from("Provided index is out of bounds.")))
        }
    }

    /// Immediately sends all data in the batch to the graphics card.
    ///
    /// Generally just calling `graphics::draw()` on the `SpriteBatch`
    /// will do this automatically.
    pub fn flush(&self, ctx: &mut Context) -> GameResult<()> {
        let gfx = &mut ctx.gfx_context;
        if gfx.data.rect_instance_properties.len() < self.sprites.len() {
            gfx.data.rect_instance_properties = gfx.factory
                .create_buffer(self.sprites.len(),
                               gfx::buffer::Role::Vertex,
                               gfx::memory::Usage::Dynamic,
                               gfx::TRANSFER_DST)?;
        }
        gfx.encoder
            .update_buffer(&gfx.data.rect_instance_properties, &self.sprites[..], 0)?;
        Ok(())
    }

    /// Removes all data from the sprite batch.
    pub fn clear(&mut self) {
        self.sprites.clear();
    }

    /// Unwraps the contained `Image`
    pub fn into_inner(self) -> graphics::Image {
        self.image
    }

    /// Replaces the contained `Image`, returning the old one.
    pub fn set_image(&mut self, image: graphics::Image) -> graphics::Image {
        use std::mem;
        mem::replace(&mut self.image, image)
    }
}

impl graphics::Drawable for SpriteBatch {
    /// Does not properly work yet, ideally the position, scale, etc. of the given
    /// DrawParam would be added to the DrawParam for each sprite.
    fn draw_ex(&self, ctx: &mut Context, param: graphics::DrawParam) -> GameResult<()> {
        self.flush(ctx)?;
        let gfx = &mut ctx.gfx_context;
        let sampler = gfx.samplers
            .get_or_insert(self.image.sampler_info, gfx.factory.as_mut());
        gfx.data.vbuf = gfx.quad_vertex_buffer.clone();
        gfx.data.tex = (self.image.texture.clone(), sampler);
        let mut slice = gfx.quad_slice.clone();
        slice.instances = Some((self.sprites.len() as u32, 0));
        let curr_transform = gfx.get_transform();
        gfx.push_transform(param.into_matrix() * curr_transform);
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        let previous_mode: Option<BlendMode> = if let Some(mode) = self.blend_mode {
            let current_mode = gfx.get_blend_mode();
            if current_mode != mode {
                gfx.set_blend_mode(mode)?;
                Some(current_mode)
            } else {
                None
            }
        } else {
            None
        };
        gfx.draw(Some(&slice))?;
        if let Some(mode) = previous_mode {
            gfx.set_blend_mode(mode)?;
        }
        gfx.pop_transform();
        gfx.calculate_transform_matrix();
        gfx.update_globals()?;
        Ok(())
    }
    fn set_blend_mode(&mut self, mode: Option<BlendMode>) {
        self.blend_mode = mode;
    }
    fn get_blend_mode(&self) -> Option<BlendMode> {
        self.blend_mode
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Greatest_element_of_a_list

#![cfg(not_tested)]
fn main()
{
	//greater element of a list main
	let list1 = vec!(1,2,3,4,5,6,7,8,9);
	println!("Max of first list {}", list1.iter().max_by(|x|{*x}).unwrap());

	let list2 = vec!(123,3543,23,432,5,2,34,234,234,2,4,234,23,4,24,25,7,658,68);
	println!("Max of the second list {}", list2.iter().max_by(|x|{*x}).unwrap());

	let list3 = vec!('a','b','c','d','e');
	println!("Max of Third list {}", list3.iter().max_by(|x|{*x}).unwrap());

	let list4 = vec!("Bonjour","Hola","Hello","Hallo","Bongiorno");
	println!("Max of Forth list {}", list4.iter().max_by(|x|{*x}).unwrap());
}
<commit_msg>Fix closure braces<commit_after>// http://rosettacode.org/wiki/Greatest_element_of_a_list

#![cfg(not_tested)]
fn main()
{
	//greater element of a list main
	let list1 = vec!(1,2,3,4,5,6,7,8,9);
	println!("Max of first list {}", list1.iter().max_by(|x| *x ).unwrap());

	let list2 = vec!(123,3543,23,432,5,2,34,234,234,2,4,234,23,4,24,25,7,658,68);
	println!("Max of the second list {}", list2.iter().max_by(|x| *x ).unwrap());

	let list3 = vec!('a','b','c','d','e');
	println!("Max of Third list {}", list3.iter().max_by(|x| *x ).unwrap());

	let list4 = vec!("Bonjour","Hola","Hello","Hallo","Bongiorno");
	println!("Max of Forth list {}", list4.iter().max_by(|x| *x ).unwrap());
}
<|endoftext|>


<commit_before>use std::iter;
use std::collections::vec_deque::VecDeque;
use player::Player;
use cell::Cell;

struct DfaState {
    empty: i32,
    red: i32,
    black: i32,
    bad: i32,
    pattern: i32
}

struct Dfa {
    states: Vec<DfaState>
}

impl Dfa {
    pub fn product(&self, other: &Dfa) -> Dfa {
        let other_len = other.states.len();
        let other_len_i32 = other_len as i32;
        let mut new_states = Vec::with_capacity(self.states.len() * other_len);
        for self_state in &self.states {
            let base_empty = (self_state.empty + 1) * other_len_i32;
            let base_red = (self_state.red + 1) * other_len_i32;
            let base_black = (self_state.black + 1) * other_len_i32;
            let base_bad = (self_state.bad + 1) * other_len_i32;
            for other_state in &other.states {
                let new_state = DfaState {
                    empty: base_empty + other_state.empty,
                    red: base_red + other_state.red,
                    black: base_black + other_state.black,
                    bad: base_bad + other_state.bad,
                    pattern: if self_state.pattern != -1 { self_state.pattern } else { other_state.pattern }
                };
                new_states.push(new_state);
            }
        }
        Dfa {
            states: new_states
        }
    }

    pub fn run(&self, iter: &mut Iterator<Item = Cell>) -> Option<u32> {
        let mut state_idx = 0i32;
        loop {
            let state = &self.states[state_idx as usize];
            if state.pattern != -1 {
                return Some(state.pattern as u32);
            }
            if let Some(cell) = iter.next() {
                if cell.is_bad() {
                    state_idx = state.bad;
                } else if let Some(player) = cell.get_owner() {
                    match player {
                        Player::Red => state_idx = state.red,
                        Player::Black => state_idx = state.black
                    }
                } else {
                    state_idx = state.empty;
                }
            } else {
                return None;
            }
            if state_idx == -1 {
                return None;
            }
        }
    }

    pub fn delete_non_reachable(&mut self) {
        let mut reachable = iter::repeat(0).take(self.states.len()).collect::<Vec<u32>>();
        let mut q = VecDeque::with_capacity(self.states.len());
        q.push_back(1);
        while let Some(idx) = q.pop_front() {
            let state = &self.states[idx as usize];
            if state.empty != -1 && reachable[state.empty as usize] == 0 {
                reachable[state.empty as usize] = 1;
                q.push_back(state.empty);
            }
            if state.red != -1 && reachable[state.red as usize] == 0 {
                reachable[state.red as usize] = 1;
                q.push_back(state.red);
            }
            if state.black != -1 && reachable[state.black as usize] == 0 {
                reachable[state.black as usize] = 1;
                q.push_back(state.black);
            }
            if state.bad != -1 && reachable[state.bad as usize] == 0 {
                reachable[state.bad as usize] = 1;
                q.push_back(state.bad);
            }
        }
        let mut shifts = Vec::with_capacity(self.states.len());
        for r in &reachable {
            let shift = shifts.last().map_or(0, |&d| d) + 1 - r;
            shifts.push(shift);
        }
        let deletions = shifts.last().map_or(0, |&d| d);
        if deletions == 0 {
            return;
        }
        let mut new_states = Vec::with_capacity(self.states.len() - deletions as usize);
        for state in self.states.iter().zip(reachable.into_iter()).filter_map(|(state, r)| if r == 1 { Some(state) } else { None }) {
            let new_state = DfaState {
                empty: if state.empty == -1 { -1 } else { state.empty - shifts[state.empty as usize] as i32 },
                red: if state.red == -1 { -1 } else { state.red - shifts[state.red as usize] as i32 },
                black: if state.black == -1 { -1 } else { state.black - shifts[state.black as usize] as i32 },
                bad: if state.bad == -1 { -1 } else { state.bad - shifts[state.bad as usize] as i32 },
                pattern: state.pattern
            };
            new_states.push(new_state);
        }
        self.states = new_states;
    }
}
<commit_msg>Minimization draft.<commit_after>use std::iter;
use std::collections::vec_deque::VecDeque;
use player::Player;
use cell::Cell;

struct DfaState {
    empty: i32,
    red: i32,
    black: i32,
    bad: i32,
    pattern: i32
}

struct Dfa {
    states: Vec<DfaState>
}

impl Dfa {
    pub fn product(&self, other: &Dfa) -> Dfa {
        let other_len = other.states.len();
        let other_len_i32 = other_len as i32;
        let mut new_states = Vec::with_capacity(self.states.len() * other_len);
        for self_state in &self.states {
            let base_empty = (self_state.empty + 1) * other_len_i32;
            let base_red = (self_state.red + 1) * other_len_i32;
            let base_black = (self_state.black + 1) * other_len_i32;
            let base_bad = (self_state.bad + 1) * other_len_i32;
            for other_state in &other.states {
                let new_state = DfaState {
                    empty: base_empty + other_state.empty,
                    red: base_red + other_state.red,
                    black: base_black + other_state.black,
                    bad: base_bad + other_state.bad,
                    pattern: if self_state.pattern != -1 { self_state.pattern } else { other_state.pattern }
                };
                new_states.push(new_state);
            }
        }
        Dfa {
            states: new_states
        }
    }

    pub fn run(&self, iter: &mut Iterator<Item = Cell>) -> Option<u32> {
        let mut state_idx = 0i32;
        loop {
            let state = &self.states[state_idx as usize];
            if state.pattern != -1 {
                return Some(state.pattern as u32);
            }
            if let Some(cell) = iter.next() {
                if cell.is_bad() {
                    state_idx = state.bad;
                } else if let Some(player) = cell.get_owner() {
                    match player {
                        Player::Red => state_idx = state.red,
                        Player::Black => state_idx = state.black
                    }
                } else {
                    state_idx = state.empty;
                }
            } else {
                return None;
            }
            if state_idx == -1 {
                return None;
            }
        }
    }

    pub fn delete_non_reachable(&mut self) {
        let mut reachable = iter::repeat(0).take(self.states.len()).collect::<Vec<u32>>();
        let mut q = VecDeque::with_capacity(self.states.len());
        q.push_back(1);
        while let Some(idx) = q.pop_front() {
            let state = &self.states[idx as usize];
            if state.empty != -1 && reachable[state.empty as usize] == 0 {
                reachable[state.empty as usize] = 1;
                q.push_back(state.empty);
            }
            if state.red != -1 && reachable[state.red as usize] == 0 {
                reachable[state.red as usize] = 1;
                q.push_back(state.red);
            }
            if state.black != -1 && reachable[state.black as usize] == 0 {
                reachable[state.black as usize] = 1;
                q.push_back(state.black);
            }
            if state.bad != -1 && reachable[state.bad as usize] == 0 {
                reachable[state.bad as usize] = 1;
                q.push_back(state.bad);
            }
        }
        let mut shifts = Vec::with_capacity(self.states.len());
        for r in &reachable {
            let shift = shifts.last().map_or(0, |&d| d) + 1 - r;
            shifts.push(shift);
        }
        let deletions = shifts.last().map_or(0, |&d| d);
        if deletions == 0 {
            return;
        }
        let mut new_states = Vec::with_capacity(self.states.len() - deletions as usize);
        for state in self.states.iter().zip(reachable.into_iter()).filter_map(|(state, r)| if r == 1 { Some(state) } else { None }) {
            let new_state = DfaState {
                empty: if state.empty == -1 { -1 } else { state.empty - shifts[state.empty as usize] as i32 },
                red: if state.red == -1 { -1 } else { state.red - shifts[state.red as usize] as i32 },
                black: if state.black == -1 { -1 } else { state.black - shifts[state.black as usize] as i32 },
                bad: if state.bad == -1 { -1 } else { state.bad - shifts[state.bad as usize] as i32 },
                pattern: state.pattern
            };
            new_states.push(new_state);
        }
        self.states = new_states;
    }

    fn pyramid_idx_base(i: usize) -> usize {
        i * (i - 1) / 2
    }

    fn pyramid_idx(i: usize, j: usize) -> usize {
        Dfa::pyramid_idx_base(i) + j
    }

    pub fn minimize(&mut self) {
        let len = self.states.len();
        let mut not_equal = iter::repeat(0).take(len * (len - 1) / 2 + len - 1).collect::<Vec<u32>>();
        for (i, pattern_i) in self.states.iter().enumerate().skip(1) {
            let base = Dfa::pyramid_idx_base(i);
            for (j, pattern_j) in self.states[.. i - 1].iter().enumerate() {
                if pattern_i.pattern != pattern_j.pattern {
                    not_equal[base + j] = 1;
                }
            }
        }
        'outer: loop {
            for (i, pattern_i) in self.states.iter().enumerate().skip(1) {
                let base = Dfa::pyramid_idx_base(i);
                for (j, pattern_j) in self.states[.. i - 1].iter().enumerate() {
                    let idx = base + j;
                    if not_equal[idx] == 0 {
                        if pattern_i.empty != pattern_j.empty && (pattern_i.empty == -1 || pattern_j.empty == -1 || not_equal[Dfa::pyramid_idx(pattern_i.empty as usize, pattern_j.empty as usize)] == 1) ||
                            pattern_i.red != pattern_j.red && (pattern_i.red == -1 || pattern_j.red == -1 || not_equal[Dfa::pyramid_idx(pattern_i.red as usize, pattern_j.red as usize)] == 1) {
                            not_equal[idx] = 1;
                            continue 'outer;
                        }
                    }
                }
            }
            break;
        }
    }
}
<|endoftext|>


<commit_before>//! Simple graphviz dot file format output.

use std::fmt::{self, Display, Write};
use prelude::*;
use {
    EdgeType,
};
use super::graph::IndexType;
use graphmap::NodeTrait;
use std::collections::HashMap;

/// `Dot` implements output to graphviz .dot format for a graph.
///
/// Formatting and options are rather simple, this is mostly intended
/// for debugging. Exact output may change.
pub struct Dot<'a, G: 'a> {
    graph: &'a G,
    config: &'a [Config],
}

static TYPE: [&'static str; 2] = ["graph", "digraph"];
static EDGE: [&'static str; 2] = ["--", "->"];
static INDENT: &'static str = "    ";

impl<'a, G> Dot<'a, G> {
    /// Create a `Dot` formatting wrapper with default configuration.
    pub fn new(graph: &'a G) -> Self {
        Self::with_config(graph, &[])
    }

    /// Create a `Dot` formatting wrapper with custom configuration.
    pub fn with_config(graph: &'a G, config: &'a [Config]) -> Self {
        Dot {
            graph: graph,
            config: config,
        }
    }
}

/// `Dot` configuration.
///
/// This enum does not have an exhaustive definition (will be expanded)
#[derive(Debug, PartialEq, Eq)]
pub enum Config {
    /// Use indices for node labels.
    NodeIndexLabel,
    /// Use indices for edge labels.
    EdgeIndexLabel,
    /// Use no edge labels.
    EdgeNoLabel,
    #[doc(hidden)]
    _Incomplete(()),
}

impl<'a, N, E, Ty, Ix> Dot<'a, Graph<N, E, Ty, Ix>>
    where Ty: EdgeType,
          Ix: IndexType,
{
    fn graph_fmt<F, G>(&self, f: &mut fmt::Formatter,
                       mut node_fmt: F, mut edge_fmt: G) -> fmt::Result
        where F: FnMut(&N, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
              G: FnMut(&E, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
{
        let g = self.graph;
        try!(writeln!(f, "{} {{", TYPE[g.is_directed() as usize]));

        // output all labels
        for index in g.node_indices() {
            try!(write!(f, "{}{}", INDENT, index.index()));
            if self.config.contains(&Config::NodeIndexLabel) {
                try!(writeln!(f, ""));
            } else {
                try!(write!(f, " [label=\""));
                try!(node_fmt(&g[index], &mut |d| Escaped(d).fmt(f)));
                try!(writeln!(f, "\"]"));
            }

        }
        // output all edges
        for (i, edge) in g.raw_edges().iter().enumerate() {
            try!(write!(f, "{}{} {} {}",
                        INDENT,
                        edge.source().index(),
                        EDGE[g.is_directed() as usize],
                        edge.target().index()));
            if self.config.contains(&Config::EdgeNoLabel) {
                try!(writeln!(f, ""));
            } else if self.config.contains(&Config::EdgeIndexLabel) {
                try!(writeln!(f, " [label=\"{}\"]", i));
            } else {
                try!(write!(f, " [label=\""));
                try!(edge_fmt(&edge.weight, &mut |d| Escaped(d).fmt(f)));
                try!(writeln!(f, "\"]"));
            }
        }

        try!(writeln!(f, "}}"));
        Ok(())
    }
}

impl<'a, N, E, Ty, Ix> fmt::Display for Dot<'a, Graph<N, E, Ty, Ix>>
    where N: fmt::Display,
          E: fmt::Display,
          Ty: EdgeType,
          Ix: IndexType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graph_fmt(f, |n, cb| cb(n), |e, cb| cb(e))
    }
}

impl<'a, N, E, Ty, Ix> fmt::Debug for Dot<'a, Graph<N, E, Ty, Ix>>
    where N: fmt::Debug,
          E: fmt::Debug,
          Ty: EdgeType,
          Ix: IndexType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graph_fmt(f,
                       |n, cb| cb(&DebugFmt(n)),
                       |e, cb| cb(&DebugFmt(e)))
    }
}

impl<'a, N, E, Ty> Dot<'a, GraphMap<N, E, Ty>>
    where N: NodeTrait,
          Ty: EdgeType,
{
    fn graphmap_fmt<F, G>(&self, f: &mut fmt::Formatter,
                          mut node_fmt: F, mut edge_fmt: G) -> fmt::Result
        where F: FnMut(&N, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
              G: FnMut(&E, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
    {
        let g = self.graph;
        let is_directed = g.is_directed() as usize;
        try!(writeln!(f, "{} {{", TYPE[is_directed]));

        let mut labels = HashMap::new();

        // output all labels
        for (i, node) in g.nodes().enumerate() {
            labels.insert(node, i);
            try!(write!(f, "{}{}", INDENT, i));
            if self.config.contains(&Config::NodeIndexLabel) {
                try!(writeln!(f, ""));
            } else {
                try!(write!(f, " [label=\""));
                try!(node_fmt(&node, &mut |d| Escaped(d).fmt(f)));
                try!(writeln!(f, "\"]"));
            }
        }
        // output all edges
        for (i, (a, b, edge_weight)) in g.all_edges().enumerate() {
            try!(write!(f, "{}{} {} {}",
                        INDENT,
                        labels[&a],
                        EDGE[is_directed],
                        labels[&b]));
            if self.config.contains(&Config::EdgeNoLabel) {
                try!(writeln!(f, ""));
            } else if self.config.contains(&Config::EdgeIndexLabel) {
                try!(writeln!(f, " [label=\"{}\"]", i));
            } else {
                try!(write!(f, " [label=\""));
                try!(edge_fmt(&edge_weight, &mut |d| Escaped(d).fmt(f)));
                try!(writeln!(f, "\"]"));
            }
        }

        try!(writeln!(f, "}}"));
        Ok(())
    }
}
impl<'a, N, E, Ty> fmt::Display for Dot<'a, GraphMap<N, E, Ty>>
    where N: fmt::Display + NodeTrait,
          E: fmt::Display,
          Ty: EdgeType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graphmap_fmt(f, |n, cb| cb(n), |e, cb| cb(e))
    }
}

impl<'a, N, E, Ty> fmt::Debug for Dot<'a, GraphMap<N, E, Ty>>
    where N: fmt::Debug + NodeTrait,
          E: fmt::Debug,
          Ty: EdgeType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graphmap_fmt(f,
                          |n, cb| cb(&DebugFmt(n)),
                          |e, cb| cb(&DebugFmt(e)))
    }
}

/// Escape for Graphviz
struct Escaper<W>(W);

impl<W> fmt::Write for Escaper<W>
    where W: fmt::Write
{
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for c in s.chars() {
            try!(self.write_char(c));
        }
        Ok(())
    }

    fn write_char(&mut self, c: char) -> fmt::Result {
        match c {
            '"' => try!(self.0.write_char('\\')),
            // \l is for left justified linebreak
            '\n' => return self.0.write_str(r#"\l"#),
            _   => { }
        }
        self.0.write_char(c)
    }
}

/// Pass Display formatting through a simple escaping filter
struct Escaped<T>(T);

impl<T> fmt::Display for Escaped<T>
    where T: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if f.alternate() {
            write!(&mut Escaper(f), "{:#}\\l", &self.0)
        } else {
            write!(&mut Escaper(f), "{}", &self.0)
        }
    }
}

/// Pass Debug formatting to Display
struct DebugFmt<T>(T);

impl<T> fmt::Display for DebugFmt<T>
    where T: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}
<commit_msg>Add example to Dot<commit_after>//! Simple graphviz dot file format output.

use std::fmt::{self, Display, Write};
use prelude::*;
use {
    EdgeType,
};
use super::graph::IndexType;
use graphmap::NodeTrait;
use std::collections::HashMap;

/// `Dot` implements output to graphviz .dot format for a graph.
///
/// Formatting and options are rather simple, this is mostly intended
/// for debugging. Exact output may change.
///
/// # Examples
///
/// ```
/// use petgraph::Graph;
/// use petgraph::dot::{Dot, Config};
///
/// let mut graph = Graph::<_, ()>::new();
/// graph.add_node("A");
/// graph.add_node("B");
/// graph.add_node("C");
/// graph.add_node("D");
/// graph.extend_with_edges(&[
///     (0, 1), (0, 2), (0, 3),
///     (1, 2), (1, 3),
///     (2, 3),
/// ]);
///
/// println!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel]));
///
/// // In this case the output looks like this:
/// //
/// // digraph {
/// //     0 [label="\"A\""]
/// //     1 [label="\"B\""]
/// //     2 [label="\"C\""]
/// //     3 [label="\"D\""]
/// //     0 -> 1
/// //     0 -> 2
/// //     0 -> 3
/// //     1 -> 2
/// //     1 -> 3
/// //     2 -> 3
/// // }
///
/// // If you need multiple config options, just list them all in the slice.
/// ```
pub struct Dot<'a, G: 'a> {
    graph: &'a G,
    config: &'a [Config],
}

static TYPE: [&'static str; 2] = ["graph", "digraph"];
static EDGE: [&'static str; 2] = ["--", "->"];
static INDENT: &'static str = "    ";

impl<'a, G> Dot<'a, G> {
    /// Create a `Dot` formatting wrapper with default configuration.
    pub fn new(graph: &'a G) -> Self {
        Self::with_config(graph, &[])
    }

    /// Create a `Dot` formatting wrapper with custom configuration.
    pub fn with_config(graph: &'a G, config: &'a [Config]) -> Self {
        Dot {
            graph: graph,
            config: config,
        }
    }
}

/// `Dot` configuration.
///
/// This enum does not have an exhaustive definition (will be expanded)
#[derive(Debug, PartialEq, Eq)]
pub enum Config {
    /// Use indices for node labels.
    NodeIndexLabel,
    /// Use indices for edge labels.
    EdgeIndexLabel,
    /// Use no edge labels.
    EdgeNoLabel,
    #[doc(hidden)]
    _Incomplete(()),
}

impl<'a, N, E, Ty, Ix> Dot<'a, Graph<N, E, Ty, Ix>>
    where Ty: EdgeType,
          Ix: IndexType,
{
    fn graph_fmt<F, G>(&self, f: &mut fmt::Formatter,
                       mut node_fmt: F, mut edge_fmt: G) -> fmt::Result
        where F: FnMut(&N, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
              G: FnMut(&E, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
{
        let g = self.graph;
        try!(writeln!(f, "{} {{", TYPE[g.is_directed() as usize]));

        // output all labels
        for index in g.node_indices() {
            try!(write!(f, "{}{}", INDENT, index.index()));
            if self.config.contains(&Config::NodeIndexLabel) {
                try!(writeln!(f, ""));
            } else {
                try!(write!(f, " [label=\""));
                try!(node_fmt(&g[index], &mut |d| Escaped(d).fmt(f)));
                try!(writeln!(f, "\"]"));
            }

        }
        // output all edges
        for (i, edge) in g.raw_edges().iter().enumerate() {
            try!(write!(f, "{}{} {} {}",
                        INDENT,
                        edge.source().index(),
                        EDGE[g.is_directed() as usize],
                        edge.target().index()));
            if self.config.contains(&Config::EdgeNoLabel) {
                try!(writeln!(f, ""));
            } else if self.config.contains(&Config::EdgeIndexLabel) {
                try!(writeln!(f, " [label=\"{}\"]", i));
            } else {
                try!(write!(f, " [label=\""));
                try!(edge_fmt(&edge.weight, &mut |d| Escaped(d).fmt(f)));
                try!(writeln!(f, "\"]"));
            }
        }

        try!(writeln!(f, "}}"));
        Ok(())
    }
}

impl<'a, N, E, Ty, Ix> fmt::Display for Dot<'a, Graph<N, E, Ty, Ix>>
    where N: fmt::Display,
          E: fmt::Display,
          Ty: EdgeType,
          Ix: IndexType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graph_fmt(f, |n, cb| cb(n), |e, cb| cb(e))
    }
}

impl<'a, N, E, Ty, Ix> fmt::Debug for Dot<'a, Graph<N, E, Ty, Ix>>
    where N: fmt::Debug,
          E: fmt::Debug,
          Ty: EdgeType,
          Ix: IndexType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graph_fmt(f,
                       |n, cb| cb(&DebugFmt(n)),
                       |e, cb| cb(&DebugFmt(e)))
    }
}

impl<'a, N, E, Ty> Dot<'a, GraphMap<N, E, Ty>>
    where N: NodeTrait,
          Ty: EdgeType,
{
    fn graphmap_fmt<F, G>(&self, f: &mut fmt::Formatter,
                          mut node_fmt: F, mut edge_fmt: G) -> fmt::Result
        where F: FnMut(&N, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
              G: FnMut(&E, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
    {
        let g = self.graph;
        let is_directed = g.is_directed() as usize;
        try!(writeln!(f, "{} {{", TYPE[is_directed]));

        let mut labels = HashMap::new();

        // output all labels
        for (i, node) in g.nodes().enumerate() {
            labels.insert(node, i);
            try!(write!(f, "{}{}", INDENT, i));
            if self.config.contains(&Config::NodeIndexLabel) {
                try!(writeln!(f, ""));
            } else {
                try!(write!(f, " [label=\""));
                try!(node_fmt(&node, &mut |d| Escaped(d).fmt(f)));
                try!(writeln!(f, "\"]"));
            }
        }
        // output all edges
        for (i, (a, b, edge_weight)) in g.all_edges().enumerate() {
            try!(write!(f, "{}{} {} {}",
                        INDENT,
                        labels[&a],
                        EDGE[is_directed],
                        labels[&b]));
            if self.config.contains(&Config::EdgeNoLabel) {
                try!(writeln!(f, ""));
            } else if self.config.contains(&Config::EdgeIndexLabel) {
                try!(writeln!(f, " [label=\"{}\"]", i));
            } else {
                try!(write!(f, " [label=\""));
                try!(edge_fmt(&edge_weight, &mut |d| Escaped(d).fmt(f)));
                try!(writeln!(f, "\"]"));
            }
        }

        try!(writeln!(f, "}}"));
        Ok(())
    }
}
impl<'a, N, E, Ty> fmt::Display for Dot<'a, GraphMap<N, E, Ty>>
    where N: fmt::Display + NodeTrait,
          E: fmt::Display,
          Ty: EdgeType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graphmap_fmt(f, |n, cb| cb(n), |e, cb| cb(e))
    }
}

impl<'a, N, E, Ty> fmt::Debug for Dot<'a, GraphMap<N, E, Ty>>
    where N: fmt::Debug + NodeTrait,
          E: fmt::Debug,
          Ty: EdgeType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graphmap_fmt(f,
                          |n, cb| cb(&DebugFmt(n)),
                          |e, cb| cb(&DebugFmt(e)))
    }
}

/// Escape for Graphviz
struct Escaper<W>(W);

impl<W> fmt::Write for Escaper<W>
    where W: fmt::Write
{
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for c in s.chars() {
            try!(self.write_char(c));
        }
        Ok(())
    }

    fn write_char(&mut self, c: char) -> fmt::Result {
        match c {
            '"' => try!(self.0.write_char('\\')),
            // \l is for left justified linebreak
            '\n' => return self.0.write_str(r#"\l"#),
            _   => { }
        }
        self.0.write_char(c)
    }
}

/// Pass Display formatting through a simple escaping filter
struct Escaped<T>(T);

impl<T> fmt::Display for Escaped<T>
    where T: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if f.alternate() {
            write!(&mut Escaper(f), "{:#}\\l", &self.0)
        } else {
            write!(&mut Escaper(f), "{}", &self.0)
        }
    }
}

/// Pass Debug formatting to Display
struct DebugFmt<T>(T);

impl<T> fmt::Display for DebugFmt<T>
    where T: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}
<|endoftext|>


<commit_before>/// Creates Rust structure for new Ruby class
///
/// # Examples
///
/// ```no_run
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{AnyObject, Class, RString, VM};
/// use ruru::types::{Argc, Value};
/// use ruru::traits::Object;
///
/// class!(Greeter);
///
/// methods!(
///     Greeter,
///     itself,
///
///     fn anonymous_greeting() -> RString {
///         RString::new("Hello stranger!")
///     }
///
///     fn friendly_greeting(name: RString) -> RString {
///         let greeting = format!("Hello dear {}!", name.to_string());
///
///         RString::new(&greeting)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("Greeter").define(|itself| {
///         itself.def("anonymous_greeting", anonymous_greeting);
///         itself.def("friendly_greeting", friendly_greeting);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class Greeter
///   def anonymous_greeting
///     'Hello stranger!'
///   end
///
///   def friendly_greeting(name)
///     "Hello dear #{name}"
///   end
/// end
/// ```
#[macro_export]
macro_rules! class {
    ($class: ident) => {
        pub struct $class {
            value: Value,
        }

        impl From<Value> for $class {
            fn from(value: Value) -> Self {
                $class { value: value }
            }
        }

        impl Object for $class {
            fn value(&self) -> Value {
                self.value
            }
        }
    }
}

/// Creates callbacks for Ruby methods
///
/// # Examples
///
/// ```no_run
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{AnyObject, Boolean, Class, Fixnum, RString, VM};
/// use ruru::types::Argc;
/// use ruru::traits::Object;
///
/// // Creates `string_is_blank` and `string_length_equals` functions
/// methods!(
///     RString, // type of `self` object
///     itself, // name of `self` object which will be used in methods
///
///     fn string_is_blank() -> Boolean {
///         Boolean::new(itself.to_string().chars().all(|c| c.is_whitespace()))
///     }
///
///     fn string_length_equals(expected_length: Fixnum) -> Boolean {
///         let real_length = itself.to_string().len() as i64;
///
///         Boolean::new(expected_length.to_i64() == real_length)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::from_existing("String").define(|itself| {
///         itself.def("blank?", string_is_blank);
///         itself.def("length_equals?", string_length_equals);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class String
///   def blank?
///     # ...
///   end
///
///   def length_equals?(expected_length)
///     # ...
///   end
/// end
/// ```
#[macro_export]
macro_rules! methods {
    (
        $itself_class: ty,
        $itself_name: ident,
        $(
            fn $method_name: ident
            ($($arg_name: ident: $arg_type: ty),*) -> $return_type: ident $body: block
        )*
    ) => {
        $(
            #[no_mangle]
            pub extern fn $method_name(argc: Argc,
                                       argv: *const AnyObject,
                                       mut $itself_name: $itself_class) -> $return_type {
                let arguments = VM::parse_arguments(argc, argv);
                let mut i = 0;

                $(
                    let $arg_name = arguments[i].to::<$arg_type>();
                    i += 1;
                )*

                $body
            }
        )*
    }
}
<commit_msg>Fix methods! macro warnings<commit_after>/// Creates Rust structure for new Ruby class
///
/// # Examples
///
/// ```no_run
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{AnyObject, Class, RString, VM};
/// use ruru::types::{Argc, Value};
/// use ruru::traits::Object;
///
/// class!(Greeter);
///
/// methods!(
///     Greeter,
///     itself,
///
///     fn anonymous_greeting() -> RString {
///         RString::new("Hello stranger!")
///     }
///
///     fn friendly_greeting(name: RString) -> RString {
///         let greeting = format!("Hello dear {}!", name.to_string());
///
///         RString::new(&greeting)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::new("Greeter").define(|itself| {
///         itself.def("anonymous_greeting", anonymous_greeting);
///         itself.def("friendly_greeting", friendly_greeting);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class Greeter
///   def anonymous_greeting
///     'Hello stranger!'
///   end
///
///   def friendly_greeting(name)
///     "Hello dear #{name}"
///   end
/// end
/// ```
#[macro_export]
macro_rules! class {
    ($class: ident) => {
        pub struct $class {
            value: Value,
        }

        impl From<Value> for $class {
            fn from(value: Value) -> Self {
                $class { value: value }
            }
        }

        impl Object for $class {
            fn value(&self) -> Value {
                self.value
            }
        }
    }
}

/// Creates callbacks for Ruby methods
///
/// # Examples
///
/// ```no_run
/// #[macro_use]
/// extern crate ruru;
///
/// use ruru::{AnyObject, Boolean, Class, Fixnum, RString, VM};
/// use ruru::types::Argc;
/// use ruru::traits::Object;
///
/// // Creates `string_is_blank` and `string_length_equals` functions
/// methods!(
///     RString, // type of `self` object
///     itself, // name of `self` object which will be used in methods
///
///     fn string_is_blank() -> Boolean {
///         Boolean::new(itself.to_string().chars().all(|c| c.is_whitespace()))
///     }
///
///     fn string_length_equals(expected_length: Fixnum) -> Boolean {
///         let real_length = itself.to_string().len() as i64;
///
///         Boolean::new(expected_length.to_i64() == real_length)
///     }
/// );
///
/// fn main() {
///     # VM::init();
///     Class::from_existing("String").define(|itself| {
///         itself.def("blank?", string_is_blank);
///         itself.def("length_equals?", string_length_equals);
///     });
/// }
/// ```
///
/// Ruby:
///
/// ```ruby
/// class String
///   def blank?
///     # ...
///   end
///
///   def length_equals?(expected_length)
///     # ...
///   end
/// end
/// ```
#[macro_export]
macro_rules! methods {
    (
        $itself_class: ty,
        $itself_name: ident,
        $(
            fn $method_name: ident
            ($($arg_name: ident: $arg_type: ty),*) -> $return_type: ident $body: block
        )*
    ) => {
        $(
            #[no_mangle]
            #[allow(unused_mut)]
            pub extern fn $method_name(argc: Argc,
                                       argv: *const AnyObject,
                                       mut $itself_name: $itself_class) -> $return_type {
                let _arguments = VM::parse_arguments(argc, argv);
                let mut _i = 0;

                $(
                    let $arg_name = _arguments[_i].to::<$arg_type>();
                    _i += 1;
                )*

                $body
            }
        )*
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use semver::Version;
use std::env;
use git2::{self, Repository, Commit, Signature, PushOptions, RemoteCallbacks, Cred};

use commit_analyzer::{self, CommitType};
use error::Error;
use config::Config;

pub fn get_signature(repo: &Repository) -> Result<Signature, Error> {
    let author = {
        let mut author = env::var("GIT_COMMITTER_NAME").map_err(Error::from);

        if author.is_err() {
            let config = try!(repo.config());
            author = config.get_string("user.name").map_err(Error::from);
        }
        try!(author)
    };

    let email = {
        let mut email = env::var("GIT_COMMITTER_EMAIL").map_err(Error::from);

        if email.is_err() {
            let config = try!(repo.config());
            email = config.get_string("user.email").map_err(Error::from);
        }
        try!(email)
    };

    Signature::now(&author, &email).map_err(From::from)
}

fn range_to_head(commit: &str) -> String {
    format!("{}..HEAD", commit)
}

fn format_commit(commit: Commit) -> String {
    format!("{}\n{}", commit.id(), commit.message().unwrap_or(""))
}

fn add<P: AsRef<Path>>(repo: &Repository, files: &[P]) -> Result<(), git2::Error> {
    let mut index = try!(repo.index());

    for path in files {
        try!(index.add_path(path.as_ref()));
    }

    index.write()
}

fn commit(config: &Config, message: &str) -> Result<(), git2::Error> {
    let update_ref = format!("refs/heads/{}", config.branch);
    let repo = &config.repository;

    let oid = try!(repo.refname_to_id("HEAD"));
    let parent_commit = try!(repo.find_commit(oid));
    let parents = vec![&parent_commit];

    let mut index = try!(repo.index());
    let tree_oid = try!(index.write_tree());
    let tree = try!(repo.find_tree(tree_oid));

    repo
        .commit(Some(&update_ref), &config.signature, &config.signature, message, &tree, &parents)
        .map(|_| ())
}

fn create_tag(config: &Config, tag_name: &str, message: &str) -> Result<(), git2::Error> {
    let repo = &config.repository;

    let rev = format!("refs/heads/{}", config.branch);
    let obj = try!(repo.revparse_single(&rev));

    repo.tag(tag_name, &obj, &config.signature, message, false)
        .map(|_| ())
}

fn is_https_remote(maybe_remote: Option<&str>) -> bool {
    if let Some(remote) = maybe_remote {
        remote.to_string()
              .starts_with("https://")
    } else {
        false
    }
}

pub fn latest_tag(repo: &Repository) -> Option<Version> {
    let tags = match repo.tag_names(None) {
        Ok(tags) => tags,
        Err(_) => return None
    };

    tags.iter()
        .map(|tag| tag.unwrap())
        .filter_map(|tag| Version::parse(&tag[1..]).ok())
        .max()
}

pub fn version_bump_since_latest(repo: &Repository) -> CommitType {
    match latest_tag(repo) {
        Some(t) => {
            let tag = format!("v{}", t.to_string());
            version_bump_since_tag(repo, &tag)
        },
        None => CommitType::Major
    }
}

pub fn version_bump_since_tag(repo: &Repository, tag: &str) -> CommitType {
    let tag = range_to_head(tag);

    let mut walker = repo.revwalk().expect("Creating a revwalk failed");
    walker.push_range(&tag).expect("Adding a range failed");

    walker.map(|c| repo.find_commit(c.expect("Not a valid commit")).expect("No commit found"))
        .map(format_commit)
        .map(|c| commit_analyzer::analyze_single(&c).expect("Analyzing commit failed"))
        .max().unwrap_or(CommitType::Unknown)
}

pub fn generate_commit_message(new_version: &str) -> String {
    format!("Bump version to {}", new_version).into()
}

pub fn commit_files(config: &Config, new_version: &str) -> Result<(), Error> {
    let repo = &config.repository;
    let files = ["Cargo.toml", "Cargo.lock", "Changelog.md"];
    let files = files.iter().filter(|filename| {
        let path = Path::new(filename);
        !repo.status_should_ignore(path).expect("Determining ignore status of file failed")
    }).collect::<Vec<_>>();

    try!(add(&config.repository, &files[..]));

    commit(config, &generate_commit_message(new_version)).map_err(Error::from)
}

pub fn tag(config: &Config, tag_name: &str, tag_message: &str) -> Result<(), Error> {
    create_tag(config, &tag_name, &tag_message)
        .map_err(Error::from)
}

pub fn push(config: &Config, tag_name: &str) -> Result<(), Error> {
    let repo      = &config.repository;

    let branch    = &config.branch;
    let token     = config.gh_token.as_ref();

    // We need to push both the branch we just committed as well as the tag we created.
    let branch_ref = format!("refs/heads/{}", branch);
    let tag_ref    = format!("refs/tags/{}", tag_name);
    let refs = [&branch_ref[..], &tag_ref[..]];

    let mut remote = try!(repo.find_remote("origin"));
    let mut cbs = RemoteCallbacks::new();
    let mut opts = PushOptions::new();

    if is_https_remote(remote.url()) {
        cbs.credentials(|_url, _username, _allowed| {
            Cred::userpass_plaintext(&token.unwrap(), "")
        });
        opts.remote_callbacks(cbs);
    } else {
        cbs.credentials(|_url, username, _allowed| {
            Cred::ssh_key_from_agent(&username.unwrap())
        });
        opts.remote_callbacks(cbs);
    }

    remote
        .push(&refs, Some(&mut opts))
        .map(|_| ())
        .map_err(Error::from)
}
<commit_msg>fix: remove superflous to_string()<commit_after>use std::path::Path;
use semver::Version;
use std::env;
use git2::{self, Repository, Commit, Signature, PushOptions, RemoteCallbacks, Cred};

use commit_analyzer::{self, CommitType};
use error::Error;
use config::Config;

pub fn get_signature(repo: &Repository) -> Result<Signature, Error> {
    let author = {
        let mut author = env::var("GIT_COMMITTER_NAME").map_err(Error::from);

        if author.is_err() {
            let config = try!(repo.config());
            author = config.get_string("user.name").map_err(Error::from);
        }
        try!(author)
    };

    let email = {
        let mut email = env::var("GIT_COMMITTER_EMAIL").map_err(Error::from);

        if email.is_err() {
            let config = try!(repo.config());
            email = config.get_string("user.email").map_err(Error::from);
        }
        try!(email)
    };

    Signature::now(&author, &email).map_err(From::from)
}

fn range_to_head(commit: &str) -> String {
    format!("{}..HEAD", commit)
}

fn format_commit(commit: Commit) -> String {
    format!("{}\n{}", commit.id(), commit.message().unwrap_or(""))
}

fn add<P: AsRef<Path>>(repo: &Repository, files: &[P]) -> Result<(), git2::Error> {
    let mut index = try!(repo.index());

    for path in files {
        try!(index.add_path(path.as_ref()));
    }

    index.write()
}

fn commit(config: &Config, message: &str) -> Result<(), git2::Error> {
    let update_ref = format!("refs/heads/{}", config.branch);
    let repo = &config.repository;

    let oid = try!(repo.refname_to_id("HEAD"));
    let parent_commit = try!(repo.find_commit(oid));
    let parents = vec![&parent_commit];

    let mut index = try!(repo.index());
    let tree_oid = try!(index.write_tree());
    let tree = try!(repo.find_tree(tree_oid));

    repo
        .commit(Some(&update_ref), &config.signature, &config.signature, message, &tree, &parents)
        .map(|_| ())
}

fn create_tag(config: &Config, tag_name: &str, message: &str) -> Result<(), git2::Error> {
    let repo = &config.repository;

    let rev = format!("refs/heads/{}", config.branch);
    let obj = try!(repo.revparse_single(&rev));

    repo.tag(tag_name, &obj, &config.signature, message, false)
        .map(|_| ())
}

fn is_https_remote(maybe_remote: Option<&str>) -> bool {
    if let Some(remote) = maybe_remote {
        remote.starts_with("https://")
    } else {
        false
    }
}

pub fn latest_tag(repo: &Repository) -> Option<Version> {
    let tags = match repo.tag_names(None) {
        Ok(tags) => tags,
        Err(_) => return None
    };

    tags.iter()
        .map(|tag| tag.unwrap())
        .filter_map(|tag| Version::parse(&tag[1..]).ok())
        .max()
}

pub fn version_bump_since_latest(repo: &Repository) -> CommitType {
    match latest_tag(repo) {
        Some(t) => {
            let tag = format!("v{}", t.to_string());
            version_bump_since_tag(repo, &tag)
        },
        None => CommitType::Major
    }
}

pub fn version_bump_since_tag(repo: &Repository, tag: &str) -> CommitType {
    let tag = range_to_head(tag);

    let mut walker = repo.revwalk().expect("Creating a revwalk failed");
    walker.push_range(&tag).expect("Adding a range failed");

    walker.map(|c| repo.find_commit(c.expect("Not a valid commit")).expect("No commit found"))
        .map(format_commit)
        .map(|c| commit_analyzer::analyze_single(&c).expect("Analyzing commit failed"))
        .max().unwrap_or(CommitType::Unknown)
}

pub fn generate_commit_message(new_version: &str) -> String {
    format!("Bump version to {}", new_version).into()
}

pub fn commit_files(config: &Config, new_version: &str) -> Result<(), Error> {
    let repo = &config.repository;
    let files = ["Cargo.toml", "Cargo.lock", "Changelog.md"];
    let files = files.iter().filter(|filename| {
        let path = Path::new(filename);
        !repo.status_should_ignore(path).expect("Determining ignore status of file failed")
    }).collect::<Vec<_>>();

    try!(add(&config.repository, &files[..]));

    commit(config, &generate_commit_message(new_version)).map_err(Error::from)
}

pub fn tag(config: &Config, tag_name: &str, tag_message: &str) -> Result<(), Error> {
    create_tag(config, &tag_name, &tag_message)
        .map_err(Error::from)
}

pub fn push(config: &Config, tag_name: &str) -> Result<(), Error> {
    let repo      = &config.repository;

    let branch    = &config.branch;
    let token     = config.gh_token.as_ref();

    // We need to push both the branch we just committed as well as the tag we created.
    let branch_ref = format!("refs/heads/{}", branch);
    let tag_ref    = format!("refs/tags/{}", tag_name);
    let refs = [&branch_ref[..], &tag_ref[..]];

    let mut remote = try!(repo.find_remote("origin"));
    let mut cbs = RemoteCallbacks::new();
    let mut opts = PushOptions::new();

    if is_https_remote(remote.url()) {
        cbs.credentials(|_url, _username, _allowed| {
            Cred::userpass_plaintext(&token.unwrap(), "")
        });
        opts.remote_callbacks(cbs);
    } else {
        cbs.credentials(|_url, username, _allowed| {
            Cred::ssh_key_from_agent(&username.unwrap())
        });
        opts.remote_callbacks(cbs);
    }

    remote
        .push(&refs, Some(&mut opts))
        .map(|_| ())
        .map_err(Error::from)
}
<|endoftext|>


<commit_before>use std::io::Command;
use regex::Regex;
use common:: { LogEntry, Feature, Fix, Unknown };

#[deriving(Show)]
pub struct LogReaderConfig {
    pub grep: String,
    pub format: String,
    pub from: String,
    pub to: String
}

pub fn get_latest_tag () -> String {

    Command::new("git")
            .arg("rev-list")
            .arg("--tags")
            .arg("--max-count=1")
            .spawn()
            .ok().expect("failed to invoke ref-list")
            .stdout.get_mut_ref().read_to_string()
            .ok().expect("failed to get latest git log")
            .as_slice().trim_chars('\n')
            .to_string()
}

pub fn get_log_entries (config:LogReaderConfig) -> Vec<LogEntry>{

    let range = if config.from.len() == 0 {
        "HEAD".to_string()
    }
    else {
        format!("{}..{}", config.from, config.to)
    };

    Command::new("git")
            .arg("log")
            .arg("-E")
            .arg(format!("--grep={}",config.grep))
            .arg(format!("--format={}", "%H%n%s%n%b%n==END=="))
            .arg(range)
            .spawn()
            .ok().expect("failed to invoke `git log`")
            .stdout.get_mut_ref().read_to_string()
            .ok().expect("failed to read git log")
            .as_slice()
            .split_str("\n==END==\n")
            .map(|commit_str| { parse_raw_commit(commit_str) })
            .filter(| entry| entry.commit_type != Unknown)
            .collect()
}

static COMMIT_PATTERN: Regex = regex!(r"^(.*)\((.*)\):(.*)");
static CLOSES_PATTERN: Regex = regex!(r"(?:Closes|Fixes|Resolves)\s((?:#(\d+)(?:,\s)?)+)");

fn parse_raw_commit(commit_str:&str) -> LogEntry {

    let mut lines = commit_str.split('\n').collect::<Vec<&str>>();

    //println!("parsed: {}", lines);

    let hash = lines.remove(0).unwrap_or("").to_string();
    let temp_subject = lines.remove(0).unwrap_or("").to_string();

    let mut entry = LogEntry {
        hash: hash,
        subject: "".to_string(),
        component: "".to_string(),
        closes: vec!(),
        breaks: vec!(),
        commit_type: Unknown
    };

    lines.iter().all(|line| {
        CLOSES_PATTERN.captures(*line)
                      .map(|caps| {
                          entry.closes.push(caps.at(2).to_string());
                      });
        true
    });

    match COMMIT_PATTERN.captures(temp_subject.as_slice()) {
        Some(caps) => {
            entry.commit_type = match caps.at(1) {
                "feat" => Feature,
                "fix"  => Fix,
                _      => Unknown
            };
            entry.component = caps.at(2).to_string();
            entry.subject = caps.at(3).to_string();
        },
        _ => ()
    };

    entry
}<commit_msg>refactor(git): reduce boilerplate code<commit_after>use std::io::Command;
use regex::Regex;
use common:: { LogEntry, Feature, Fix, Unknown };

#[deriving(Show)]
pub struct LogReaderConfig {
    pub grep: String,
    pub format: String,
    pub from: String,
    pub to: String
}

pub fn get_latest_tag () -> String {

    Command::new("git")
            .arg("rev-list")
            .arg("--tags")
            .arg("--max-count=1")
            .spawn()
            .ok().expect("failed to invoke ref-list")
            .stdout.get_mut_ref().read_to_string()
            .ok().expect("failed to get latest git log")
            .as_slice().trim_chars('\n')
            .to_string()
}

pub fn get_log_entries (config:LogReaderConfig) -> Vec<LogEntry>{

    let range = if config.from.len() == 0 {
        "HEAD".to_string()
    }
    else {
        format!("{}..{}", config.from, config.to)
    };

    Command::new("git")
            .arg("log")
            .arg("-E")
            .arg(format!("--grep={}",config.grep))
            .arg(format!("--format={}", "%H%n%s%n%b%n==END=="))
            .arg(range)
            .spawn()
            .ok().expect("failed to invoke `git log`")
            .stdout.get_mut_ref().read_to_string()
            .ok().expect("failed to read git log")
            .as_slice()
            .split_str("\n==END==\n")
            .map(|commit_str| { parse_raw_commit(commit_str) })
            .filter(| entry| entry.commit_type != Unknown)
            .collect()
}

static COMMIT_PATTERN: Regex = regex!(r"^(.*)\((.*)\):(.*)");
static CLOSES_PATTERN: Regex = regex!(r"(?:Closes|Fixes|Resolves)\s((?:#(\d+)(?:,\s)?)+)");

fn parse_raw_commit(commit_str:&str) -> LogEntry {

    let mut lines = commit_str.split('\n').collect::<Vec<&str>>();

    //println!("parsed: {}", lines);

    let hash = lines.remove(0).unwrap_or("").to_string();
    let temp_subject = lines.remove(0).unwrap_or("").to_string();

    let mut entry = LogEntry {
        hash: hash,
        subject: "".to_string(),
        component: "".to_string(),
        closes: vec!(),
        breaks: vec!(),
        commit_type: Unknown
    };

    lines.iter().all(|line| {
        CLOSES_PATTERN.captures(*line)
                      .map(|caps| {
                          entry.closes.push(caps.at(2).to_string());
                      });
        true
    });

    COMMIT_PATTERN.captures(temp_subject.as_slice())
                  .map(|caps| {
                       entry.commit_type = match caps.at(1) {
                           "feat" => Feature,
                           "fix"  => Fix,
                           _      => Unknown
                       };
                       entry.component = caps.at(2).to_string();
                       entry.subject = caps.at(3).to_string();
                  });

    entry
}<|endoftext|>


<commit_before>use std::cmp;
use image::Pixel;

pub struct HSL {
    pub h: f64, // 0-360 Degree
    pub s: f64, // 0-1 (Percent)
    pub l: f64, // 0-1 (Percent)
}

impl HSL {
    /// Convert Pixel value to HSL
    ///
    /// Algorithm from [go-color] by Brandon Thomson <bt@brandonthomson.com>.
    ///
    /// [go-color]: https://github.com/bthomson/go-color
    pub fn from_pixel<P>(pixel: &P) -> HSL
        where P: Pixel<Subpixel = u8>
    {
        let mut h: f64;
        let s: f64;
        let l: f64;

        let pixel = pixel.clone();
        let rgb = pixel.to_rgb();
        let rgb = rgb.channels();
        let (r, g, b) = (rgb[0], rgb[1], rgb[2]);

        let max = cmp::max(cmp::max(r, g), b);
        let min = cmp::min(cmp::min(r, g), b);

        // Normalized RGB: Divide everything by 255 to get percentages of colors.
        let (r, g, b) = (r as f64 / 255_f64, g as f64 / 255_f64, b as f64 / 255_f64);
        let (min, max) = (min as f64 / 255_f64, max as f64 / 255_f64);

        // Luminosity is the average of the max and min rgb color intensities.
        l = (max + min) / 2_f64;

        // Saturation
        let delta: f64 = max - min;
        if delta == 0_f64 {
    		// it's gray
            return HSL { h: 0_f64, s: 0_f64, l: l};
        }

        // it's not gray
        if l < 0.5_f64 {
            s = delta / (max + min);
        } else {
            s = delta / (2_f64 - max - min);
        }

        // Hue
        let r2 = (((max - r) / 6_f64) + (delta / 2_f64)) / delta;
        let g2 = (((max - g) / 6_f64) + (delta / 2_f64)) / delta;
        let b2 = (((max - b) / 6_f64) + (delta / 2_f64)) / delta;

        h = match max {
            x if x == r => b2 - g2,
            x if x == g => (1_f64 / 3_f64) + r2 - b2,
            _ => (2_f64 / 3_f64) + g2 - r2,
        };

        // Fix wraparounds
        if h < 0 as f64 {
            h += 1_f64;
        } else if h > 1 as f64 {
            h -= 1_f64;
        }

        HSL { h: h * 360_f64, s: s, l: l }
    }
}

#[cfg(test)]
mod test {
    macro_rules! test_rgb_to_hsl {
        (($r:expr, $g:expr, $b:expr) => ($h:expr, $s:expr, $l:expr)) => {
            {
                // Round gracefully to half a percent
                const EPSILON: f64 = 0.05;
                // Round gracefully to half a degree
                const EPSILON_DEGREE: f64 = 0.5;

                let rgb = Rgb::from_channels($r as u8, $g as u8, $b as u8, 0_u8);
                let hsl = HSL::from_pixel(&rgb);

                assert!(
                    $h - hsl.h <= EPSILON_DEGREE,
                    "Converting {:?} to HSL: H differs too much. Expected {}, got {}.",
                        rgb, $h, hsl.h
                );
                assert!(
                    $s - hsl.s <= EPSILON,
                    "Converting {:?} to HSL: S differs too much. Expected {}, got {}.",
                        rgb, $s, hsl.s
                );
                assert!(
                    $l - hsl.l <= EPSILON,
                    "Converting {:?} to HSL: L differs too much. Expected {}, got {}.",
                        rgb, $l, hsl.l
                );
            }
        };
    }

    use image::{Rgb, Pixel};
    use super::HSL;

    #[test]
    fn rgb_to_hsl() {
        // black
        test_rgb_to_hsl!( (0, 0, 0) => (0_f64, 0_f64, 0_f64) );

        // white
        test_rgb_to_hsl!( (255, 255, 255) => (0_f64, 0_f64, 1_f64) );

        // http://rgb.to/rgb/18,35,67
        test_rgb_to_hsl!( (18, 35, 67) => (219_f64, 0.58_f64, 0.17_f64) );

        // http://rgb.to/hex/93c6cd
        test_rgb_to_hsl!( (147, 198, 205) => (187_f64, 0.37_f64, 0.69_f64) );

        // http://rgb.to/hex/bada55
        test_rgb_to_hsl!( (186, 218, 85) => (74_f64, 0.64_f64, 0.59_f64) );

        // http://rgb.to/hex/ff0
        test_rgb_to_hsl!( (255, 255, 0) => (60_f64, 1_f64, 0.5_f64) );

        // http://rgb.to/rgb/198,250,172
        test_rgb_to_hsl!( (198, 250, 172) => (100_f64, 0.89_f64, 0.83_f64) );

        // http://rgb.to/hex/faadc7
        test_rgb_to_hsl!( (250, 173, 199) => (340_f64, 0.89_f64, 0.83_f64) );
    }
}
<commit_msg>Reformat HSL Tests<commit_after>use std::cmp;
use image::Pixel;

pub struct HSL {
    pub h: f64, // 0-360 Degree
    pub s: f64, // 0-1 (Percent)
    pub l: f64, // 0-1 (Percent)
}

impl HSL {
    /// Convert Pixel value to HSL
    ///
    /// Algorithm from [go-color] by Brandon Thomson <bt@brandonthomson.com>.
    ///
    /// [go-color]: https://github.com/bthomson/go-color
    pub fn from_pixel<P>(pixel: &P) -> HSL
        where P: Pixel<Subpixel = u8>
    {
        let mut h: f64;
        let s: f64;
        let l: f64;

        let pixel = pixel.clone();
        let rgb = pixel.to_rgb();
        let rgb = rgb.channels();
        let (r, g, b) = (rgb[0], rgb[1], rgb[2]);

        let max = cmp::max(cmp::max(r, g), b);
        let min = cmp::min(cmp::min(r, g), b);

        // Normalized RGB: Divide everything by 255 to get percentages of colors.
        let (r, g, b) = (r as f64 / 255_f64, g as f64 / 255_f64, b as f64 / 255_f64);
        let (min, max) = (min as f64 / 255_f64, max as f64 / 255_f64);

        // Luminosity is the average of the max and min rgb color intensities.
        l = (max + min) / 2_f64;

        // Saturation
        let delta: f64 = max - min;
        if delta == 0_f64 {
    		// it's gray
            return HSL { h: 0_f64, s: 0_f64, l: l};
        }

        // it's not gray
        if l < 0.5_f64 {
            s = delta / (max + min);
        } else {
            s = delta / (2_f64 - max - min);
        }

        // Hue
        let r2 = (((max - r) / 6_f64) + (delta / 2_f64)) / delta;
        let g2 = (((max - g) / 6_f64) + (delta / 2_f64)) / delta;
        let b2 = (((max - b) / 6_f64) + (delta / 2_f64)) / delta;

        h = match max {
            x if x == r => b2 - g2,
            x if x == g => (1_f64 / 3_f64) + r2 - b2,
            _ => (2_f64 / 3_f64) + g2 - r2,
        };

        // Fix wraparounds
        if h < 0 as f64 {
            h += 1_f64;
        } else if h > 1 as f64 {
            h -= 1_f64;
        }

        HSL { h: h * 360_f64, s: s, l: l }
    }
}

#[cfg(test)]
mod test {
    macro_rules! test_rgb_to_hsl {
        (($r:expr, $g:expr, $b:expr) <=> ($h:expr, $s:expr, $l:expr)) => {
            {
                // Round gracefully to half a percent
                const EPSILON: f64 = 0.05;
                // Round gracefully to half a degree
                const EPSILON_DEGREE: f64 = 0.5;

                let rgb = Rgb::from_channels($r as u8, $g as u8, $b as u8, 0_u8);
                let hsl = HSL::from_pixel(&rgb);

                assert!(
                    $h - hsl.h <= EPSILON_DEGREE,
                    "Converting {:?} to HSL: H differs too much. Expected {}, got {}.",
                        rgb, $h, hsl.h
                );
                assert!(
                    $s - hsl.s <= EPSILON,
                    "Converting {:?} to HSL: S differs too much. Expected {}, got {}.",
                        rgb, $s, hsl.s
                );
                assert!(
                    $l - hsl.l <= EPSILON,
                    "Converting {:?} to HSL: L differs too much. Expected {}, got {}.",
                        rgb, $l, hsl.l
                );
            }
        };
    }

    use image::{Rgb, Pixel};
    use super::HSL;

    #[test]
    fn rgb_to_hsl() {
        // black
        test_rgb_to_hsl!( (0, 0, 0) <=> (0_f64, 0_f64, 0_f64) );

        // white
        test_rgb_to_hsl!( (255, 255, 255) <=> (0_f64, 0_f64, 1_f64) );

        // http://rgb.to/rgb/18,35,67
        test_rgb_to_hsl!( (18, 35, 67) <=> (219_f64, 0.58_f64, 0.17_f64) );

        // http://rgb.to/hex/93c6cd
        test_rgb_to_hsl!( (147, 198, 205) <=> (187_f64, 0.37_f64, 0.69_f64) );

        // http://rgb.to/hex/bada55
        test_rgb_to_hsl!( (186, 218, 85) <=> (74_f64, 0.64_f64, 0.59_f64) );

        // http://rgb.to/hex/ff0
        test_rgb_to_hsl!( (255, 255, 0) <=> (60_f64, 1_f64, 0.5_f64) );

        // http://rgb.to/rgb/198,250,172
        test_rgb_to_hsl!( (198, 250, 172) <=> (100_f64, 0.89_f64, 0.83_f64) );

        // http://rgb.to/hex/faadc7
        test_rgb_to_hsl!( (250, 173, 199) <=> (340_f64, 0.89_f64, 0.83_f64) );
    }
}
<|endoftext|>