<commit_before>#[macro_use]
extern crate nom;

use std::str;
use nom::{IResult, ErrorKind, digit};

#[derive(Debug, PartialEq)]
pub enum LiteralValue {
    Null,
    Number,
    String
}

#[derive(Debug, PartialEq)]
pub enum Expression {
    ThisExpression,
    Literal {
        value: LiteralValue
    }
}

#[derive(Debug, PartialEq)]
pub struct VariableDeclarator {
    pub id: String,
    pub init: Option<Expression>
}

#[derive(Debug, PartialEq)]
pub enum Statement {
    VariableDeclaration {
        declarations: Vec<VariableDeclarator>,
        kind: String
    },
    Expression(Expression)
}

#[derive(Debug, PartialEq)]
pub struct Program {
    pub body: Vec<Statement>
}

fn var_name_char(c: char) -> bool {
    c.is_alphanumeric() || c == '_' || c == '$'
}

named!(variable_declarator< &str, VariableDeclarator >, do_parse!(
    return_error!(ErrorKind::Custom(42), peek!(none_of!("0123456789"))) >>
    // return_error!(ErrorKind::Custom(42), not!(tag!("1"))) >>
    // peek!(verify!(nom::anychar, |c: char| (c.is_alphabetic() || c == '_' || c == '$'))) >>
    id: take_while1_s!(var_name_char) >>
    init: opt!(
        do_parse!(
            ws!(tag!("=")) >>
            res: expression >>
            (res)
        )
    ) >>
    (VariableDeclarator {
        id: id.to_string(),
        init: init
    })
));

named!(variable_declaration_statement< &str, Statement >, do_parse!(
    var_type: tag!("var") >>
    take_while1_s!(char::is_whitespace) >>
    declarators: ws!(separated_list!(tag!(","), variable_declarator)) >>
    (Statement::VariableDeclaration {
        declarations: declarators,
        kind: var_type.to_string()
    })
));

named!(null_literal_value< &str, LiteralValue >, do_parse!(
    tag!("null") >>
    (LiteralValue::Null)
));

// Largely inspired from nom (thanks to geal)
// https://github.com/Geal/nom/blob/66128e5ccf316f60fdd55a7ae8d266f42955b00c/benches/json.rs#L23-L48
named!(number_literal_value< &str, LiteralValue >, do_parse!(
    pair!(
        opt!(alt!(tag!("+") | tag!("-"))),
        alt_complete!(
            delimited!(digit, tag!("."), opt!(complete!(digit))) |
            delimited!(opt!(digit), tag!("."), digit)            |
            digit
        )
    ) >>
    (LiteralValue::Number)
));

pub fn eat_string(input: &str) -> IResult< &str, &str > {
    if input.len() == 0 {
        return IResult::Incomplete(nom::Needed::Unknown);
    }
    let mut chars = input.chars();

    let separator = match chars.nth(0) {
        sep @ Some('\'') | sep @ Some('"') => sep.unwrap(),
        Some(_) | None => return nom::IResult::Error(error_position!(ErrorKind::Custom(43), input))
    };

    let mut escaped = false;
    let mut idx = 1;
    for item in chars {
        if escaped {
            escaped = false;
        } else {
            match item {
                c if c == separator => return IResult::Done(&input[idx+1..], &input[0..idx+1]),
                '\\' => escaped = true,
                '\n' => return IResult::Incomplete(nom::Needed::Unknown),
                _ => ()
            }
        }
        idx += 1;
    }

    return IResult::Error(error_position!(ErrorKind::Custom(43), input));
}

fn print_str<'a>(input: &'a str, string: &str) -> IResult< &'a str, &'a str > {
    println!("{}", string);
    IResult::Done(input, input)
}

named!(string_literal_value< &str, LiteralValue >, do_parse!(
    string: call!(eat_string) >>
    call!(print_str, string) >>
    (LiteralValue::String)
));

named!(literal_value< &str, LiteralValue >, alt_complete!(
    null_literal_value |
    number_literal_value |
    string_literal_value
));

named!(literal_expression< &str, Expression >, do_parse!(
    literal_value: call!(literal_value) >>
    (Expression::Literal {
        value: literal_value
    })
));

named!(this_expression< &str, Expression >, do_parse!(
    tag!("this") >>
    (Expression::ThisExpression)
));

named!(expression< &str, Expression >, alt_complete!(
    this_expression |
    literal_expression
));

named!(expression_statement< &str, Statement >, do_parse!(
    expression: call!(expression) >>
    (Statement::Expression(expression))
));

named!(statement< &str, Statement >, alt_complete!(
    variable_declaration_statement |
    expression_statement
));

named!(pub program< &str, Program >, do_parse!(
    // TODO support ASI
    body: ws!(separated_list!(tag!(";"), statement)) >>
    // Paving the way for ASI with opt! here.
    opt!(tag!(";")) >>
    (Program {
        body: body
    })
));

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

    #[test]
    fn it_parses_declaration_expression() {
        assert_eq!(program("var test;"), IResult::Done("", Program {
            body: vec![
                Statement::VariableDeclaration {
                    declarations: vec![VariableDeclarator {
                        id: "test".to_string(),
                        init: None
                    }],
                    kind: "var".to_string()
                }
            ]
        }));
    }

    #[test]
    fn it_parses_multi_declaration_expression() {
        assert_eq!(program("var test,\n\t foo;"), IResult::Done("", Program {
            body: vec![
                Statement::VariableDeclaration {
                    declarations: vec![VariableDeclarator {
                        id: "test".to_string(),
                        init: None
                    }, VariableDeclarator {
                        id: "foo".to_string(),
                        init: None
                    }],
                    kind: "var".to_string()
                }
            ]
        }));
    }

    #[test]
    fn it_parses_multi_declaration_expression_with_initialisation() {
        assert_eq!(program("var test = this,\n\t foo = null;"), IResult::Done("", Program {
            body: vec![
                Statement::VariableDeclaration {
                    declarations: vec![VariableDeclarator {
                        id: "test".to_string(),
                        init: Some(Expression::ThisExpression)
                    }, VariableDeclarator {
                        id: "foo".to_string(),
                        init: Some(Expression::Literal {
                            value: LiteralValue::Null
                        })
                    }],
                    kind: "var".to_string()
                }
            ]
        }));
    }

    #[test]
    fn it_parses_statements_with_whitespaces_around() {
        assert_eq!(program(" var test;"), program("var test;"));
        assert_eq!(program(" var   test   ;"), program("var test;"));
        assert_eq!(program(" var   test   ;   ").to_result(), program("var test;").to_result());
    }

    #[test]
    fn it_fails_to_parse_var_names_beginning_with_nums() {
        let res = program("var 1test;");
        println!("FAIL HERE {:?}", res);
        assert!(res.is_err());
        assert!(false, "decris mieux!");
    }

    #[test]
    fn it_parses_this_expression() {
        assert_eq!(program("this;"), IResult::Done("", Program {
            body: vec![
                Statement::Expression(Expression::ThisExpression)
            ]
        }));
    }

    #[test]
    fn it_parses_null_literal_expression() {
        assert_eq!(program("null;"), IResult::Done("", Program {
            body: vec![
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Null
                    }
                )
            ]
        }));
    }

    #[test]
    fn it_parses_number_literal_expression() {
        assert_eq!(program("42;   +42.042;   -42.4242;"), IResult::Done("", Program {
            body: vec![
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Number
                    }
                ),
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Number
                    }
                ),
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Number
                    }
                )
            ]
        }));
    }

    #[test]
    fn it_parses_string_literal_expression() {
        let res = program("\"foo\";   'foo'; \"foo$\\n \\\"bar\\\"\";");
        assert_eq!(res, IResult::Done("", Program {
            body: vec![
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::String
                    }
                ),
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::String
                    }
                ),
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::String
                    }
                )
            ]
        }));
        assert!(false);
    }

    #[test]
    fn it_parses_incomplete_string_literal_expression() {
        assert_eq!(program("\"foo   \r\n bar\";"), IResult::Incomplete(nom::Needed::Unknown));
        assert_eq!(program("\"foo   \n bar\";"), IResult::Incomplete(nom::Needed::Unknown));
    }

}
<commit_msg>parse literal values and support if statements<commit_after>#[macro_use]
extern crate nom;

use std::str::{self, FromStr};
use nom::{IResult, ErrorKind, digit};

#[derive(Debug, PartialEq)]
pub enum LiteralValue {
    Null,
    Number(f32),
    String(String),
    Boolean(bool)
}

#[derive(Debug, PartialEq)]
pub enum Expression {
    ThisExpression,
    Literal {
        value: LiteralValue
    }
}

#[derive(Debug, PartialEq)]
pub struct VariableDeclarator {
    pub id: String,
    pub init: Option<Expression>
}

#[derive(Debug, PartialEq)]
pub enum Statement {
    VariableDeclaration {
        declarations: Vec<VariableDeclarator>,
        kind: String
    },
    If {
        test: Expression,
        consequent: Box<Statement>,
        alternate: Option<Box<Statement>>
    },
    Block {
        body: Vec<Statement>
    },
    Expression(Expression)
}

#[derive(Debug, PartialEq)]
pub struct Program {
    pub body: Vec<Statement>
}

fn var_name_char(c: char) -> bool {
    c.is_alphanumeric() || c == '_' || c == '$'
}

named!(variable_declarator< &str, VariableDeclarator >, do_parse!(
    return_error!(ErrorKind::Custom(42), peek!(none_of!("0123456789"))) >>
    // return_error!(ErrorKind::Custom(42), not!(tag!("1"))) >>
    // peek!(verify!(nom::anychar, |c: char| (c.is_alphabetic() || c == '_' || c == '$'))) >>
    id: take_while1_s!(var_name_char) >>
    init: opt!(
        do_parse!(
            ws!(tag!("=")) >>
            res: expression >>
            (res)
        )
    ) >>
    (VariableDeclarator {
        id: id.to_string(),
        init: init
    })
));

named!(if_statement< &str, Statement >, do_parse!(
    ws!(tag!("if")) >>
    test: delimited!(tag!("("), expression, tag!(")")) >>
    consequent: call!(block_statement) >>
    // opt!(complete!(…)) so it doesn't return an incomplete state
    // FIXME: isn't there a smarter way to handle this?
    alternate_opt: opt!(complete!(preceded!(ws!(tag!("else")), block_statement))) >>
    (Statement::If {
        test: test,
        consequent: Box::new(consequent),
        alternate: match alternate_opt {
            Some(alternate) => Some(Box::new(alternate)),
            None => None
        }
    })
));

named!(block_statement< &str, Statement >, map!(
    ws!(delimited!(
        tag!("{"),
        call!(body),
        tag!("}")
    )), |body| (Statement::Block { body: body })
));

named!(variable_declaration_statement< &str, Statement >, do_parse!(
    var_type: tag!("var") >>
    take_while1_s!(char::is_whitespace) >>
    declarators: ws!(separated_list!(tag!(","), variable_declarator)) >>
    (Statement::VariableDeclaration {
        declarations: declarators,
        kind: var_type.to_string()
    })
));

named!(null_literal_value< &str, LiteralValue >, do_parse!(
    tag!("null") >>
    (LiteralValue::Null)
));

named!(boolean_literal_value< &str, LiteralValue >, alt!(
    tag!("true")  => { |_| LiteralValue::Boolean(true)  } |
    tag!("false") => { |_| LiteralValue::Boolean(false) }
));

// Largely inspired from nom (thanks to geal)
// https://github.com/Geal/nom/blob/66128e5ccf316f60fdd55a7ae8d266f42955b00c/benches/json.rs#L23-L48
// FIXME support hexadecimal, octal and binary expressions too
named!(number_literal_value< &str, LiteralValue >, map!(
    pair!(
        opt!(alt!(tag!("+") | tag!("-"))),
        map_res!(
            recognize!(
                alt_complete!(
                    delimited!(digit, tag!("."), opt!(complete!(digit))) |
                    delimited!(opt!(digit), tag!("."), digit)            |
                    digit
                )
            ),
            FromStr::from_str
        )
    ),
    |(sign, abs_value): (Option<&str>, f32)| {
        let value = if sign == Some("-") { -abs_value } else { abs_value };
        LiteralValue::Number(value)
    }
));

fn eat_string(input: &str) -> IResult< &str, &str > {
    if input.len() == 0 {
        return IResult::Incomplete(nom::Needed::Unknown);
    }
    let mut chars = input.chars();

    let separator = match chars.nth(0) {
        sep @ Some('\'') | sep @ Some('"') => sep.unwrap(),
        Some(_) | None => return nom::IResult::Error(error_position!(ErrorKind::Custom(43), input))
    };

    let mut escaped = false;
    let mut idx = 1;
    for item in chars {
        if escaped {
            escaped = false;
        } else {
            match item {
                c if c == separator => return IResult::Done(&input[idx+1..], &input[0..idx+1]),
                '\\' => escaped = true,
                '\n' => return IResult::Incomplete(nom::Needed::Unknown),
                _ => ()
            }
        }
        idx += 1;
    }

    return IResult::Error(error_position!(ErrorKind::Custom(43), input));
}

named!(string_literal_value< &str, LiteralValue >, do_parse!(
    string: call!(eat_string) >>
    (LiteralValue::String(string.to_string()))
));

named!(literal_value< &str, LiteralValue >, alt_complete!(
    number_literal_value |
    null_literal_value |
    boolean_literal_value |
    string_literal_value
));

named!(literal_expression< &str, Expression >, do_parse!(
    literal_value: call!(literal_value) >>
    (Expression::Literal {
        value: literal_value
    })
));

named!(this_expression< &str, Expression >, do_parse!(
    tag!("this") >>
    (Expression::ThisExpression)
));

named!(expression< &str, Expression >, ws!(alt_complete!(
    this_expression |
    literal_expression
)));

named!(expression_statement< &str, Statement >, do_parse!(
    expression: call!(expression) >>
    (Statement::Expression(expression))
));

named!(statement< &str, Statement >, alt_complete!(
    terminated!(variable_declaration_statement, tag!(";")) |
    terminated!(expression_statement, tag!(";")) |
    block_statement |
    if_statement
));

// TODO support ASI
named!(body< &str, Vec<Statement> >, ws!(
    many0!(statement)
));

named!(pub program< &str, Program >, do_parse!(
    body: call!(body) >>
    (Program {
        body: body
    })
));

#[cfg(test)]
mod tests {
    use super::*;
    use nom::{IResult, Needed};

    #[test]
    fn it_parses_declaration_expression() {
        assert_eq!(program("var test;"), IResult::Done("", Program {
            body: vec![
                Statement::VariableDeclaration {
                    declarations: vec![VariableDeclarator {
                        id: "test".to_string(),
                        init: None
                    }],
                    kind: "var".to_string()
                }
            ]
        }));
    }

    #[test]
    fn it_parses_multi_declaration_expression() {
        assert_eq!(program("var test,\n\t foo;"), IResult::Done("", Program {
            body: vec![
                Statement::VariableDeclaration {
                    declarations: vec![VariableDeclarator {
                        id: "test".to_string(),
                        init: None
                    }, VariableDeclarator {
                        id: "foo".to_string(),
                        init: None
                    }],
                    kind: "var".to_string()
                }
            ]
        }));
    }

    #[test]
    fn it_parses_multi_declaration_expression_with_initialisation() {
        assert_eq!(program("var test = this,\n\t foo = null;"), IResult::Done("", Program {
            body: vec![
                Statement::VariableDeclaration {
                    declarations: vec![VariableDeclarator {
                        id: "test".to_string(),
                        init: Some(Expression::ThisExpression)
                    }, VariableDeclarator {
                        id: "foo".to_string(),
                        init: Some(Expression::Literal {
                            value: LiteralValue::Null
                        })
                    }],
                    kind: "var".to_string()
                }
            ]
        }));
    }

    #[test]
    fn it_parses_statements_with_whitespaces_around() {
        assert_eq!(program(" var test;"), program("var test;"));
        assert_eq!(program(" var   test   ;"), program("var test;"));
        assert_eq!(program(" var   test   ;   ").to_result(), program("var test;").to_result());
    }

    #[test]
    fn it_fails_to_parse_var_names_beginning_with_nums() {
        let res = program("var 1test;");
        println!("FAIL HERE {:?}", res);
        assert!(res.is_err());
        assert!(false, "decris mieux!");
    }

    #[test]
    fn it_parses_this_expression() {
        assert_eq!(program("this;"), IResult::Done("", Program {
            body: vec![
                Statement::Expression(Expression::ThisExpression)
            ]
        }));
    }

    #[test]
    fn it_parses_null_literal_expression() {
        assert_eq!(program("null;"), IResult::Done("", Program {
            body: vec![
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Null
                    }
                )
            ]
        }));
    }

    #[test]
    fn it_parses_decimal_number_literal_expression() {
        assert_eq!(program("42;   +42.042;   -42.4242;"), IResult::Done("", Program {
            body: vec![
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Number(42.0f32)
                    }
                ),
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Number(42.042f32)
                    }
                ),
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Number(-42.4242f32)
                    }
                )
            ]
        }));
    }

    // FIXME should pass…
    #[test]
    fn it_parses_octal_number_literal_expression() {
        assert_eq!(program("0o10"), IResult::Done("", Program {
            body: vec![
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Number(8f32)
                    }
                )
            ]
        }));
    }

    #[test]
    fn it_parses_string_literal_expression() {
        let res = program("\"foo\";   'foo'; \"foo$\\n \\\"bar\\\"\";");
        assert_eq!(res, IResult::Done("", Program {
            body: vec![
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::String("\"foo\"".to_string())
                    }
                ),
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::String("'foo'".to_string())
                    }
                ),
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::String("\"foo$\\n \\\"bar\\\"\"".to_string())
                    }
                )
            ]
        }));
    }

    #[test]
    fn it_parses_incomplete_string_literal_expression() {
        assert_eq!(program("\"foo   \r\n bar\";"), IResult::Incomplete(Needed::Unknown));
        assert_eq!(program("\"foo   \n bar\";"), IResult::Incomplete(Needed::Unknown));
    }

    #[test]
    fn it_parses_boolean_literal_expression() {
        assert_eq!(program("true; false;"), IResult::Done("", Program {
            body: vec![
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Boolean(true)
                    }
                ),
                Statement::Expression(
                    Expression::Literal {
                        value: LiteralValue::Boolean(false)
                    }
                )
            ]
        }));
    }

    #[test]
    fn it_parses_if_statement() {
        // FIXME test with newlines in the test. ASI shouldn't work in it.
        // TODO

        assert_eq!(program("if ( true ) {\n 42; \n 43; \n}"), IResult::Done("", Program {
            body: vec![
                Statement::If {
                    test: Expression::Literal {
                        value: LiteralValue::Boolean(true)
                    },
                    consequent: Box::new(Statement::Block {
                        body: vec![
                            Statement::Expression(
                                Expression::Literal {
                                    value: LiteralValue::Number(42f32)
                                }
                            ),
                            Statement::Expression(
                                Expression::Literal {
                                    value: LiteralValue::Number(43f32)
                                }
                            )
                        ]
                    }),
                    alternate: None
                }
            ]
        }));
    }

    #[test]
    fn it_parses_if_else_statement() {
        // FIXME test with newlines in the test. ASI shouldn't work in it.
        assert_eq!(program("if (true) {\n 42; 43; \n} else { 44; 45; }"), IResult::Done("", Program {
            body: vec![
                Statement::If {
                    test: Expression::Literal {
                        value: LiteralValue::Boolean(true)
                    },
                    consequent: Box::new(Statement::Block {
                        body: vec![
                            Statement::Expression(
                                Expression::Literal {
                                    value: LiteralValue::Number(42f32)
                                }
                            ),
                            Statement::Expression(
                                Expression::Literal {
                                    value: LiteralValue::Number(43f32)
                                }
                            )
                        ]
                    }),
                    alternate: Some(Box::new(Statement::Block{
                        body: vec![
                            Statement::Expression(
                                Expression::Literal {
                                    value: LiteralValue::Number(44f32)
                                }
                            ),
                            Statement::Expression(
                                Expression::Literal {
                                    value: LiteralValue::Number(45f32)
                                }
                            )
                        ]
                    }))
                }
            ]
        }));
    }

    #[test]
    fn it_parses_block_statement() {
        assert_eq!(program("{ true; var test; }"), IResult::Done("", Program {
            body: vec![
                Statement::Block {
                    body: vec![
                        Statement::Expression(
                            Expression::Literal {
                                value: LiteralValue::Boolean(true)
                            }
                        ),
                        Statement::VariableDeclaration {
                            declarations: vec![VariableDeclarator {
                                id: "test".to_string(),
                                init: None
                            }],
                            kind: "var".to_string()
                        }
                    ]
                }
            ]
        }));
    }

}
<|endoftext|>


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

use std::cell::UnsafeCell;
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::sync::atomic::AtomicPtr;
use std::sync::atomic::Ordering;
use std::sync::Arc;

/// An Atom wraps an AtomicPtr, it allows for safe mutation of an atomic
/// into common Rust Types.
pub struct Atom

where
    P: IntoRawPtr + FromRawPtr,
{
    inner: AtomicPtr<()>,
    data: PhantomData<UnsafeCell
>,
}

impl
 Debug for Atom

where
    P: IntoRawPtr + FromRawPtr,
{
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        write!(f, "atom({:?})", self.inner.load(Ordering::Relaxed))
    }
}

impl
 Atom

where
    P: IntoRawPtr + FromRawPtr,
{
    /// Create a empty Atom
    pub fn empty() -> Atom
 {
        Atom {
            inner: AtomicPtr::new(ptr::null_mut()),
            data: PhantomData,
        }
    }

    /// Create a new Atomic from Pointer P
    pub fn new(value: P) -> Atom
 {
        Atom {
            inner: AtomicPtr::new(value.into_raw()),
            data: PhantomData,
        }
    }

    /// Swap a new value into the Atom, This will try multiple
    /// times until it succeeds. The old value will be returned.
    pub fn swap(&self, v: P, order: Ordering) -> Option
 {
        let new = v.into_raw();
        let old = self.inner.swap(new, order);
        unsafe { Self::inner_from_raw(old) }
    }

    /// Take the value of the Atom replacing it with null pointer
    /// Returning the contents. If the contents was a `null` pointer the
    /// result will be `None`.
    pub fn take(&self, order: Ordering) -> Option
 {
        let old = self.inner.swap(ptr::null_mut(), order);
        unsafe { Self::inner_from_raw(old) }
    }

    /// This will do a `CAS` setting the value only if it is NULL
    /// this will return `None` if the value was written,
    /// otherwise a `Some(v)` will be returned, where the value was
    /// the same value that you passed into this function
    pub fn set_if_none(&self, v: P, order: Ordering) -> Option
 {
        let new = v.into_raw();
        let old = self.inner.compare_and_swap(ptr::null_mut(), new, order);
        if !old.is_null() {
            Some(unsafe { FromRawPtr::from_raw(new) })
        } else {
            None
        }
    }

    /// Take the current content, write it into P then do a CAS to extent this
    /// Atom with the previous contents. This can be used to create a LIFO
    ///
    /// Returns true if this set this migrated the Atom from null.
    pub fn replace_and_set_next(
        &self,
        mut value: P,
        load_order: Ordering,
        cas_order: Ordering,
    ) -> bool
    where
        P: GetNextMut<NextPtr = Option
>,
    {
        let next = value.get_next() as *mut Option
;
        let raw = value.into_raw();
        // If next was set to Some(P) we want to
        // assert that it was droppeds
        unsafe { ptr::drop_in_place(next) };
        loop {
            let pcurrent = self.inner.load(load_order);
            let current = unsafe { Self::inner_from_raw(pcurrent) };
            unsafe { ptr::write(next, current) };
            let last = self.inner.compare_and_swap(pcurrent, raw, cas_order);
            if last == pcurrent {
                return last.is_null();
            }
        }
    }

    /// Check to see if an atom is None
    ///
    /// This only means that the contents was None when it was measured
    pub fn is_none(&self, order: Ordering) -> bool {
        self.inner.load(order).is_null()
    }

    #[inline]
    unsafe fn inner_from_raw(ptr: *mut ()) -> Option
 {
        if !ptr.is_null() {
            Some(FromRawPtr::from_raw(ptr))
        } else {
            None
        }
    }
}

impl
 Drop for Atom

where
    P: IntoRawPtr + FromRawPtr,
{
    fn drop(&mut self) {
        self.take(Ordering::Relaxed);
    }
}

unsafe impl
 Send for Atom

where
    P: IntoRawPtr + FromRawPtr + Send,
{
}
unsafe impl
 Sync for Atom

where
    P: IntoRawPtr + FromRawPtr + Send,
{
}

/// Convert from into a raw pointer
pub trait IntoRawPtr {
    fn into_raw(self) -> *mut ();
}

/// Convert from a raw ptr into a pointer
pub trait FromRawPtr {
    unsafe fn from_raw(ptr: *mut ()) -> Self;
}

impl<T> IntoRawPtr for Box<T> {
    #[inline]
    fn into_raw(self) -> *mut () {
        Box::into_raw(self) as *mut ()
    }
}

impl<T> FromRawPtr for Box<T> {
    #[inline]
    unsafe fn from_raw(ptr: *mut ()) -> Box<T> {
        Box::from_raw(ptr as *mut T)
    }
}

impl<T> IntoRawPtr for Arc<T> {
    #[inline]
    fn into_raw(self) -> *mut () {
        Arc::into_raw(self) as *mut T as *mut ()
    }
}

impl<T> FromRawPtr for Arc<T> {
    #[inline]
    unsafe fn from_raw(ptr: *mut ()) -> Arc<T> {
        Arc::from_raw(ptr as *const () as *const T)
    }
}

// This impl can be useful for stack-allocated and 'static values.
impl<'a, T> IntoRawPtr for &'a T {
    #[inline]
    unsafe fn into_raw(self) -> *mut () {
        self as *const _ as *mut ()
    }
}

impl<'a, T> FromRawPtr for &'a T {
    #[inline]
    unsafe fn from_raw(ptr: *mut ()) -> &'a T {
        &*(ptr as *mut T)
    }
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S, ptr: &T) -> &'a T {
    mem::transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
unsafe fn copy_mut_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S, ptr: &mut T) -> &'a mut T {
    mem::transmute(ptr)
}

/// This is a restricted version of the Atom. It allows for only
/// `set_if_none` to be called.
///
/// `swap` and `take` can be used only with a mutable reference. Meaning
/// that AtomSetOnce is not usable as a
#[derive(Debug)]
pub struct AtomSetOnce

where
    P: IntoRawPtr + FromRawPtr,
{
    inner: Atom
,
}

impl
 AtomSetOnce

where
    P: IntoRawPtr + FromRawPtr,
{
    /// Create an empty `AtomSetOnce`
    pub fn empty() -> AtomSetOnce
 {
        AtomSetOnce {
            inner: Atom::empty(),
        }
    }

    /// Create a new `AtomSetOnce` from Pointer P
    pub fn new(value: P) -> AtomSetOnce
 {
        AtomSetOnce {
            inner: Atom::new(value),
        }
    }

    /// This will do a `CAS` setting the value only if it is NULL
    /// this will return `OK(())` if the value was written,
    /// otherwise a `Err(P)` will be returned, where the value was
    /// the same value that you passed into this function
    pub fn set_if_none(&self, v: P, order: Ordering) -> Option
 {
        self.inner.set_if_none(v, order)
    }

    /// Convert an `AtomSetOnce` into an `Atom`
    pub fn into_atom(self) -> Atom
 {
        self.inner
    }

    /// Allow access to the atom if exclusive access is granted
    pub fn atom(&mut self) -> &mut Atom
 {
        &mut self.inner
    }

    /// Check to see if an atom is None
    ///
    /// This only means that the contents was None when it was measured
    pub fn is_none(&self, order: Ordering) -> bool {
        self.inner.is_none(order)
    }
}

impl<T, P> AtomSetOnce

where
    P: IntoRawPtr + FromRawPtr + Deref<Target = T>,
{
    /// If the Atom is set, get the value
    pub fn get<'a>(&'a self, order: Ordering) -> Option<&'a T> {
        let ptr = self.inner.inner.load(order);
        let val = unsafe { Atom::inner_from_raw(ptr) };
        val.map(|v: P| {
            // This is safe since ptr cannot be changed once it is set
            // which means that this is now a Arc or a Box.
            let out = unsafe { copy_lifetime(self, &*v) };
            mem::forget(v);
            out
        })
    }
}

impl<T> AtomSetOnce<Box<T>> {
    /// If the Atom is set, get the value
    pub fn get_mut<'a>(&'a mut self, order: Ordering) -> Option<&'a mut T> {
        let ptr = self.inner.inner.load(order);
        let val = unsafe { Atom::inner_from_raw(ptr) };
        val.map(move |mut v: Box<T>| {
            // This is safe since ptr cannot be changed once it is set
            // which means that this is now a Arc or a Box.
            let out = unsafe { copy_mut_lifetime(self, &mut *v) };
            mem::forget(v);
            out
        })
    }
}

impl<T> AtomSetOnce<T>
where
    T: Clone + IntoRawPtr + FromRawPtr,
{
    /// Duplicate the inner pointer if it is set
    pub fn dup<'a>(&self, order: Ordering) -> Option<T> {
        let ptr = self.inner.inner.load(order);
        let val = unsafe { Atom::inner_from_raw(ptr) };
        val.map(|v: T| {
            let out = v.clone();
            mem::forget(v);
            out
        })
    }
}

/// This is a utility Trait that fetches the next ptr from
/// an object.
pub trait GetNextMut {
    type NextPtr;
    fn get_next(&mut self) -> &mut Self::NextPtr;
}
<commit_msg>into_raw no longer unsafe<commit_after>//   Copyright 2015 Colin Sherratt
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

use std::cell::UnsafeCell;
use std::fmt::{self, Debug, Formatter};
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::sync::atomic::AtomicPtr;
use std::sync::atomic::Ordering;
use std::sync::Arc;

/// An Atom wraps an AtomicPtr, it allows for safe mutation of an atomic
/// into common Rust Types.
pub struct Atom

where
    P: IntoRawPtr + FromRawPtr,
{
    inner: AtomicPtr<()>,
    data: PhantomData<UnsafeCell
>,
}

impl
 Debug for Atom

where
    P: IntoRawPtr + FromRawPtr,
{
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        write!(f, "atom({:?})", self.inner.load(Ordering::Relaxed))
    }
}

impl
 Atom

where
    P: IntoRawPtr + FromRawPtr,
{
    /// Create a empty Atom
    pub fn empty() -> Atom
 {
        Atom {
            inner: AtomicPtr::new(ptr::null_mut()),
            data: PhantomData,
        }
    }

    /// Create a new Atomic from Pointer P
    pub fn new(value: P) -> Atom
 {
        Atom {
            inner: AtomicPtr::new(value.into_raw()),
            data: PhantomData,
        }
    }

    /// Swap a new value into the Atom, This will try multiple
    /// times until it succeeds. The old value will be returned.
    pub fn swap(&self, v: P, order: Ordering) -> Option
 {
        let new = v.into_raw();
        let old = self.inner.swap(new, order);
        unsafe { Self::inner_from_raw(old) }
    }

    /// Take the value of the Atom replacing it with null pointer
    /// Returning the contents. If the contents was a `null` pointer the
    /// result will be `None`.
    pub fn take(&self, order: Ordering) -> Option
 {
        let old = self.inner.swap(ptr::null_mut(), order);
        unsafe { Self::inner_from_raw(old) }
    }

    /// This will do a `CAS` setting the value only if it is NULL
    /// this will return `None` if the value was written,
    /// otherwise a `Some(v)` will be returned, where the value was
    /// the same value that you passed into this function
    pub fn set_if_none(&self, v: P, order: Ordering) -> Option
 {
        let new = v.into_raw();
        let old = self.inner.compare_and_swap(ptr::null_mut(), new, order);
        if !old.is_null() {
            Some(unsafe { FromRawPtr::from_raw(new) })
        } else {
            None
        }
    }

    /// Take the current content, write it into P then do a CAS to extent this
    /// Atom with the previous contents. This can be used to create a LIFO
    ///
    /// Returns true if this set this migrated the Atom from null.
    pub fn replace_and_set_next(
        &self,
        mut value: P,
        load_order: Ordering,
        cas_order: Ordering,
    ) -> bool
    where
        P: GetNextMut<NextPtr = Option
>,
    {
        let next = value.get_next() as *mut Option
;
        let raw = value.into_raw();
        // If next was set to Some(P) we want to
        // assert that it was droppeds
        unsafe { ptr::drop_in_place(next) };
        loop {
            let pcurrent = self.inner.load(load_order);
            let current = unsafe { Self::inner_from_raw(pcurrent) };
            unsafe { ptr::write(next, current) };
            let last = self.inner.compare_and_swap(pcurrent, raw, cas_order);
            if last == pcurrent {
                return last.is_null();
            }
        }
    }

    /// Check to see if an atom is None
    ///
    /// This only means that the contents was None when it was measured
    pub fn is_none(&self, order: Ordering) -> bool {
        self.inner.load(order).is_null()
    }

    #[inline]
    unsafe fn inner_from_raw(ptr: *mut ()) -> Option
 {
        if !ptr.is_null() {
            Some(FromRawPtr::from_raw(ptr))
        } else {
            None
        }
    }
}

impl
 Drop for Atom

where
    P: IntoRawPtr + FromRawPtr,
{
    fn drop(&mut self) {
        self.take(Ordering::Relaxed);
    }
}

unsafe impl
 Send for Atom

where
    P: IntoRawPtr + FromRawPtr + Send,
{
}
unsafe impl
 Sync for Atom

where
    P: IntoRawPtr + FromRawPtr + Send,
{
}

/// Convert from into a raw pointer
pub trait IntoRawPtr {
    fn into_raw(self) -> *mut ();
}

/// Convert from a raw ptr into a pointer
pub trait FromRawPtr {
    unsafe fn from_raw(ptr: *mut ()) -> Self;
}

impl<T> IntoRawPtr for Box<T> {
    #[inline]
    fn into_raw(self) -> *mut () {
        Box::into_raw(self) as *mut ()
    }
}

impl<T> FromRawPtr for Box<T> {
    #[inline]
    unsafe fn from_raw(ptr: *mut ()) -> Box<T> {
        Box::from_raw(ptr as *mut T)
    }
}

impl<T> IntoRawPtr for Arc<T> {
    #[inline]
    fn into_raw(self) -> *mut () {
        Arc::into_raw(self) as *mut T as *mut ()
    }
}

impl<T> FromRawPtr for Arc<T> {
    #[inline]
    unsafe fn from_raw(ptr: *mut ()) -> Arc<T> {
        Arc::from_raw(ptr as *const () as *const T)
    }
}

// This impl can be useful for stack-allocated and 'static values.
impl<'a, T> IntoRawPtr for &'a T {
    #[inline]
    fn into_raw(self) -> *mut () {
        self as *const _ as *mut ()
    }
}

impl<'a, T> FromRawPtr for &'a T {
    #[inline]
    unsafe fn from_raw(ptr: *mut ()) -> &'a T {
        &*(ptr as *mut T)
    }
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S, ptr: &T) -> &'a T {
    mem::transmute(ptr)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
unsafe fn copy_mut_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S, ptr: &mut T) -> &'a mut T {
    mem::transmute(ptr)
}

/// This is a restricted version of the Atom. It allows for only
/// `set_if_none` to be called.
///
/// `swap` and `take` can be used only with a mutable reference. Meaning
/// that AtomSetOnce is not usable as a
#[derive(Debug)]
pub struct AtomSetOnce

where
    P: IntoRawPtr + FromRawPtr,
{
    inner: Atom
,
}

impl
 AtomSetOnce

where
    P: IntoRawPtr + FromRawPtr,
{
    /// Create an empty `AtomSetOnce`
    pub fn empty() -> AtomSetOnce
 {
        AtomSetOnce {
            inner: Atom::empty(),
        }
    }

    /// Create a new `AtomSetOnce` from Pointer P
    pub fn new(value: P) -> AtomSetOnce
 {
        AtomSetOnce {
            inner: Atom::new(value),
        }
    }

    /// This will do a `CAS` setting the value only if it is NULL
    /// this will return `OK(())` if the value was written,
    /// otherwise a `Err(P)` will be returned, where the value was
    /// the same value that you passed into this function
    pub fn set_if_none(&self, v: P, order: Ordering) -> Option
 {
        self.inner.set_if_none(v, order)
    }

    /// Convert an `AtomSetOnce` into an `Atom`
    pub fn into_atom(self) -> Atom
 {
        self.inner
    }

    /// Allow access to the atom if exclusive access is granted
    pub fn atom(&mut self) -> &mut Atom
 {
        &mut self.inner
    }

    /// Check to see if an atom is None
    ///
    /// This only means that the contents was None when it was measured
    pub fn is_none(&self, order: Ordering) -> bool {
        self.inner.is_none(order)
    }
}

impl<T, P> AtomSetOnce

where
    P: IntoRawPtr + FromRawPtr + Deref<Target = T>,
{
    /// If the Atom is set, get the value
    pub fn get<'a>(&'a self, order: Ordering) -> Option<&'a T> {
        let ptr = self.inner.inner.load(order);
        let val = unsafe { Atom::inner_from_raw(ptr) };
        val.map(|v: P| {
            // This is safe since ptr cannot be changed once it is set
            // which means that this is now a Arc or a Box.
            let out = unsafe { copy_lifetime(self, &*v) };
            mem::forget(v);
            out
        })
    }
}

impl<T> AtomSetOnce<Box<T>> {
    /// If the Atom is set, get the value
    pub fn get_mut<'a>(&'a mut self, order: Ordering) -> Option<&'a mut T> {
        let ptr = self.inner.inner.load(order);
        let val = unsafe { Atom::inner_from_raw(ptr) };
        val.map(move |mut v: Box<T>| {
            // This is safe since ptr cannot be changed once it is set
            // which means that this is now a Arc or a Box.
            let out = unsafe { copy_mut_lifetime(self, &mut *v) };
            mem::forget(v);
            out
        })
    }
}

impl<T> AtomSetOnce<T>
where
    T: Clone + IntoRawPtr + FromRawPtr,
{
    /// Duplicate the inner pointer if it is set
    pub fn dup<'a>(&self, order: Ordering) -> Option<T> {
        let ptr = self.inner.inner.load(order);
        let val = unsafe { Atom::inner_from_raw(ptr) };
        val.map(|v: T| {
            let out = v.clone();
            mem::forget(v);
            out
        })
    }
}

/// This is a utility Trait that fetches the next ptr from
/// an object.
pub trait GetNextMut {
    type NextPtr;
    fn get_next(&mut self) -> &mut Self::NextPtr;
}
<|endoftext|>


<commit_before>//! Send a mouse movement or click event to the system.

pub use platform::{move_mouse, press_mouse, release_mouse, move_click};

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Button {
	Left,
	Right,
	Middle,
}

#[cfg(target_os = "macos")]
mod platform {

}

#[cfg(target_os = "windows")]
mod platform {
	extern crate winapi;
	extern crate "user32-sys" as user32_sys;

	use std::mem::{size_of};
	use self::winapi::{c_int, LONG};
	use self::winapi::{MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_MOVE};
	use self::winapi::{MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP};
	use self::winapi::{MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP};
	use self::winapi::{MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP};
	use self::winapi::{INPUT, LPINPUT, MOUSEINPUT, INPUT_MOUSE};
	use self::winapi::{SM_CXSCREEN, SM_CYSCREEN};
	use self::user32_sys::{SendInput, GetSystemMetrics};

	use super::Button;

	/// Move to pixel (x,y).
	/// WARNING Windows implementation ignores pixels > 65535.
	pub fn move_mouse(x: usize, y: usize) {
		unsafe {
			// Windows absolute is [0, 65536);
			let xf = (((x as u64)*0x10000)/(GetSystemMetrics(SM_CXSCREEN) as u64)) as LONG;
			let yf = (((y as u64)*0x10000)/(GetSystemMetrics(SM_CYSCREEN) as u64)) as LONG;
			SendInput(1, &mut INPUT {
				type_: INPUT_MOUSE,
				union_: MOUSEINPUT {
					dx: xf,
					dy: yf,
					mouseData: 0,
					dwFlags: MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE,
					time: 0,
					dwExtraInfo: 0,
				}
			} as LPINPUT,size_of::<INPUT>() as c_int)
		};
	}

	pub fn press_mouse(b: Button) {
		let flag = match b {
			Button::Left => MOUSEEVENTF_LEFTDOWN,
			Button::Right => MOUSEEVENTF_RIGHTDOWN,
			Button::Middle => MOUSEEVENTF_MIDDLEDOWN,
		};
		unsafe {SendInput(1, &mut INPUT {
			type_: INPUT_MOUSE,
			union_: MOUSEINPUT {
				dx: 0,
				dy: 0,
				mouseData: 0,
				dwFlags: flag,
				time: 0,
				dwExtraInfo: 0,
			}
		} as LPINPUT,size_of::<INPUT>() as c_int)};
	}

	pub fn release_mouse(b: Button) {
		let flag = match b {
			Button::Left => MOUSEEVENTF_LEFTUP,
			Button::Right => MOUSEEVENTF_RIGHTUP,
			Button::Middle => MOUSEEVENTF_MIDDLEUP,
		};
		unsafe {SendInput(1, &mut INPUT {
			type_: INPUT_MOUSE,
			union_: MOUSEINPUT {
				dx: 0,
				dy: 0,
				mouseData: 0,
				dwFlags: flag,
				time: 0,
				dwExtraInfo: 0,
			}
		} as LPINPUT,size_of::<INPUT>() as c_int)};
	}

	pub fn move_click(x: usize, y: usize) {
		move_mouse(x, y);
		press_mouse(Button::Left);
		release_mouse(Button::Left);
	}
}

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

	#[test]
	fn test_move_mouse() {
		move_mouse(640, 480);
	}
}
<commit_msg>Update breakage<commit_after>//! Send a mouse movement or click event to the system.

pub use platform::{move_mouse, press_mouse, release_mouse, move_click};

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Button {
	Left,
	Right,
	Middle,
}

#[cfg(target_os = "macos")]
mod platform {

}

#[cfg(target_os = "windows")]
mod platform {
	extern crate winapi;
	extern crate user32 as user32_sys;

	use std::mem::{size_of};
	use self::winapi::{c_int, LONG};
	use self::winapi::{MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_MOVE};
	use self::winapi::{MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP};
	use self::winapi::{MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP};
	use self::winapi::{MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP};
	use self::winapi::{INPUT, LPINPUT, MOUSEINPUT, INPUT_MOUSE};
	use self::winapi::{SM_CXSCREEN, SM_CYSCREEN};
	use self::user32_sys::{SendInput, GetSystemMetrics};

	use super::Button;

	/// Move to pixel (x,y).
	/// WARNING Windows implementation ignores pixels > 65535.
	pub fn move_mouse(x: usize, y: usize) {
		unsafe {
			// Windows absolute is [0, 65536);
			let xf = (((x as u64)*0x10000)/(GetSystemMetrics(SM_CXSCREEN) as u64)) as LONG;
			let yf = (((y as u64)*0x10000)/(GetSystemMetrics(SM_CYSCREEN) as u64)) as LONG;
			SendInput(1, &mut INPUT {
				type_: INPUT_MOUSE,
				union_: MOUSEINPUT {
					dx: xf,
					dy: yf,
					mouseData: 0,
					dwFlags: MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE,
					time: 0,
					dwExtraInfo: 0,
				}
			} as LPINPUT,size_of::<INPUT>() as c_int)
		};
	}

	pub fn press_mouse(b: Button) {
		let flag = match b {
			Button::Left => MOUSEEVENTF_LEFTDOWN,
			Button::Right => MOUSEEVENTF_RIGHTDOWN,
			Button::Middle => MOUSEEVENTF_MIDDLEDOWN,
		};
		unsafe {SendInput(1, &mut INPUT {
			type_: INPUT_MOUSE,
			union_: MOUSEINPUT {
				dx: 0,
				dy: 0,
				mouseData: 0,
				dwFlags: flag,
				time: 0,
				dwExtraInfo: 0,
			}
		} as LPINPUT,size_of::<INPUT>() as c_int)};
	}

	pub fn release_mouse(b: Button) {
		let flag = match b {
			Button::Left => MOUSEEVENTF_LEFTUP,
			Button::Right => MOUSEEVENTF_RIGHTUP,
			Button::Middle => MOUSEEVENTF_MIDDLEUP,
		};
		unsafe {SendInput(1, &mut INPUT {
			type_: INPUT_MOUSE,
			union_: MOUSEINPUT {
				dx: 0,
				dy: 0,
				mouseData: 0,
				dwFlags: flag,
				time: 0,
				dwExtraInfo: 0,
			}
		} as LPINPUT,size_of::<INPUT>() as c_int)};
	}

	pub fn move_click(x: usize, y: usize) {
		move_mouse(x, y);
		press_mouse(Button::Left);
		release_mouse(Button::Left);
	}
}

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

	#[test]
	fn test_move_mouse() {
		move_mouse(640, 480);
	}
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A Gfx texture representation that works nicely with Piston libraries.

extern crate gfx;
extern crate texture as texture_lib;
extern crate image;

pub use texture_lib::ImageSize;
pub use texture::Texture;

mod texture;

/// Texture creation parameters.
pub struct Settings {
    /// Sometimes you need the other way around.
    pub flip_vertical: bool,
    /// Treat as sRGB space.
    pub convert_gamma: bool,
    /// Compress on GPU.
    pub compress: bool,
    /// Generate mipmap chain.
    pub generate_mipmap: bool,
}

impl Settings {
    /// Create default settings.
    pub fn new() -> Settings {
        Settings {
            flip_vertical: false,
            convert_gamma: false,
            compress: false,
            generate_mipmap: false,
        }
    }
}
<commit_msg>Added builder methods<commit_after>#![deny(missing_docs)]

//! A Gfx texture representation that works nicely with Piston libraries.

extern crate gfx;
extern crate texture as texture_lib;
extern crate image;

pub use texture_lib::ImageSize;
pub use texture::Texture;

mod texture;

/// Texture creation parameters.
pub struct Settings {
    flip_vertical: bool,
    convert_gamma: bool,
    /// Compress on GPU.
    compress: bool,
    /// Generate mipmap chain.
    generate_mipmap: bool,
}

impl Settings {
    /// Create default settings.
    pub fn new() -> Settings {
        Settings {
            flip_vertical: false,
            convert_gamma: false,
            compress: false,
            generate_mipmap: false,
        }
    }

    /// Gets whether to flip vertical.
    pub fn get_flip_vertical(&self) -> bool { self.flip_vertical }
    /// Sets flip vertical.
    pub fn set_flip_vertical(&mut self, val: bool) { self.flip_vertical = val; }
    /// Sets flip vertical.
    pub fn flip_vertical(mut self, val: bool) -> Self {
        self.set_flip_vertical(val);
        self
    }

    /// Gets wheter to convert gamma, treated as sRGB color space.
    pub fn get_convert_gamma(&self) -> bool { self.convert_gamma }
    /// Sets convert gamma.
    pub fn set_convert_gamma(&mut self, val: bool) { self.convert_gamma = val; }
    /// Sets convert gamma.
    pub fn convert_gamma(mut self, val: bool) -> Self {
        self.set_convert_gamma(val);
        self
    }

    /// Gets wheter compress on the GPU.
    pub fn get_compress(&self) -> bool { self.compress }
    /// Sets compress.
    pub fn set_compress(&mut self, val: bool) { self.compress = val; }
    /// Sets compress.
    pub fn compress(mut self, val: bool) -> Self {
        self.set_compress(val);
        self
    }

    /// Gets generate mipmap.
    pub fn get_generate_mipmap(&self) -> bool { self.generate_mipmap }
    /// Sets generate mipmap.
    pub fn set_generate_mipmap(&mut self, val: bool) {
        self.generate_mipmap = val;
    }
    /// Sets generate mipmap.
    pub fn generate_mipmap(mut self, val: bool) -> Self {
        self.set_generate_mipmap(val);
        self
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # LLDB
//!
//! This crate provides a safe binding to the public API for [LLDB], the
//! debugger provided by the [LLVM project]. LLDB provides a modern, high
//! performance debugger framework and is the default debugger for macOS
//! and iOS.
//!
//! ## Installation
//!
//! This crate works with Cargo and is on [crates.io].
//! Add it to your `Cargo.toml` like so:
//!
//! ```toml
//! lldb = "0.0.8"
//! ```
//!
//! ### macOS Installation Notes
//!
//! On macOS, this library relies upon being able to find
//! the `LLDB.framework` that is provided by Xcode.app.
//!
//! In your own application, you will need to configure the
//! `@rpath` for your executable to point to the location
//! of the `LLDB.framework` that you are using. Doing this
//! automatically is not currently supported by Cargo.
//!
//! For testing, you can use the version provided by
//! Xcode.app by setting an environment variable:
//!
//! ```shell
//! export DYLD_FRAMEWORK_PATH=/Applications/Xcode.app/Contents/SharedFrameworks
//! ```
//!
//! ### Linux Installation Notes
//!
//! Install the `lldb` and `lldb-dev` packages for your platform so that
//! you have both LLDB itself installed as well as the headers and
//! other support files required.
//!
//! ### Windows Installation Notes
//!
//! Support for building this has not yet been provided for Windows.
//! Contributions are welcome!
//!
//! ## Usage
//!
//! The primary entry point is [`SBDebugger`]. This will be how you
//! create a debug target and begin the actually interesting stuff.
//!
//! ## Important Classes
//!
//! The LLDB API provides many structs and a wide range of functionality. Some of the
//! most common usages will involve these structs and their corresponding methods:
//!
//! * [`SBDebugger`]: Manages the entire debug experience and creates [`SBTarget`]s.
//! * [`SBTarget`]: The target program running under the debugger.
//! * [`SBProcess`]: The process associated with the target program.
//! * [`SBThread`]: A thread of execution. [`SBProcess`] contains
//!   [`SBThread`]s.
//! * [`SBFrame`]: One of the stack frames associated with
//!   a thread. [`SBThread`] contains [`SBFrame`]s.
//! * [`SBSymbolContext`]: A container that stores various debugger
//!   related info.
//! * [`SBValue`]: The value of a variable, a register, or an
//!   expression.
//! * [`SBModule`]: An executable image and its associated object
//!   and symbol files.  [`SBTarget`] contains [`SBModule`]s.
//! * [`SBBreakpoint`]: A logical breakpoint and its associated
//!   settings. [`SBTarget`] contains [`SBBreakpoint`]s.
//! * [`SBSymbol`]: The symbol possibly associated with a stack frame.
//! * [`SBCompileUnit`]: A compilation unit, or compiled source file.
//! * [`SBFunction`]: A generic function, which can be inlined or not.
//! * [`SBBlock`]: A lexical block. [`SBFunction`] contains [`SBBlock`]s.
//! * [`SBLineEntry`]: Specifies an association with a contiguous range of
//!   instructions and a source file location. [`SBCompileUnit`] contains
//!   [`SBLineEntry`]s.
//!
//! ## Support and Maintenance
//!
//! I am developing this library largely on my own so far. I am able
//! to offer support and maintenance, but would very much appreciate
//! donations via [Patreon](https://patreon.com/endoli). I can also
//! provide commercial support, so feel free to
//! [contact me](mailto:bruce.mitchener@gmail.com).
//!
//! [LLDB]: https://lldb.llvm.org/
//! [LLVM project]: https://llvm.org/
//! [crates.io]: https://crates.io/crates/lldb
//! [`SBDebugger`]: struct.SBDebugger.html
//! [`SBTarget`]: struct.SBTarget.html
//! [`SBProcess`]: struct.SBProcess.html
//! [`SBThread`]: struct.SBThread.html
//! [`SBFrame`]: struct.SBFrame.html
//! [`SBSymbolContext`]: struct.SBSymbolContext.html
//! [`SBValue`]: struct.SBValue.html
//! [`SBModule`]: struct.SBModule.html
//! [`SBBreakpoint`]: struct.SBBreakpoint.html
//! [`SBSymbol`]: struct.SBSymbol.html
//! [`SBCompileUnit`]: struct.SBCompileUnit.html
//! [`SBFunction`]: struct.SBFunction.html
//! [`SBBlock`]: struct.SBBlock.html
//! [`SBLineEntry`]: struct.SBLineEntry.html

#![warn(missing_docs)]
#![deny(
    trivial_numeric_casts,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]

extern crate lldb_sys as sys;

#[cfg(feature = "graphql")]
#[macro_use]
extern crate juniper;

pub use sys::{lldb_addr_t, lldb_offset_t, lldb_pid_t, lldb_tid_t, lldb_user_id_t};

pub use sys::{
    AccessType, BasicType, BreakpointEventType, ByteOrder, CommandArgumentType, CommandFlags,
    ConnectionStatus, DescriptionLevel, DynamicValueType, EmulateInstructionOptions, Encoding,
    ErrorType, ExpressionEvaluationPhase, ExpressionResults, FilePermissions, Format,
    FrameComparison, FunctionNameType, GdbSignal, InputReaderAction, InputReaderGranularity,
    InstrumentationRuntimeType, LanguageType, LaunchFlags, MatchType, MemberFunctionKind, PathType,
    Permissions, QueueItemKind, QueueKind, RegisterKind, ReturnStatus, RunMode, ScriptLanguage,
    SectionType, StateType, StopReason, SymbolContextItem, SymbolType, TemplateArgumentKind,
    TypeClass, TypeFlags, TypeOptions, TypeSummaryCapping, ValueType, WatchpointEventType,
    WatchpointKind,
};

mod address;
mod attachinfo;
mod block;
mod breakpoint;
mod breakpointlist;
mod breakpointlocation;
mod broadcaster;
mod commandinterpreter;
mod compileunit;
mod data;
mod debugger;
mod error;
mod event;
mod expressionoptions;
mod filespec;
mod filespeclist;
mod frame;
mod function;
mod instruction;
mod instructionlist;
mod launchinfo;
mod lineentry;
mod listener;
mod module;
mod modulespec;
mod platform;
mod process;
mod processinfo;
mod queue;
mod queueitem;
mod section;
mod stream;
mod stringlist;
mod structureddata;
mod symbol;
mod symbolcontext;
mod symbolcontextlist;
mod target;
mod thread;
mod typelist;
mod types;
mod value;
mod valuelist;
mod variablesoptions;
mod watchpoint;

pub use self::address::SBAddress;
pub use self::attachinfo::SBAttachInfo;
pub use self::block::SBBlock;
pub use self::breakpoint::{SBBreakpoint, SBBreakpointLocationIter};
pub use self::breakpointlist::{SBBreakpointList, SBBreakpointListIter};
pub use self::breakpointlocation::SBBreakpointLocation;
pub use self::broadcaster::SBBroadcaster;
pub use self::commandinterpreter::SBCommandInterpreter;
pub use self::compileunit::SBCompileUnit;
pub use self::data::SBData;
pub use self::debugger::{SBDebugger, SBDebuggerTargetIter};
pub use self::error::SBError;
pub use self::event::SBEvent;
pub use self::expressionoptions::SBExpressionOptions;
pub use self::filespec::SBFileSpec;
pub use self::filespeclist::{SBFileSpecList, SBFileSpecListIter};
pub use self::frame::SBFrame;
pub use self::function::SBFunction;
pub use self::instruction::SBInstruction;
pub use self::instructionlist::{SBInstructionList, SBInstructionListIter};
pub use self::launchinfo::SBLaunchInfo;
pub use self::lineentry::SBLineEntry;
pub use self::listener::SBListener;
pub use self::module::{SBModule, SBModuleSectionIter};
pub use self::modulespec::SBModuleSpec;
pub use self::platform::SBPlatform;
pub use self::process::{
    SBProcess, SBProcessEvent, SBProcessEventRestartedReasonIter, SBProcessQueueIter,
    SBProcessThreadIter,
};
pub use self::processinfo::SBProcessInfo;
pub use self::queue::{SBQueue, SBQueueQueueItemIter, SBQueueThreadIter};
pub use self::queueitem::SBQueueItem;
pub use self::section::{SBSection, SBSectionSubSectionIter};
pub use self::stream::SBStream;
pub use self::stringlist::{SBStringList, SBStringListIter};
pub use self::structureddata::SBStructuredData;
pub use self::symbol::SBSymbol;
pub use self::symbolcontext::SBSymbolContext;
pub use self::symbolcontextlist::SBSymbolContextList;
pub use self::target::{
    SBTarget, SBTargetBreakpointIter, SBTargetEvent, SBTargetEventModuleIter, SBTargetModuleIter,
    SBTargetWatchpointIter,
};
pub use self::thread::{SBThread, SBThreadEvent, SBThreadFrameIter};
pub use self::typelist::{SBTypeList, SBTypeListIter};
pub use self::types::SBType;
pub use self::value::SBValue;
pub use self::valuelist::{SBValueList, SBValueListIter};
pub use self::variablesoptions::SBVariablesOptions;
pub use self::watchpoint::SBWatchpoint;

/// Which syntax should be used in disassembly?
///
/// On x86, there are 2 syntaxes used for disassembly. Other
/// architectures need not be concerned by this and can just
/// use `DisassemblyFlavor::Default` all the time.
#[derive(Clone, Copy, Debug)]
pub enum DisassemblyFlavor {
    /// The primary syntax used by the GNU Assembler and in the
    /// Linux world.
    ///
    /// AT&T syntax:
    ///
    /// * Operations has a suffix, indicating the operand size.
    /// * Prefixes registers with `%` and immediate values with `$`.
    /// * Orders operands with source first, then destination.
    /// * Memory operands are somewhat complicated.
    ///
    /// For example:
    ///
    /// ```asm
    /// movb $0x05, %al
    /// ```
    ///
    /// This syntax is described in detail in [GAS Syntax].
    ///
    /// [GAS Syntax]: https://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax
    ATT,
    /// The default syntax.
    Default,
    /// The primary syntax used on Windows.
    ///
    /// This differs from AT&T syntax in that:
    ///
    /// * Operations are not suffixed.
    /// * Registers are not prefixed with `%`, immediate values have a suffix.
    /// * Operands are ordered so that the destination is first, then the source.
    ///
    /// For example:
    ///
    /// ```asm
    /// mov al, 05h
    /// ```
    ///
    Intel,
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<commit_msg>clippy: Allow upper case acronyms. We mirror an existing API.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # LLDB
//!
//! This crate provides a safe binding to the public API for [LLDB], the
//! debugger provided by the [LLVM project]. LLDB provides a modern, high
//! performance debugger framework and is the default debugger for macOS
//! and iOS.
//!
//! ## Installation
//!
//! This crate works with Cargo and is on [crates.io].
//! Add it to your `Cargo.toml` like so:
//!
//! ```toml
//! lldb = "0.0.8"
//! ```
//!
//! ### macOS Installation Notes
//!
//! On macOS, this library relies upon being able to find
//! the `LLDB.framework` that is provided by Xcode.app.
//!
//! In your own application, you will need to configure the
//! `@rpath` for your executable to point to the location
//! of the `LLDB.framework` that you are using. Doing this
//! automatically is not currently supported by Cargo.
//!
//! For testing, you can use the version provided by
//! Xcode.app by setting an environment variable:
//!
//! ```shell
//! export DYLD_FRAMEWORK_PATH=/Applications/Xcode.app/Contents/SharedFrameworks
//! ```
//!
//! ### Linux Installation Notes
//!
//! Install the `lldb` and `lldb-dev` packages for your platform so that
//! you have both LLDB itself installed as well as the headers and
//! other support files required.
//!
//! ### Windows Installation Notes
//!
//! Support for building this has not yet been provided for Windows.
//! Contributions are welcome!
//!
//! ## Usage
//!
//! The primary entry point is [`SBDebugger`]. This will be how you
//! create a debug target and begin the actually interesting stuff.
//!
//! ## Important Classes
//!
//! The LLDB API provides many structs and a wide range of functionality. Some of the
//! most common usages will involve these structs and their corresponding methods:
//!
//! * [`SBDebugger`]: Manages the entire debug experience and creates [`SBTarget`]s.
//! * [`SBTarget`]: The target program running under the debugger.
//! * [`SBProcess`]: The process associated with the target program.
//! * [`SBThread`]: A thread of execution. [`SBProcess`] contains
//!   [`SBThread`]s.
//! * [`SBFrame`]: One of the stack frames associated with
//!   a thread. [`SBThread`] contains [`SBFrame`]s.
//! * [`SBSymbolContext`]: A container that stores various debugger
//!   related info.
//! * [`SBValue`]: The value of a variable, a register, or an
//!   expression.
//! * [`SBModule`]: An executable image and its associated object
//!   and symbol files.  [`SBTarget`] contains [`SBModule`]s.
//! * [`SBBreakpoint`]: A logical breakpoint and its associated
//!   settings. [`SBTarget`] contains [`SBBreakpoint`]s.
//! * [`SBSymbol`]: The symbol possibly associated with a stack frame.
//! * [`SBCompileUnit`]: A compilation unit, or compiled source file.
//! * [`SBFunction`]: A generic function, which can be inlined or not.
//! * [`SBBlock`]: A lexical block. [`SBFunction`] contains [`SBBlock`]s.
//! * [`SBLineEntry`]: Specifies an association with a contiguous range of
//!   instructions and a source file location. [`SBCompileUnit`] contains
//!   [`SBLineEntry`]s.
//!
//! ## Support and Maintenance
//!
//! I am developing this library largely on my own so far. I am able
//! to offer support and maintenance, but would very much appreciate
//! donations via [Patreon](https://patreon.com/endoli). I can also
//! provide commercial support, so feel free to
//! [contact me](mailto:bruce.mitchener@gmail.com).
//!
//! [LLDB]: https://lldb.llvm.org/
//! [LLVM project]: https://llvm.org/
//! [crates.io]: https://crates.io/crates/lldb
//! [`SBDebugger`]: struct.SBDebugger.html
//! [`SBTarget`]: struct.SBTarget.html
//! [`SBProcess`]: struct.SBProcess.html
//! [`SBThread`]: struct.SBThread.html
//! [`SBFrame`]: struct.SBFrame.html
//! [`SBSymbolContext`]: struct.SBSymbolContext.html
//! [`SBValue`]: struct.SBValue.html
//! [`SBModule`]: struct.SBModule.html
//! [`SBBreakpoint`]: struct.SBBreakpoint.html
//! [`SBSymbol`]: struct.SBSymbol.html
//! [`SBCompileUnit`]: struct.SBCompileUnit.html
//! [`SBFunction`]: struct.SBFunction.html
//! [`SBBlock`]: struct.SBBlock.html
//! [`SBLineEntry`]: struct.SBLineEntry.html

#![allow(clippy::upper_case_acronyms)]
#![warn(missing_docs)]
#![deny(
    trivial_numeric_casts,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]

extern crate lldb_sys as sys;

#[cfg(feature = "graphql")]
#[macro_use]
extern crate juniper;

pub use sys::{lldb_addr_t, lldb_offset_t, lldb_pid_t, lldb_tid_t, lldb_user_id_t};

pub use sys::{
    AccessType, BasicType, BreakpointEventType, ByteOrder, CommandArgumentType, CommandFlags,
    ConnectionStatus, DescriptionLevel, DynamicValueType, EmulateInstructionOptions, Encoding,
    ErrorType, ExpressionEvaluationPhase, ExpressionResults, FilePermissions, Format,
    FrameComparison, FunctionNameType, GdbSignal, InputReaderAction, InputReaderGranularity,
    InstrumentationRuntimeType, LanguageType, LaunchFlags, MatchType, MemberFunctionKind, PathType,
    Permissions, QueueItemKind, QueueKind, RegisterKind, ReturnStatus, RunMode, ScriptLanguage,
    SectionType, StateType, StopReason, SymbolContextItem, SymbolType, TemplateArgumentKind,
    TypeClass, TypeFlags, TypeOptions, TypeSummaryCapping, ValueType, WatchpointEventType,
    WatchpointKind,
};

mod address;
mod attachinfo;
mod block;
mod breakpoint;
mod breakpointlist;
mod breakpointlocation;
mod broadcaster;
mod commandinterpreter;
mod compileunit;
mod data;
mod debugger;
mod error;
mod event;
mod expressionoptions;
mod filespec;
mod filespeclist;
mod frame;
mod function;
mod instruction;
mod instructionlist;
mod launchinfo;
mod lineentry;
mod listener;
mod module;
mod modulespec;
mod platform;
mod process;
mod processinfo;
mod queue;
mod queueitem;
mod section;
mod stream;
mod stringlist;
mod structureddata;
mod symbol;
mod symbolcontext;
mod symbolcontextlist;
mod target;
mod thread;
mod typelist;
mod types;
mod value;
mod valuelist;
mod variablesoptions;
mod watchpoint;

pub use self::address::SBAddress;
pub use self::attachinfo::SBAttachInfo;
pub use self::block::SBBlock;
pub use self::breakpoint::{SBBreakpoint, SBBreakpointLocationIter};
pub use self::breakpointlist::{SBBreakpointList, SBBreakpointListIter};
pub use self::breakpointlocation::SBBreakpointLocation;
pub use self::broadcaster::SBBroadcaster;
pub use self::commandinterpreter::SBCommandInterpreter;
pub use self::compileunit::SBCompileUnit;
pub use self::data::SBData;
pub use self::debugger::{SBDebugger, SBDebuggerTargetIter};
pub use self::error::SBError;
pub use self::event::SBEvent;
pub use self::expressionoptions::SBExpressionOptions;
pub use self::filespec::SBFileSpec;
pub use self::filespeclist::{SBFileSpecList, SBFileSpecListIter};
pub use self::frame::SBFrame;
pub use self::function::SBFunction;
pub use self::instruction::SBInstruction;
pub use self::instructionlist::{SBInstructionList, SBInstructionListIter};
pub use self::launchinfo::SBLaunchInfo;
pub use self::lineentry::SBLineEntry;
pub use self::listener::SBListener;
pub use self::module::{SBModule, SBModuleSectionIter};
pub use self::modulespec::SBModuleSpec;
pub use self::platform::SBPlatform;
pub use self::process::{
    SBProcess, SBProcessEvent, SBProcessEventRestartedReasonIter, SBProcessQueueIter,
    SBProcessThreadIter,
};
pub use self::processinfo::SBProcessInfo;
pub use self::queue::{SBQueue, SBQueueQueueItemIter, SBQueueThreadIter};
pub use self::queueitem::SBQueueItem;
pub use self::section::{SBSection, SBSectionSubSectionIter};
pub use self::stream::SBStream;
pub use self::stringlist::{SBStringList, SBStringListIter};
pub use self::structureddata::SBStructuredData;
pub use self::symbol::SBSymbol;
pub use self::symbolcontext::SBSymbolContext;
pub use self::symbolcontextlist::SBSymbolContextList;
pub use self::target::{
    SBTarget, SBTargetBreakpointIter, SBTargetEvent, SBTargetEventModuleIter, SBTargetModuleIter,
    SBTargetWatchpointIter,
};
pub use self::thread::{SBThread, SBThreadEvent, SBThreadFrameIter};
pub use self::typelist::{SBTypeList, SBTypeListIter};
pub use self::types::SBType;
pub use self::value::SBValue;
pub use self::valuelist::{SBValueList, SBValueListIter};
pub use self::variablesoptions::SBVariablesOptions;
pub use self::watchpoint::SBWatchpoint;

/// Which syntax should be used in disassembly?
///
/// On x86, there are 2 syntaxes used for disassembly. Other
/// architectures need not be concerned by this and can just
/// use `DisassemblyFlavor::Default` all the time.
#[derive(Clone, Copy, Debug)]
pub enum DisassemblyFlavor {
    /// The primary syntax used by the GNU Assembler and in the
    /// Linux world.
    ///
    /// AT&T syntax:
    ///
    /// * Operations has a suffix, indicating the operand size.
    /// * Prefixes registers with `%` and immediate values with `$`.
    /// * Orders operands with source first, then destination.
    /// * Memory operands are somewhat complicated.
    ///
    /// For example:
    ///
    /// ```asm
    /// movb $0x05, %al
    /// ```
    ///
    /// This syntax is described in detail in [GAS Syntax].
    ///
    /// [GAS Syntax]: https://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax
    ATT,
    /// The default syntax.
    Default,
    /// The primary syntax used on Windows.
    ///
    /// This differs from AT&T syntax in that:
    ///
    /// * Operations are not suffixed.
    /// * Registers are not prefixed with `%`, immediate values have a suffix.
    /// * Operands are ordered so that the destination is first, then the source.
    ///
    /// For example:
    ///
    /// ```asm
    /// mov al, 05h
    /// ```
    ///
    Intel,
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {}
}
<|endoftext|>


<commit_before>
pub fn puzzle(input: &str) -> u32 {
    let initial_world_state = WorldState {
        steps: 0,
        elevator_floor: 0,
    };
    let mut queue = vec![initial_world_state];
    while !queue.is_empty() {
        let world = queue.remove(0);
        if world.in_end_state() {
            return world.steps;
        }

    }

    panic!("Exhausted all possible moves without finding end condition!");

}

pub struct WorldState {
    steps: u32,
    elevator_floor: usize,
}

impl WorldState {
    pub fn in_end_state(&self) -> bool {
        true
    }
}

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

}
<commit_msg>Add a method skeleton for finding next moves and adding to queue<commit_after>
pub fn puzzle(input: &str) -> u32 {
    let initial_world_state = WorldState {
        steps: 0,
        elevator_floor: 0,
    };
    let mut queue = vec![initial_world_state];
    while !queue.is_empty() {
        let world = queue.remove(0);
        if world.in_end_state() {
            return world.steps;
        }

        let mut valid_next_moves = world.next_moves();
        queue.append(&mut valid_next_moves);
    }

    panic!("Exhausted all possible moves without finding end condition!");

}

pub struct WorldState {
    steps: u32,
    elevator_floor: usize,
}

impl WorldState {
    pub fn in_end_state(&self) -> bool {
        true
    }

    pub fn next_moves(&self) -> Vec<WorldState> {
        vec![]
    }
}

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

}
<|endoftext|>


<commit_before>//! Testing and benchmarking tools for concurrent Rust code
//!
//! This crate groups together a bunch of utilities which I've found useful when
//! testing and benchmarking Rust concurrency primitives in the triple_buffer
//! and spmc_buffer crates.
//!
//! If it proves popular, other testing and benchmarking tools may be added,
//! based on user demand.
//!
//! # Examples
//!
//! For examples of this crate at work, look at its "tests" and "benchs"
//! submodules, which showcase expected usage.

#![deny(missing_docs)]

pub mod race_cell;

use std::{
    sync::{
        Arc,
        atomic::{AtomicBool, Ordering},
        Barrier,
    },
    thread,
    time::{Duration, Instant},
};

/// Test that running two operations concurrently works
///
/// When testing multi-threaded constructs, such as synchronization primitives,
/// checking that the code works when run sequentially is insufficient.
/// Concurrent interactions must also be tested, by running some operations
/// in parallel across multiple threads.
///
/// Ideally, this function would take as input a variable-size set of functors
/// to be run in parallel. Since Rust does not support variadic generics yet,
/// however, multiple versions of this function must be provided, each
/// associated with a different functor tuple size.
///
pub fn concurrent_test_2<F, G>(f1: F, f2: G)
    where F: FnOnce() + Send + 'static,
          G: FnOnce() + Send + 'static
{
    // Setup a barrier to synchronize thread startup
    let barrier1 = Arc::new(Barrier::new(2));
    let barrier2 = barrier1.clone();

    // Start the first task
    let thread1 = thread::spawn(move || {
        barrier1.wait();
        f1();
    });

    // Run the second task
    barrier2.wait();
    f2();

    // Make sure that the first task completed properly
    thread1.join().unwrap();
}

/// Test that running three operations concurrently works
///
/// This is a variant of concurrent_test_2 that works with three functors
/// instead of two. It is hoped that future evolutions of Rust will render this
/// (light) code duplication obsolete, in favor of some variadic design.
///
pub fn concurrent_test_3<F, G, H>(f1: F, f2: G, f3: H)
    where F: FnOnce() + Send + 'static,
          G: FnOnce() + Send + 'static,
          H: FnOnce() + Send + 'static
{
    // Setup a barrier to synchronize thread startup
    let barrier1 = Arc::new(Barrier::new(3));
    let barrier2 = barrier1.clone();
    let barrier3 = barrier1.clone();

    // Start the first task
    let thread1 = thread::spawn(move || {
        barrier1.wait();
        f1();
    });

    // Start the second task
    let thread2 = thread::spawn(move || {
        barrier2.wait();
        f2();
    });

    // Run the third task
    barrier3.wait();
    f3();

    // Make sure that the first two tasks completed properly
    thread1.join().unwrap();
    thread2.join().unwrap();
}

/// Microbenchmark some simple operation by running it N times
///
/// This simple benchmark harness is meant as a cheap and hackish substitute for
/// cargo benchmarks in Stable Rust. It runs a user-provided operation a certain
/// number of times and measures how much time it takes.
///
/// To use it, write your benchmark as an ignored cargo test, put a call to
/// benchmark() or counting_benchmark() as the last operation, and tell your
/// user to run the benchmarks via:
///
///   $ cargo test --release -- --ignored --nocapture --test-threads=1
///
/// This is a dreadful hack. But for now, it's the best that I've thought of.
///
pub fn benchmark<F: FnMut()>(num_iterations: u32, mut iteration: F) {
    // Run the user-provided operation in a loop
    let start_time = Instant::now();
    for _ in 0..num_iterations {
        iteration()
    }
    let total_duration = start_time.elapsed();

    // Reproducible benchmarks (<10% variance) usually take between a couple of
    // seconds and a couple of minutes, so miliseconds are the right timing unit
    // for the duration of the whole benchmark.
    let total_ms = (total_duration.as_secs() as u32) * 1000 +
                   total_duration.subsec_nanos() / 1_000_000;

    // This tool is designed for microbenchmarking, so iterations are assumed
    // to last from one CPU cycle (a fraction of a nanosecond) to a fraction of
    // a second. Longer durations will require multi-resolution formatting.
    let hundred_iter_duration = total_duration * 100 / num_iterations;
    let iter_duration = hundred_iter_duration / 100;
    assert_eq!(iter_duration.as_secs(), 0);
    let iter_ns = iter_duration.subsec_nanos();
    let iter_ns_fraction = hundred_iter_duration.subsec_nanos() % 100;

    // Display the benchmark results, in a fashion that will fit in the output
    // of cargo test in nocapture mode.
    print!("{} ms ({} iters, ~{}.{} ns/iter): ",
           total_ms,
           num_iterations,
           iter_ns,
           iter_ns_fraction);
}

/// Microbenchmark some operation while another is running in a loop
///
/// For multithreaded code, benchmarking the performance of isolated operations
/// is usually only half of the story. Synchronization and memory contention can
/// also have a large impact on performance.
///
/// For this reason, it is often useful to also measure the performance of one
/// operation as another "antagonist" operation is also running in a background
/// thread. This function implements such concurrent benchmarking.
///
pub fn concurrent_benchmark<F, A>(num_iterations: u32,
                                  iteration_func: F,
                                  mut antagonist_func: A)
    where F: FnMut(),
          A: FnMut() + Send + 'static
{
    // Setup a barrier to synchronize benchmark and antagonist startup
    let barrier = Arc::new(Barrier::new(2));

    // Setup an atomic "continue" flag to shut down the antagonist at
    // the end of the benchmarking procedure
    let run_flag = Arc::new(AtomicBool::new(true));

    // Schedule the antagonist thread
    let (a_barrier, a_run_flag) = (barrier.clone(), run_flag.clone());
    let antagonist = thread::spawn(
        move || {
            a_barrier.wait();
            while a_run_flag.load(Ordering::Relaxed) {
                antagonist_func();
            }
        }
    );

    // Wait for the antagonist to be running, and give it some headstart
    barrier.wait();
    thread::sleep(Duration::from_millis(10));

    // Run the benchmark
    benchmark(num_iterations, iteration_func);

    // Stop the antagonist and check that nothing went wrong on its side
    run_flag.store(false, Ordering::Relaxed);
    antagonist.join().unwrap();
}

/// Examples of concurrent testing code
#[cfg(test)]
mod tests {
    use std::sync::{
        Arc,
        atomic::{AtomicUsize, Ordering},
    };

    // Check the behaviour of concurrent atomic swaps and fetch-adds
    #[test]
    fn swap_and_fetch_add() {
        // Amount of atomic operations to check
        const ATOMIC_OPS_COUNT: usize = 100_000_000;

        // Create a shared atomic variable
        let atom = Arc::new(AtomicUsize::new(0));
        let atom2 = atom.clone();

        // Check that concurrent atomic operations work correctly
        let mut last_value = 0;
        ::concurrent_test_2(
            move || {
                // One thread continuously increments the atomic variable...
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let former_atom = atom.fetch_add(1, Ordering::Relaxed);
                    assert!((former_atom == 0) || (former_atom == last_value));
                    last_value = former_atom+1;
                }
            },
            move || {
                // ...as another continuously resets it to zero
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let former_atom = atom2.swap(0, Ordering::Relaxed);
                    assert!(former_atom <= ATOMIC_OPS_COUNT);
                }
            }
        );
    }

    // Check the behaviour of concurrent fetch-and/or/xors
    #[test]
    fn fetch_and_or_xor() {
        // Amount of atomic operations to check
        const ATOMIC_OPS_COUNT: usize = 30_000_000;

        // Create a shared atomic variable. Even though this is an atomic Usize,
        // we will only use the 16 low-order bits for maximal portability.
        let atom = Arc::new(AtomicUsize::new(0));
        let atom2 = atom.clone();
        let atom3 = atom.clone();

        // Masks used by each atomic operation
        const AND_MASK: usize = 0b0000_0000_0000_0000; // Clear all bits
        const XOR_MASK: usize = 0b0000_1111_0000_1111; // Flip some bits
        const OR_MASK: usize  = 0b1111_0000_1111_0000; // Set other bits

        // Check that concurrent atomic operations work correctly by ensuring
        // that at any point in time, only the 16 low-order bits can be set, and
        // the grouped sets of bits in the masks above are either all set or
        // all cleared in any observable state.
        ::concurrent_test_3(
            move || {
                // One thread runs fetch-ands in a loop...
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let old_val = atom.fetch_and(AND_MASK, Ordering::Relaxed);
                    assert_eq!(old_val.bitand(0b1111_1111_1111_1111), old_val);
                    assert!((old_val.bitand(XOR_MASK) == XOR_MASK) ||
                            (old_val.bitand(XOR_MASK) == 0));
                    assert!((old_val.bitand(OR_MASK) == OR_MASK) ||
                            (old_val.bitand(OR_MASK) == 0));
                }
            },
            move || {
                // ...another runs fetch-ors in a loop...
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let old_val = atom2.fetch_or(OR_MASK, Ordering::Relaxed);
                    assert_eq!(old_val.bitand(0b1111_1111_1111_1111), old_val);
                    assert!((old_val.bitand(XOR_MASK) == XOR_MASK) ||
                            (old_val.bitand(XOR_MASK) == 0));
                    assert!((old_val.bitand(OR_MASK) == OR_MASK) ||
                            (old_val.bitand(OR_MASK) == 0));
                }
            },
            move || {
                // ...and the last one runs fetch-xors in a loop...
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let old_val = atom3.fetch_xor(XOR_MASK, Ordering::Relaxed);
                    assert_eq!(old_val.bitand(0b1111_1111_1111_1111), old_val);
                    assert!((old_val.bitand(XOR_MASK) == XOR_MASK) ||
                            (old_val.bitand(XOR_MASK) == 0));
                    assert!((old_val.bitand(OR_MASK) == OR_MASK) ||
                            (old_val.bitand(OR_MASK) == 0));
                }
            }
        );
    }
}

/// Exemples of benchmarking code
///
/// As discussed before, these should be run via the following command:
///
///   $ cargo test --release -- --ignored --nocapture --test-threads=1
#[cfg(test)]
mod benchs {
    use std::sync::{
        Arc,
        atomic::{AtomicUsize, Ordering},
    };

    // Benchmark relaxed atomics in sequential code (best case)
    #[test]
    #[ignore]
    fn bench_relaxed() {
        let atom = AtomicUsize::new(0);
        ::benchmark(500_000_000, || { atom.fetch_add(1, Ordering::Relaxed); });
        assert_eq!(atom.load(Ordering::Relaxed), 500_000_000);
    }

    // Benchmark sequentially consistent atomics in concurrent code (worst case)
    #[test]
    #[ignore]
    fn bench_seqcst() {
        let atom = Arc::new(AtomicUsize::new(0));
        let atom2 = atom.clone();
        ::concurrent_benchmark(
            100_000_000,
            move || { atom.fetch_add(1, Ordering::SeqCst); },
            move || { atom2.fetch_add(1, Ordering::SeqCst); }
        );
    }
}
<commit_msg>Minor cleanup<commit_after>//! Testing and benchmarking tools for concurrent Rust code
//!
//! This crate groups together a bunch of utilities which I've found useful when
//! testing and benchmarking Rust concurrency primitives in the triple_buffer
//! and spmc_buffer crates.
//!
//! If it proves popular, other testing and benchmarking tools may be added,
//! based on user demand.
//!
//! # Examples
//!
//! For examples of this crate at work, look at its "tests" and "benchs"
//! submodules, which showcase expected usage.

#![deny(missing_docs)]

pub mod race_cell;

use std::{
    sync::{
        Arc,
        atomic::{AtomicBool, Ordering},
        Barrier,
    },
    thread,
    time::{Duration, Instant},
};

/// Test that running two operations concurrently works
///
/// When testing multi-threaded constructs, such as synchronization primitives,
/// checking that the code works when run sequentially is insufficient.
/// Concurrent interactions must also be tested, by running some operations
/// in parallel across multiple threads.
///
/// Ideally, this function would take as input a variable-size set of functors
/// to be run in parallel. Since Rust does not support variadic generics yet,
/// however, multiple versions of this function must be provided, each
/// associated with a different functor tuple size.
///
pub fn concurrent_test_2<F, G>(f1: F, f2: G)
    where F: FnOnce() + Send + 'static,
          G: FnOnce() + Send + 'static
{
    // Setup a barrier to synchronize thread startup
    let barrier1 = Arc::new(Barrier::new(2));
    let barrier2 = barrier1.clone();

    // Start the first task
    let thread1 = thread::spawn(move || {
        barrier1.wait();
        f1();
    });

    // Run the second task
    barrier2.wait();
    f2();

    // Make sure that the first task completed properly
    thread1.join().unwrap();
}

/// Test that running three operations concurrently works
///
/// This is a variant of concurrent_test_2 that works with three functors
/// instead of two. It is hoped that future evolutions of Rust will render this
/// (light) code duplication obsolete, in favor of some variadic design.
///
pub fn concurrent_test_3<F, G, H>(f1: F, f2: G, f3: H)
    where F: FnOnce() + Send + 'static,
          G: FnOnce() + Send + 'static,
          H: FnOnce() + Send + 'static
{
    // Setup a barrier to synchronize thread startup
    let barrier1 = Arc::new(Barrier::new(3));
    let barrier2 = barrier1.clone();
    let barrier3 = barrier1.clone();

    // Start the first task
    let thread1 = thread::spawn(move || {
        barrier1.wait();
        f1();
    });

    // Start the second task
    let thread2 = thread::spawn(move || {
        barrier2.wait();
        f2();
    });

    // Run the third task
    barrier3.wait();
    f3();

    // Make sure that the first two tasks completed properly
    thread1.join().unwrap();
    thread2.join().unwrap();
}

/// Microbenchmark some simple operation by running it N times
///
/// This simple benchmark harness is meant as a cheap and hackish substitute for
/// cargo benchmarks in Stable Rust. It runs a user-provided operation a certain
/// number of times and measures how much time it takes.
///
/// To use it, write your benchmark as an ignored cargo test, put a call to
/// benchmark() or counting_benchmark() as the last operation, and tell your
/// user to run the benchmarks via:
///
///   $ cargo test --release -- --ignored --nocapture --test-threads=1
///
/// This is a dreadful hack. But for now, it's the best that I've thought of.
///
pub fn benchmark<F: FnMut()>(num_iterations: u32, mut iteration: F) {
    // Run the user-provided operation in a loop
    let start_time = Instant::now();
    for _ in 0..num_iterations {
        iteration()
    }
    let total_duration = start_time.elapsed();

    // Reproducible benchmarks (<10% variance) usually take between a couple of
    // seconds and a couple of minutes, so miliseconds are the right timing unit
    // for the duration of the whole benchmark.
    let total_ms = (total_duration.as_secs() as u32) * 1000 +
                   total_duration.subsec_nanos() / 1_000_000;

    // This tool is designed for microbenchmarking, so iterations are assumed
    // to last from one CPU cycle (a fraction of a nanosecond) to a fraction of
    // a second. Longer durations will require multi-resolution formatting.
    let hundred_iter_duration = total_duration * 100 / num_iterations;
    let iter_duration = hundred_iter_duration / 100;
    assert_eq!(iter_duration.as_secs(), 0);
    let iter_ns = iter_duration.subsec_nanos();
    let iter_ns_fraction = hundred_iter_duration.subsec_nanos() % 100;

    // Display the benchmark results, in a fashion that will fit in the output
    // of cargo test in nocapture mode.
    print!("{} ms ({} iters, ~{}.{} ns/iter): ",
           total_ms,
           num_iterations,
           iter_ns,
           iter_ns_fraction);
}

/// Microbenchmark some operation while another is running in a loop
///
/// For multithreaded code, benchmarking the performance of isolated operations
/// is usually only half of the story. Synchronization and memory contention can
/// also have a large impact on performance.
///
/// For this reason, it is often useful to also measure the performance of one
/// operation as another "antagonist" operation is also running in a background
/// thread. This function implements such concurrent benchmarking.
///
pub fn concurrent_benchmark<F, A>(num_iterations: u32,
                                  iteration_func: F,
                                  mut antagonist_func: A)
    where F: FnMut(),
          A: FnMut() + Send + 'static
{
    // Setup a barrier to synchronize benchmark and antagonist startup
    let barrier = Arc::new(Barrier::new(2));

    // Setup an atomic "continue" flag to shut down the antagonist at
    // the end of the benchmarking procedure
    let run_flag = Arc::new(AtomicBool::new(true));

    // Schedule the antagonist thread
    let (antag_barrier, antag_run_flag) = (barrier.clone(), run_flag.clone());
    let antagonist = thread::spawn(
        move || {
            antag_barrier.wait();
            while antag_run_flag.load(Ordering::Relaxed) {
                antagonist_func();
            }
        }
    );

    // Wait for the antagonist to be running, and give it some headstart
    barrier.wait();
    thread::sleep(Duration::from_millis(10));

    // Run the benchmark
    benchmark(num_iterations, iteration_func);

    // Stop the antagonist and check that nothing went wrong on its side
    run_flag.store(false, Ordering::Relaxed);
    antagonist.join().unwrap();
}

/// Examples of concurrent testing code
#[cfg(test)]
mod tests {
    use std::sync::{
        Arc,
        atomic::{AtomicUsize, Ordering},
    };

    // Check the behaviour of concurrent atomic swaps and fetch-adds
    #[test]
    fn swap_and_fetch_add() {
        // Amount of atomic operations to check
        const ATOMIC_OPS_COUNT: usize = 100_000_000;

        // Create a shared atomic variable
        let atom = Arc::new(AtomicUsize::new(0));
        let atom2 = atom.clone();

        // Check that concurrent atomic operations work correctly
        let mut last_value = 0;
        ::concurrent_test_2(
            move || {
                // One thread continuously increments the atomic variable...
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let former_atom = atom.fetch_add(1, Ordering::Relaxed);
                    assert!((former_atom == 0) || (former_atom == last_value));
                    last_value = former_atom+1;
                }
            },
            move || {
                // ...as another continuously resets it to zero
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let former_atom = atom2.swap(0, Ordering::Relaxed);
                    assert!(former_atom <= ATOMIC_OPS_COUNT);
                }
            }
        );
    }

    // Check the behaviour of concurrent fetch-and/or/xors
    #[test]
    fn fetch_and_or_xor() {
        // Amount of atomic operations to check
        const ATOMIC_OPS_COUNT: usize = 30_000_000;

        // Create a shared atomic variable. Even though this is an atomic Usize,
        // we will only use the 16 low-order bits for maximal portability.
        let atom = Arc::new(AtomicUsize::new(0));
        let atom2 = atom.clone();
        let atom3 = atom.clone();

        // Masks used by each atomic operation
        const AND_MASK: usize = 0b0000_0000_0000_0000; // Clear all bits
        const XOR_MASK: usize = 0b0000_1111_0000_1111; // Flip some bits
        const OR_MASK: usize  = 0b1111_0000_1111_0000; // Set other bits

        // Check that concurrent atomic operations work correctly by ensuring
        // that at any point in time, only the 16 low-order bits can be set, and
        // the grouped sets of bits in the masks above are either all set or
        // all cleared in any observable state.
        ::concurrent_test_3(
            move || {
                // One thread runs fetch-ands in a loop...
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let old_val = atom.fetch_and(AND_MASK, Ordering::Relaxed);
                    assert_eq!(old_val & 0b1111_1111_1111_1111, old_val);
                    assert!((old_val & XOR_MASK == XOR_MASK) ||
                            (old_val & XOR_MASK == 0));
                    assert!((old_val & OR_MASK == OR_MASK) ||
                            (old_val & OR_MASK == 0));
                }
            },
            move || {
                // ...another runs fetch-ors in a loop...
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let old_val = atom2.fetch_or(OR_MASK, Ordering::Relaxed);
                    assert_eq!(old_val & 0b1111_1111_1111_1111, old_val);
                    assert!((old_val & XOR_MASK == XOR_MASK) ||
                            (old_val & XOR_MASK == 0));
                    assert!((old_val & OR_MASK == OR_MASK) ||
                            (old_val & OR_MASK == 0));
                }
            },
            move || {
                // ...and the last one runs fetch-xors in a loop...
                for _ in 1..(ATOMIC_OPS_COUNT + 1) {
                    let old_val = atom3.fetch_xor(XOR_MASK, Ordering::Relaxed);
                    assert_eq!(old_val & 0b1111_1111_1111_1111, old_val);
                    assert!((old_val & XOR_MASK == XOR_MASK) ||
                            (old_val & XOR_MASK == 0));
                    assert!((old_val & OR_MASK == OR_MASK) ||
                            (old_val & OR_MASK == 0));
                }
            }
        );
    }
}

/// Exemples of benchmarking code
///
/// As discussed before, these should be run via the following command:
///
///   $ cargo test --release -- --ignored --nocapture --test-threads=1
#[cfg(test)]
mod benchs {
    use std::sync::{
        Arc,
        atomic::{AtomicUsize, Ordering},
    };

    // Benchmark relaxed atomics in sequential code (best case)
    #[test]
    #[ignore]
    fn bench_relaxed() {
        let atom = AtomicUsize::new(0);
        ::benchmark(500_000_000, || { atom.fetch_add(1, Ordering::Relaxed); });
        assert_eq!(atom.load(Ordering::Relaxed), 500_000_000);
    }

    // Benchmark sequentially consistent atomics in concurrent code (worst case)
    #[test]
    #[ignore]
    fn bench_seqcst() {
        let atom = Arc::new(AtomicUsize::new(0));
        let atom2 = atom.clone();
        ::concurrent_benchmark(
            100_000_000,
            move || { atom.fetch_add(1, Ordering::SeqCst); },
            move || { atom2.fetch_add(1, Ordering::SeqCst); }
        );
    }
}
<|endoftext|>


<commit_before>#![crate_id = "clap"]
#![crate_type= "lib"]

#![feature(collections, core, libc, env)]

//! A simply library for parsing command line arguments when writing
//! command line and console applications.

pub use arg::Arg;
pub use app::App;

mod app;
mod argmatches;
mod arg;
mod args;
<commit_msg>Re-addedd the pub-use<commit_after>#![crate_id = "clap"]
#![crate_type= "lib"]

#![feature(collections, core, libc, env)]

//! A simply library for parsing command line arguments when writing
//! command line and console applications.

pub use argmatches::ArgMatches;
pub use arg::Arg;
pub use app::App;

mod app;
mod argmatches;
mod arg;
mod args;
<|endoftext|>