<commit_before>//! A data structure for tracking source positions in language implementations, inspired by the
//! [CodeMap type in rustc's libsyntax](https://github.com/rust-lang/rust/blob/master/src/libsyntax/codemap.rs).
//!
//! The `CodeMap` tracks all source files and maps positions within them to linear indexes as if all
//! source files were concatenated. This allows a source position to be represented by a small
//! 32-bit `Pos` indexing into the `CodeMap`, under the assumption that the total amount of parsed
//! source code will not exceed 4GiB. The `CodeMap` can look up the source file, line, and column
//! of a `Pos` or `Span`, as well as provide source code snippets for error reporting.
//!
//! # Example
//! ```
//! use codemap::CodeMap;
//! let mut codemap = CodeMap::new();
//! let file = codemap.add_file("test.rs".to_string(), "fn test(){\n    println!(\"Hello\");\n}\n".to_string());
//! let string_literal_span = file.span.subspan(24, 31);
//!
//! let location = codemap.look_up_span(string_literal_span);
//! assert_eq!(location.file.name, "test.rs");
//! assert_eq!(location.begin.line, 1);
//! assert_eq!(location.begin.column, 13);
//! assert_eq!(location.end.line, 1);
//! assert_eq!(location.end.column, 20);
//! ```

use std::cmp::Ordering;
use std::ops::{Add, Sub, Deref};
use std::fmt;
use std::sync::Arc;

/// A small, `Copy`, value representing a position in a `CodeMap`'s file.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct Pos(u32);

pub const DUMMY_POS: Pos = Pos(0);

impl Add<u64> for Pos {
    type Output = Pos;
    fn add(self, other: u64) -> Pos {
        Pos(self.0 + other as u32)
    }
}

impl Sub<Pos> for Pos {
    type Output = u64;
    fn sub(self, other: Pos) -> u64 {
        (self.0 - other.0) as u64
    }
}

/// A range of text within a CodeMap.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct Span {
    /// The position in the codemap representing the first byte of the span.
    low: Pos,

    /// The position after the last byte of the span.
    high: Pos,
}

pub const DUMMY_SP: Span = Span { low: DUMMY_POS, high: DUMMY_POS };

impl Span {
    /// Makes a span from offsets relative to the start of this span.
    ///
    /// # Panics
    ///   * If `end < begin`
    ///   * If `end` is beyond the length of the span
    pub fn subspan(&self, begin: u64, end: u64) -> Span {
        assert!(end >= begin);
        assert!(self.low + end <= self.high);
        Span {
            low: self.low + begin,
            high: self.low + end,
        }
    }

    /// Checks if a span is contained within this span.
    pub fn contains(&self, other: Span) -> bool {
        self.low <= other.low && self.high >= other.high
    }

    /// The position in the codemap representing the first byte of the span.
    pub fn low(&self) -> Pos {
        self.low
    }

    /// The position after the last byte of the span.
    pub fn high(&self) -> Pos {
        self.high
    }

    /// The length in bytes of the text of the span
    pub fn len(&self) -> u64 {
        self.high - self.low
    }
}

/// Associate a Span with a value of arbitrary type (e.g. an AST node).
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
pub struct Spanned<T> {
    pub node: T,
    pub span: Span,
}

impl<T> Deref for Spanned<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.node
    }
}

/// A data structure recording source code files for position lookup.
pub struct CodeMap {
    files: Vec<Arc<File>>,
    _allow_priv: ()
}

impl CodeMap {
    /// Creates an empty `CodeMap`.
    pub fn new() -> CodeMap {
        CodeMap {
            files: vec![],
            _allow_priv: ()
        }
    }

    /// Adds a file with the given name and contents.
    ///
    /// Use the returned `File` and its `.span` property to create `Spans`
    /// representing substrings of the file.
    pub fn add_file(&mut self, name: String, source: String) -> Arc<File> {
        let low = self.end_pos() + 1;
        let high = low + source.len() as u64;
        let mut lines = vec![low];
        lines.extend(source.match_indices('\n').map(|(p, _)| { low + (p + 1) as u64 }));

        let file = Arc::new(File {
            span: Span { low: low, high: high },
            name: name,
            source: source,
            lines: lines,
            _allow_priv: (),
        });

        self.files.push(file.clone());
        file
    }

    fn end_pos(&self) -> Pos {
        self.files.last().map(|x| x.span.high).unwrap_or(Pos(0))
    }

    /// Looks up the `File` that contains the specified position.
    pub fn find_file(&self, pos: Pos) -> &File {
        self.files.binary_search_by(|file| {
            if file.span.high < pos {
                Ordering::Less
            } else if file.span.low > pos {
                Ordering::Greater
            } else {
                Ordering::Equal
            }
        }).ok().map(|i| &self.files[i]).expect("Mapping unknown source location")
    }

    /// Gets the file, line, and column represented by a `Pos`.
    pub fn look_up_pos(&self, pos: Pos) -> Loc {
        let file = self.find_file(pos);
        let position = file.find_line_col(pos);
        Loc { file, position }
    }

    /// Gets the file and its line and column ranges represented by a `Span`.
    pub fn look_up_span(&self, span: Span) -> SpanLoc {
        let file = self.find_file(span.low);
        let begin = file.find_line_col(span.low);
        let end = file.find_line_col(span.high);
        SpanLoc { file, begin, end }
    }
}

/// A `CodeMap`'s record of a source file.
pub struct File {
    /// The span representing the entire file.
    pub span: Span,

    /// The filename as it would be displayed in an error message.
    pub name: String,

    /// Contents of the file.
    pub source: String,

    /// Byte positions of line beginnings.
    pub lines: Vec<Pos>,

    _allow_priv: ()
}

impl File {
    /// Gets the line number of a Pos.
    ///
    /// The lines are 0-indexed (first line is numbered 0)
    ///
    /// # Panics
    ///
    ///  * If `pos` is not within this file's span
    pub fn find_line(&self, pos: Pos) -> usize {
        assert!(pos >= self.span.low);
        assert!(pos <= self.span.high);
        (match self.lines.binary_search(&pos) {
            Ok(i) => i,
            Err(i) => i - 1,
        })
    }

    /// Gets the line and column of a Pos.
    ///
    /// # Panics
    ///
    /// * If `pos` is not with this file's span
    /// * If `pos` points to a byte in the middle of a UTF-8 character
    pub fn find_line_col(&self, pos: Pos) -> LineCol {
        let line = self.find_line(pos);
        let line_span = self.line_span(line);
        let byte_col = pos - line_span.low;
        let col = self.source_slice(line_span)[..byte_col as usize].chars().count();

        LineCol{ line: line, column: col }
    }

    /// Gets the source text of a Span.
    ///
    /// # Panics
    ///
    ///   * If `span` is not entirely within this file.
    pub fn source_slice(&self, span: Span) -> &str {
        assert!(self.span.contains(span));
        self.source[((span.low - self.span.low) as usize)..((span.high - self.span.low) as usize)].trim_right()
    }

    /// Gets the span representing a line by line number.
    ///
    /// The line number is 0-indexed (first line is numbered 0)
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn line_span(&self, line: usize) -> Span {
        assert!(line < self.lines.len());
        Span {
            low: self.lines[line],
            high: *self.lines.get(line + 1).unwrap_or(&self.span.high)
        }
    }

    /// Gets the source text of a line.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn source_line(&self, line: usize) -> &str {
        self.source_slice(self.line_span(line))
    }
}

/// A line and column.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct LineCol {
    /// The line number within the file (0-indexed).
    pub line: usize,

    /// The column within the line (0-indexed).
    pub column: usize,
}

/// A file, and a line and column within it.
#[derive(Clone)]
pub struct Loc<'a> {
    pub file: &'a File,
    pub position: LineCol,
}

impl<'a> fmt::Display for Loc<'a> {
    /// Formats the location as `filename:line:column`, with a 1-indexed
    /// line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}:{}:{}", self.file.name, self.position.line+1, self.position.column+1)
    }
}

/// A file, and a line and column range within it.
#[derive(Clone)]
pub struct SpanLoc<'a> {
    pub file: &'a File,
    pub begin: LineCol,
    pub end: LineCol,
}

impl<'a> fmt::Display for SpanLoc<'a> {
    /// Formats the span as `filename:start_line:start_column: end_line:end_column`,
    /// or if the span is zero-length, `filename:line:column`, with a 1-indexed line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.begin == self.end {
            write!(f, "{}:{}:{}", self.file.name, self.begin.line+1, self.begin.column+1)
        } else {
            write!(f, "{}:{}:{}: {}:{}", self.file.name, self.begin.line+1, self.begin.column+1, self.end.line+1, self.end.column+1)
        }
    }
}

#[test]
fn test_codemap() {
    let mut codemap = CodeMap::new();
    let f1 = codemap.add_file("test1.rs".to_string(), "abcd\nefghij\nqwerty".to_string());
    let f2 = codemap.add_file("test2.rs".to_string(), "foo\nbar".to_string());

    let x = f1.span.subspan(5, 10);
    let f = codemap.find_file(x.low);
    assert_eq!(f.name, "test1.rs");
    assert_eq!(f.find_line_col(f.span.low()), LineCol { line: 0, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 4), LineCol { line: 0, column: 4 });
    assert_eq!(f.find_line_col(f.span.low() + 5), LineCol { line: 1, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 16), LineCol { line: 2, column: 4 });

    let x = f2.span.subspan(4, 7);
    assert_eq!(codemap.find_file(x.low()).name, "test2.rs");
    assert_eq!(codemap.find_file(x.high()).name, "test2.rs");
}
<commit_msg>Remove dummy values in favor of Option<Span> or Option<Pos><commit_after>//! A data structure for tracking source positions in language implementations, inspired by the
//! [CodeMap type in rustc's libsyntax](https://github.com/rust-lang/rust/blob/master/src/libsyntax/codemap.rs).
//!
//! The `CodeMap` tracks all source files and maps positions within them to linear indexes as if all
//! source files were concatenated. This allows a source position to be represented by a small
//! 32-bit `Pos` indexing into the `CodeMap`, under the assumption that the total amount of parsed
//! source code will not exceed 4GiB. The `CodeMap` can look up the source file, line, and column
//! of a `Pos` or `Span`, as well as provide source code snippets for error reporting.
//!
//! # Example
//! ```
//! use codemap::CodeMap;
//! let mut codemap = CodeMap::new();
//! let file = codemap.add_file("test.rs".to_string(), "fn test(){\n    println!(\"Hello\");\n}\n".to_string());
//! let string_literal_span = file.span.subspan(24, 31);
//!
//! let location = codemap.look_up_span(string_literal_span);
//! assert_eq!(location.file.name, "test.rs");
//! assert_eq!(location.begin.line, 1);
//! assert_eq!(location.begin.column, 13);
//! assert_eq!(location.end.line, 1);
//! assert_eq!(location.end.column, 20);
//! ```

use std::cmp::Ordering;
use std::ops::{Add, Sub, Deref};
use std::fmt;
use std::sync::Arc;

/// A small, `Copy`, value representing a position in a `CodeMap`'s file.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct Pos(u32);

impl Add<u64> for Pos {
    type Output = Pos;
    fn add(self, other: u64) -> Pos {
        Pos(self.0 + other as u32)
    }
}

impl Sub<Pos> for Pos {
    type Output = u64;
    fn sub(self, other: Pos) -> u64 {
        (self.0 - other.0) as u64
    }
}

/// A range of text within a CodeMap.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct Span {
    /// The position in the codemap representing the first byte of the span.
    low: Pos,

    /// The position after the last byte of the span.
    high: Pos,
}

impl Span {
    /// Makes a span from offsets relative to the start of this span.
    ///
    /// # Panics
    ///   * If `end < begin`
    ///   * If `end` is beyond the length of the span
    pub fn subspan(&self, begin: u64, end: u64) -> Span {
        assert!(end >= begin);
        assert!(self.low + end <= self.high);
        Span {
            low: self.low + begin,
            high: self.low + end,
        }
    }

    /// Checks if a span is contained within this span.
    pub fn contains(&self, other: Span) -> bool {
        self.low <= other.low && self.high >= other.high
    }

    /// The position in the codemap representing the first byte of the span.
    pub fn low(&self) -> Pos {
        self.low
    }

    /// The position after the last byte of the span.
    pub fn high(&self) -> Pos {
        self.high
    }

    /// The length in bytes of the text of the span
    pub fn len(&self) -> u64 {
        self.high - self.low
    }
}

/// Associate a Span with a value of arbitrary type (e.g. an AST node).
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
pub struct Spanned<T> {
    pub node: T,
    pub span: Span,
}

impl<T> Deref for Spanned<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.node
    }
}

/// A data structure recording source code files for position lookup.
pub struct CodeMap {
    files: Vec<Arc<File>>,
    _allow_priv: ()
}

impl CodeMap {
    /// Creates an empty `CodeMap`.
    pub fn new() -> CodeMap {
        CodeMap {
            files: vec![],
            _allow_priv: ()
        }
    }

    /// Adds a file with the given name and contents.
    ///
    /// Use the returned `File` and its `.span` property to create `Spans`
    /// representing substrings of the file.
    pub fn add_file(&mut self, name: String, source: String) -> Arc<File> {
        let low = self.end_pos() + 1;
        let high = low + source.len() as u64;
        let mut lines = vec![low];
        lines.extend(source.match_indices('\n').map(|(p, _)| { low + (p + 1) as u64 }));

        let file = Arc::new(File {
            span: Span { low: low, high: high },
            name: name,
            source: source,
            lines: lines,
            _allow_priv: (),
        });

        self.files.push(file.clone());
        file
    }

    fn end_pos(&self) -> Pos {
        self.files.last().map(|x| x.span.high).unwrap_or(Pos(0))
    }

    /// Looks up the `File` that contains the specified position.
    pub fn find_file(&self, pos: Pos) -> &File {
        self.files.binary_search_by(|file| {
            if file.span.high < pos {
                Ordering::Less
            } else if file.span.low > pos {
                Ordering::Greater
            } else {
                Ordering::Equal
            }
        }).ok().map(|i| &self.files[i]).expect("Mapping unknown source location")
    }

    /// Gets the file, line, and column represented by a `Pos`.
    pub fn look_up_pos(&self, pos: Pos) -> Loc {
        let file = self.find_file(pos);
        let position = file.find_line_col(pos);
        Loc { file, position }
    }

    /// Gets the file and its line and column ranges represented by a `Span`.
    pub fn look_up_span(&self, span: Span) -> SpanLoc {
        let file = self.find_file(span.low);
        let begin = file.find_line_col(span.low);
        let end = file.find_line_col(span.high);
        SpanLoc { file, begin, end }
    }
}

/// A `CodeMap`'s record of a source file.
pub struct File {
    /// The span representing the entire file.
    pub span: Span,

    /// The filename as it would be displayed in an error message.
    pub name: String,

    /// Contents of the file.
    pub source: String,

    /// Byte positions of line beginnings.
    pub lines: Vec<Pos>,

    _allow_priv: ()
}

impl File {
    /// Gets the line number of a Pos.
    ///
    /// The lines are 0-indexed (first line is numbered 0)
    ///
    /// # Panics
    ///
    ///  * If `pos` is not within this file's span
    pub fn find_line(&self, pos: Pos) -> usize {
        assert!(pos >= self.span.low);
        assert!(pos <= self.span.high);
        (match self.lines.binary_search(&pos) {
            Ok(i) => i,
            Err(i) => i - 1,
        })
    }

    /// Gets the line and column of a Pos.
    ///
    /// # Panics
    ///
    /// * If `pos` is not with this file's span
    /// * If `pos` points to a byte in the middle of a UTF-8 character
    pub fn find_line_col(&self, pos: Pos) -> LineCol {
        let line = self.find_line(pos);
        let line_span = self.line_span(line);
        let byte_col = pos - line_span.low;
        let col = self.source_slice(line_span)[..byte_col as usize].chars().count();

        LineCol{ line: line, column: col }
    }

    /// Gets the source text of a Span.
    ///
    /// # Panics
    ///
    ///   * If `span` is not entirely within this file.
    pub fn source_slice(&self, span: Span) -> &str {
        assert!(self.span.contains(span));
        self.source[((span.low - self.span.low) as usize)..((span.high - self.span.low) as usize)].trim_right()
    }

    /// Gets the span representing a line by line number.
    ///
    /// The line number is 0-indexed (first line is numbered 0)
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn line_span(&self, line: usize) -> Span {
        assert!(line < self.lines.len());
        Span {
            low: self.lines[line],
            high: *self.lines.get(line + 1).unwrap_or(&self.span.high)
        }
    }

    /// Gets the source text of a line.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn source_line(&self, line: usize) -> &str {
        self.source_slice(self.line_span(line))
    }
}

/// A line and column.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct LineCol {
    /// The line number within the file (0-indexed).
    pub line: usize,

    /// The column within the line (0-indexed).
    pub column: usize,
}

/// A file, and a line and column within it.
#[derive(Clone)]
pub struct Loc<'a> {
    pub file: &'a File,
    pub position: LineCol,
}

impl<'a> fmt::Display for Loc<'a> {
    /// Formats the location as `filename:line:column`, with a 1-indexed
    /// line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}:{}:{}", self.file.name, self.position.line+1, self.position.column+1)
    }
}

/// A file, and a line and column range within it.
#[derive(Clone)]
pub struct SpanLoc<'a> {
    pub file: &'a File,
    pub begin: LineCol,
    pub end: LineCol,
}

impl<'a> fmt::Display for SpanLoc<'a> {
    /// Formats the span as `filename:start_line:start_column: end_line:end_column`,
    /// or if the span is zero-length, `filename:line:column`, with a 1-indexed line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.begin == self.end {
            write!(f, "{}:{}:{}", self.file.name, self.begin.line+1, self.begin.column+1)
        } else {
            write!(f, "{}:{}:{}: {}:{}", self.file.name, self.begin.line+1, self.begin.column+1, self.end.line+1, self.end.column+1)
        }
    }
}

#[test]
fn test_codemap() {
    let mut codemap = CodeMap::new();
    let f1 = codemap.add_file("test1.rs".to_string(), "abcd\nefghij\nqwerty".to_string());
    let f2 = codemap.add_file("test2.rs".to_string(), "foo\nbar".to_string());

    let x = f1.span.subspan(5, 10);
    let f = codemap.find_file(x.low);
    assert_eq!(f.name, "test1.rs");
    assert_eq!(f.find_line_col(f.span.low()), LineCol { line: 0, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 4), LineCol { line: 0, column: 4 });
    assert_eq!(f.find_line_col(f.span.low() + 5), LineCol { line: 1, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 16), LineCol { line: 2, column: 4 });

    let x = f2.span.subspan(4, 7);
    assert_eq!(codemap.find_file(x.low()).name, "test2.rs");
    assert_eq!(codemap.find_file(x.high()).name, "test2.rs");
}
<|endoftext|>


<commit_before>pub mod types;

mod query_source;
mod connection;
mod result;
#[macro_use]
mod macros;

pub use result::*;
pub use query_source::{QuerySource, Queriable, Table, Column};
pub use connection::Connection;

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

    #[derive(PartialEq, Eq, Debug)]
    struct User {
        id: i32,
        name: String,
        age: Option<i16>,
    }

    table! {
        users {
            id -> Serial,
            name -> VarChar,
            age -> Nullable<SmallInt>,
        }
    }

    queriable! {
        User {
            id -> i32,
            name -> String,
            age -> Option<i16>,
        }
    }

    #[test]
    fn selecting_basic_data() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let expected_data = vec![
            (1i32, "Sean".to_string(), None::<i16>),
            (2i32, "Tess".to_string(), None::<i16>),
         ];
        let actual_data = connection.query_all(&users::table).unwrap();
        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn selecting_a_struct() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let expected_users = vec![
            User { id: 1, name: "Sean".to_string(), age: None },
            User { id: 2, name: "Tess".to_string(), age: None },
         ];
        let actual_users = connection.query_all(&users::table).unwrap();
        assert_eq!(expected_users, actual_users);
    }

    #[test]
    fn with_safe_select() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let select_id = users.select(id);
        // fails to compile (we should test this)
        // let select_id = users::table.select(posts::id);
        let select_name = users.select(name);
        let ids = connection.query_all(&select_id).unwrap();
        let names: Vec<String> = connection.query_all(&select_name).unwrap();
        // fails to compile (we should test this)
        // let names: Vec<String> = connection.query_all(&select_id).unwrap();

        assert_eq!(vec![1, 2], ids);
        assert_eq!(vec!["Sean".to_string(), "Tess".to_string()], names);
    }

    #[test]
    fn selecting_multiple_columns() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name, age) VALUES ('Jim', 30), ('Bob', 40)")
            .unwrap();

        let source = users.select((name, age));
        let expected_data = vec![
            ("Jim".to_string(), Some(30i16)),
            ("Bob".to_string(), Some(40i16)),
        ];
        let actual_data = connection.query_all(&source).unwrap();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn with_select_sql() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let select_count = unsafe { users::table.select_sql::<types::BigInt>("COUNT(*)") };
        let get_count = || connection.query_one::<_, i64>(&select_count).unwrap();
        // fails to compile (we should test this)
        // let actual_count = connection.query_one::<_, String>(&select_count).unwrap();

        assert_eq!(Some(2), get_count());

        connection.execute("INSERT INTO users (name) VALUES ('Jim')")
            .unwrap();

        assert_eq!(Some(3), get_count());
    }

    fn connection() -> Connection {
        let connection_url = ::std::env::var("DATABASE_URL").ok()
            .expect("DATABASE_URL must be set in order to run tests");
        let result = Connection::establish(&connection_url).unwrap();
        result.execute("BEGIN").unwrap();
        result
    }

    fn setup_users_table(connection: &Connection) {
        connection.execute("CREATE TABLE users (
            id SERIAL PRIMARY KEY,
            name VARCHAR NOT NULL,
            age SMALLINT
        )").unwrap();
    }
}
<commit_msg>Clarify intent in a few comments<commit_after>pub mod types;

mod query_source;
mod connection;
mod result;
#[macro_use]
mod macros;

pub use result::*;
pub use query_source::{QuerySource, Queriable, Table, Column};
pub use connection::Connection;

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

    #[derive(PartialEq, Eq, Debug)]
    struct User {
        id: i32,
        name: String,
        age: Option<i16>,
    }

    // Compiler plugin will automatically invoke this based on schema
    table! {
        users {
            id -> Serial,
            name -> VarChar,
            age -> Nullable<SmallInt>,
        }
    }

    // Compiler plugin will replace this with #[derive(Queriable)]
    queriable! {
        User {
            id -> i32,
            name -> String,
            age -> Option<i16>,
        }
    }

    #[test]
    fn selecting_basic_data() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let expected_data = vec![
            (1i32, "Sean".to_string(), None::<i16>),
            (2i32, "Tess".to_string(), None::<i16>),
         ];
        let actual_data = connection.query_all(&users::table).unwrap();
        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn selecting_a_struct() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let expected_users = vec![
            User { id: 1, name: "Sean".to_string(), age: None },
            User { id: 2, name: "Tess".to_string(), age: None },
         ];
        let actual_users = connection.query_all(&users::table).unwrap();
        assert_eq!(expected_users, actual_users);
    }

    #[test]
    fn with_safe_select() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let select_id = users.select(id);
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let select_id = users::table.select(posts::id);
        let select_name = users.select(name);
        let ids = connection.query_all(&select_id).unwrap();
        let names: Vec<String> = connection.query_all(&select_name).unwrap();
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let names: Vec<String> = connection.query_all(&select_id).unwrap();

        assert_eq!(vec![1, 2], ids);
        assert_eq!(vec!["Sean".to_string(), "Tess".to_string()], names);
    }

    #[test]
    fn selecting_multiple_columns() {
        use self::users::columns::*;
        use self::users::table as users;

        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name, age) VALUES ('Jim', 30), ('Bob', 40)")
            .unwrap();

        let source = users.select((name, age));
        let expected_data = vec![
            ("Jim".to_string(), Some(30i16)),
            ("Bob".to_string(), Some(40i16)),
        ];
        let actual_data = connection.query_all(&source).unwrap();

        assert_eq!(expected_data, actual_data);
    }

    #[test]
    fn with_select_sql() {
        let connection = connection();
        setup_users_table(&connection);
        connection.execute("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
            .unwrap();

        let select_count = unsafe { users::table.select_sql::<types::BigInt>("COUNT(*)") };
        let get_count = || connection.query_one::<_, i64>(&select_count).unwrap();
        // This should fail type checking, and we should add a test to ensure
        // it continues to fail to compile.
        // let actual_count = connection.query_one::<_, String>(&select_count).unwrap();

        assert_eq!(Some(2), get_count());

        connection.execute("INSERT INTO users (name) VALUES ('Jim')")
            .unwrap();

        assert_eq!(Some(3), get_count());
    }

    fn connection() -> Connection {
        let connection_url = ::std::env::var("DATABASE_URL").ok()
            .expect("DATABASE_URL must be set in order to run tests");
        let result = Connection::establish(&connection_url).unwrap();
        result.execute("BEGIN").unwrap();
        result
    }

    fn setup_users_table(connection: &Connection) {
        connection.execute("CREATE TABLE users (
            id SERIAL PRIMARY KEY,
            name VARCHAR NOT NULL,
            age SMALLINT
        )").unwrap();
    }
}
<|endoftext|>


<commit_before>//! A build dependency for Cargo libraries to find system artifacts through the
//! `pkg-config` utility.
//!
//! This library will shell out to `pkg-config` as part of build scripts and
//! probe the system to determine how to link to a specified library. The
//! `Config` structure serves as a method of configuring how `pkg-config` is
//! invoked in a builder style.
//!
//! A number of environment variables are available to globally configure how
//! this crate will invoke `pkg-config`:
//!
//! * `PKG_CONFIG_ALLOW_CROSS` - if this variable is not set, then `pkg-config`
//!   will automatically be disabled for all cross compiles.
//! * `FOO_NO_PKG_CONFIG` - if set, this will disable running `pkg-config` when
//!   probing for the library named `foo`.
//!
//! There are also a number of environment variables which can configure how a
//! library is linked to (dynamically vs statically). These variables control
//! whether the `--static` flag is passed. Note that this behavior can be
//! overridden by configuring explicitly on `Config`. The variables are checked
//! in the following order:
//!
//! * `FOO_STATIC` - pass `--static` for the library `foo`
//! * `FOO_DYNAMIC` - do not pass `--static` for the library `foo`
//! * `PKG_CONFIG_ALL_STATIC` - pass `--static` for all libraries
//! * `PKG_CONFIG_ALL_DYNAMIC` - do not pass `--static` for all libraries
//!
//! After running `pkg-config` all appropriate Cargo metadata will be printed on
//! stdout if the search was successful.
//!
//! # Example
//!
//! Find the system library named `foo`.
//!
//! ```no_run
//! extern crate pkg_config;
//!
//! fn main() {
//!     pkg_config::find_library("foo").unwrap();
//! }
//! ```
//!
//! Configure how library `foo` is linked to.
//!
//! ```no_run
//! extern crate pkg_config;
//!
//! fn main() {
//!     pkg_config::Config::new().statik(true).find("foo").unwrap();
//! }
//! ```

#![doc(html_root_url = "http://alexcrichton.com/pkg-config-rs")]
#![cfg_attr(test, deny(warnings))]

use std::ascii::AsciiExt;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use std::str;

pub fn target_supported() -> bool {
    env::var("HOST") == env::var("TARGET") ||
        env::var_os("PKG_CONFIG_ALLOW_CROSS").is_some()
}

#[derive(Clone)]
pub struct Config {
    statik: Option<bool>,
    atleast_version: Option<String>,
    extra_args: Vec<OsString>,
}

#[derive(Debug)]
pub struct Library {
    pub libs: Vec<String>,
    pub link_paths: Vec<PathBuf>,
    pub frameworks: Vec<String>,
    pub framework_paths: Vec<PathBuf>,
    pub include_paths: Vec<PathBuf>,
    _priv: (),
}

/// Simple shortcut for using all default options for finding a library.
pub fn find_library(name: &str) -> Result<Library, String> {
    Config::new().find(name)
}

impl Config {
    /// Creates a new set of configuration options which are all initially set
    /// to "blank".
    pub fn new() -> Config {
        Config {
            statik: None,
            atleast_version: None,
            extra_args: vec![],
        }
    }

    /// Indicate whether the `--static` flag should be passed.
    ///
    /// This will override the inference from environment variables described in
    /// the crate documentation.
    pub fn statik(&mut self, statik: bool) -> &mut Config {
        self.statik = Some(statik);
        self
    }

    /// Indicate that the library must be at least version `vers`.
    pub fn atleast_version(&mut self, vers: &str) -> &mut Config {
        self.atleast_version = Some(vers.to_string());
        self
    }

    /// Add an argument to pass to pkg-config.
    ///
    /// It's placed after all of the arguments generated by this library.
    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Config {
        self.extra_args.push(arg.as_ref().to_os_string());
        self
    }

    /// Run `pkg-config` to find the library `name`.
    ///
    /// This will use all configuration previously set to specify how
    /// `pkg-config` is run.
    pub fn find(&self, name: &str) -> Result<Library, String> {
        if env::var_os(&format!("{}_NO_PKG_CONFIG", envify(name))).is_some() {
            return Err(format!("pkg-config requested to be aborted for {}", name))
        } else if !target_supported() {
            return Err("pkg-config doesn't handle cross compilation. Use \
                        PKG_CONFIG_ALLOW_CROSS=1 to override".to_string());
        }

        let mut ret = Library {
            libs: Vec::new(),
            link_paths: Vec::new(),
            include_paths: Vec::new(),
            frameworks: Vec::new(),
            framework_paths: Vec::new(),
            _priv: (),
        };

        let stdout = try!(run(command(name, &["--libs", "--cflags"], self)));

        let mut dirs = Vec::new();
        let parts = stdout.split(' ').filter(|l| l.len() > 2)
                          .map(|arg| (&arg[0..2], &arg[2..]))
                          .collect::<Vec<_>>();
        for &(flag, val) in parts.iter() {
            if flag == "-L" {
                println!("cargo:rustc-link-search=native={}", val);
                dirs.push(PathBuf::from(val));
                ret.link_paths.push(PathBuf::from(val));
            } else if flag == "-F" {
                println!("cargo:rustc-link-search=framework={}", val);
                ret.framework_paths.push(PathBuf::from(val));
            } else if flag == "-I" {
                ret.include_paths.push(PathBuf::from(val));
            }
        }
        let statik = is_static(name, self);
        for &(flag, val) in parts.iter() {
            if flag == "-l" {
                ret.libs.push(val.to_string());
                if statik && !is_system(val, &dirs) {
                    println!("cargo:rustc-link-lib=static={}", val);
                } else {
                    println!("cargo:rustc-link-lib={}", val);
                }
            }
        }
        let mut iter = stdout.split(' ');
        while let Some(part) = iter.next() {
            if part != "-framework" { continue }
            if let Some(lib) = iter.next() {
                println!("cargo:rustc-link-lib=framework={}", lib);
                ret.frameworks.push(lib.to_string());
            }
        }

        Ok(ret)
    }

    /// Run `pkg-config` to get the value of a variable from a package using
    /// --variable.
    pub fn get_variable(package: &str, variable: &str) -> Result<String, String> {
        let arg = format!("--variable={}", variable);
        Ok(try!(run(command(package, &[&arg], &Config::new()))).trim_right().to_owned())
    }
}

fn infer_static(name: &str) -> bool {
    let name = envify(name);
    if env::var_os(&format!("{}_STATIC", name)).is_some() {
        true
    } else if env::var_os(&format!("{}_DYNAMIC", name)).is_some() {
        false
    } else if env::var_os("PKG_CONFIG_ALL_STATIC").is_some() {
        true
    } else if env::var_os("PKG_CONFIG_ALL_DYNAMIC").is_some() {
        false
    } else {
        false
    }
}

fn envify(name: &str) -> String {
    name.chars().map(|c| c.to_ascii_uppercase()).map(|c| if c == '-' {'_'} else {c}).collect()
}

fn is_static(name: &str, config: &Config) -> bool {
    config.statik.unwrap_or_else(|| infer_static(name))
}

fn is_system(name: &str, dirs: &[PathBuf]) -> bool {
    let libname = format!("lib{}.a", name);
    let root = Path::new("/usr");
    !dirs.iter().any(|d| {
        !d.starts_with(root) && fs::metadata(&d.join(&libname)).is_ok()
    })
}

fn command(name: &str, args: &[&str], config: &Config) -> Command {
    let mut cmd = Command::new("pkg-config");
    if is_static(name, config) {
        cmd.arg("--static");
    }
    cmd.args(args);
    cmd.args(&config.extra_args);
    match config.atleast_version {
        Some(ref version) => {
            cmd.arg(&format!("{} >= {}", name, version));
        },
        None => {
            cmd.arg(name);
        },
    }
    cmd.env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1");
    cmd
}

fn run(mut cmd: Command) -> Result<String, String> {
    let out = try!(cmd.output().map_err(|e| {
        format!("failed to run `{:?}`: {}", cmd, e)
    }));

    let stdout = String::from_utf8(out.stdout).unwrap();
    if out.status.success() {
        return Ok(stdout);
    }

    let stderr = str::from_utf8(&out.stderr).unwrap();
    let mut msg = format!("`{:?}` did not exit successfully: {}", cmd, out.status);
    if stdout.len() > 0 {
        msg.push_str("\n--- stdout\n");
        msg.push_str(&*stdout);
    }
    if stderr.len() > 0 {
        msg.push_str("\n--- stderr\n");
        msg.push_str(stderr);
    }

    return Err(msg);
}
<commit_msg>Delegate the output parsing to Library<commit_after>//! A build dependency for Cargo libraries to find system artifacts through the
//! `pkg-config` utility.
//!
//! This library will shell out to `pkg-config` as part of build scripts and
//! probe the system to determine how to link to a specified library. The
//! `Config` structure serves as a method of configuring how `pkg-config` is
//! invoked in a builder style.
//!
//! A number of environment variables are available to globally configure how
//! this crate will invoke `pkg-config`:
//!
//! * `PKG_CONFIG_ALLOW_CROSS` - if this variable is not set, then `pkg-config`
//!   will automatically be disabled for all cross compiles.
//! * `FOO_NO_PKG_CONFIG` - if set, this will disable running `pkg-config` when
//!   probing for the library named `foo`.
//!
//! There are also a number of environment variables which can configure how a
//! library is linked to (dynamically vs statically). These variables control
//! whether the `--static` flag is passed. Note that this behavior can be
//! overridden by configuring explicitly on `Config`. The variables are checked
//! in the following order:
//!
//! * `FOO_STATIC` - pass `--static` for the library `foo`
//! * `FOO_DYNAMIC` - do not pass `--static` for the library `foo`
//! * `PKG_CONFIG_ALL_STATIC` - pass `--static` for all libraries
//! * `PKG_CONFIG_ALL_DYNAMIC` - do not pass `--static` for all libraries
//!
//! After running `pkg-config` all appropriate Cargo metadata will be printed on
//! stdout if the search was successful.
//!
//! # Example
//!
//! Find the system library named `foo`.
//!
//! ```no_run
//! extern crate pkg_config;
//!
//! fn main() {
//!     pkg_config::find_library("foo").unwrap();
//! }
//! ```
//!
//! Configure how library `foo` is linked to.
//!
//! ```no_run
//! extern crate pkg_config;
//!
//! fn main() {
//!     pkg_config::Config::new().statik(true).find("foo").unwrap();
//! }
//! ```

#![doc(html_root_url = "http://alexcrichton.com/pkg-config-rs")]
#![cfg_attr(test, deny(warnings))]

use std::ascii::AsciiExt;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use std::str;

pub fn target_supported() -> bool {
    env::var("HOST") == env::var("TARGET") ||
        env::var_os("PKG_CONFIG_ALLOW_CROSS").is_some()
}

#[derive(Clone)]
pub struct Config {
    statik: Option<bool>,
    atleast_version: Option<String>,
    extra_args: Vec<OsString>,
}

#[derive(Debug)]
pub struct Library {
    pub libs: Vec<String>,
    pub link_paths: Vec<PathBuf>,
    pub frameworks: Vec<String>,
    pub framework_paths: Vec<PathBuf>,
    pub include_paths: Vec<PathBuf>,
    _priv: (),
}

/// Simple shortcut for using all default options for finding a library.
pub fn find_library(name: &str) -> Result<Library, String> {
    Config::new().find(name)
}

impl Config {
    /// Creates a new set of configuration options which are all initially set
    /// to "blank".
    pub fn new() -> Config {
        Config {
            statik: None,
            atleast_version: None,
            extra_args: vec![],
        }
    }

    /// Indicate whether the `--static` flag should be passed.
    ///
    /// This will override the inference from environment variables described in
    /// the crate documentation.
    pub fn statik(&mut self, statik: bool) -> &mut Config {
        self.statik = Some(statik);
        self
    }

    /// Indicate that the library must be at least version `vers`.
    pub fn atleast_version(&mut self, vers: &str) -> &mut Config {
        self.atleast_version = Some(vers.to_string());
        self
    }

    /// Add an argument to pass to pkg-config.
    ///
    /// It's placed after all of the arguments generated by this library.
    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Config {
        self.extra_args.push(arg.as_ref().to_os_string());
        self
    }

    /// Run `pkg-config` to find the library `name`.
    ///
    /// This will use all configuration previously set to specify how
    /// `pkg-config` is run.
    pub fn find(&self, name: &str) -> Result<Library, String> {
        if env::var_os(&format!("{}_NO_PKG_CONFIG", envify(name))).is_some() {
            return Err(format!("pkg-config requested to be aborted for {}", name))
        } else if !target_supported() {
            return Err("pkg-config doesn't handle cross compilation. Use \
                        PKG_CONFIG_ALLOW_CROSS=1 to override".to_string());
        }

        let mut library = Library::new();

        let output = try!(run(command(name, &["--libs", "--cflags"], self)));
        library.digest_libs_cflags(name, &output, self);

        Ok(library)
    }

    /// Run `pkg-config` to get the value of a variable from a package using
    /// --variable.
    pub fn get_variable(package: &str, variable: &str) -> Result<String, String> {
        let arg = format!("--variable={}", variable);
        Ok(try!(run(command(package, &[&arg], &Config::new()))).trim_right().to_owned())
    }
}

impl Library {
    fn new() -> Library {
        Library {
            libs: Vec::new(),
            link_paths: Vec::new(),
            include_paths: Vec::new(),
            frameworks: Vec::new(),
            framework_paths: Vec::new(),
            _priv: (),
        }
    }

    fn digest_libs_cflags(&mut self, name: &str, output: &str, config: &Config) {
        let parts = output.split(' ').filter(|l| l.len() > 2)
                          .map(|arg| (&arg[0..2], &arg[2..]))
                          .collect::<Vec<_>>();

        let mut dirs = Vec::new();
        for &(flag, val) in parts.iter() {
            if flag == "-L" {
                println!("cargo:rustc-link-search=native={}", val);
                dirs.push(PathBuf::from(val));
                self.link_paths.push(PathBuf::from(val));
            } else if flag == "-F" {
                println!("cargo:rustc-link-search=framework={}", val);
                self.framework_paths.push(PathBuf::from(val));
            } else if flag == "-I" {
                self.include_paths.push(PathBuf::from(val));
            }
        }

        let statik = is_static(name, config);
        for &(flag, val) in parts.iter() {
            if flag == "-l" {
                self.libs.push(val.to_string());
                if statik && !is_system(val, &dirs) {
                    println!("cargo:rustc-link-lib=static={}", val);
                } else {
                    println!("cargo:rustc-link-lib={}", val);
                }
            }
        }

        let mut iter = output.split(' ');
        while let Some(part) = iter.next() {
            if part != "-framework" { continue }
            if let Some(lib) = iter.next() {
                println!("cargo:rustc-link-lib=framework={}", lib);
                self.frameworks.push(lib.to_string());
            }
        }
    }
}

fn infer_static(name: &str) -> bool {
    let name = envify(name);
    if env::var_os(&format!("{}_STATIC", name)).is_some() {
        true
    } else if env::var_os(&format!("{}_DYNAMIC", name)).is_some() {
        false
    } else if env::var_os("PKG_CONFIG_ALL_STATIC").is_some() {
        true
    } else if env::var_os("PKG_CONFIG_ALL_DYNAMIC").is_some() {
        false
    } else {
        false
    }
}

fn envify(name: &str) -> String {
    name.chars().map(|c| c.to_ascii_uppercase()).map(|c| if c == '-' {'_'} else {c}).collect()
}

fn is_static(name: &str, config: &Config) -> bool {
    config.statik.unwrap_or_else(|| infer_static(name))
}

fn is_system(name: &str, dirs: &[PathBuf]) -> bool {
    let libname = format!("lib{}.a", name);
    let root = Path::new("/usr");
    !dirs.iter().any(|d| {
        !d.starts_with(root) && fs::metadata(&d.join(&libname)).is_ok()
    })
}

fn command(name: &str, args: &[&str], config: &Config) -> Command {
    let mut cmd = Command::new("pkg-config");
    if is_static(name, config) {
        cmd.arg("--static");
    }
    cmd.args(args);
    cmd.args(&config.extra_args);
    match config.atleast_version {
        Some(ref version) => {
            cmd.arg(&format!("{} >= {}", name, version));
        },
        None => {
            cmd.arg(name);
        },
    }
    cmd.env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1");
    cmd
}

fn run(mut cmd: Command) -> Result<String, String> {
    let out = try!(cmd.output().map_err(|e| {
        format!("failed to run `{:?}`: {}", cmd, e)
    }));

    let stdout = String::from_utf8(out.stdout).unwrap();
    if out.status.success() {
        return Ok(stdout);
    }

    let stderr = str::from_utf8(&out.stderr).unwrap();
    let mut msg = format!("`{:?}` did not exit successfully: {}", cmd, out.status);
    if stdout.len() > 0 {
        msg.push_str("\n--- stdout\n");
        msg.push_str(&*stdout);
    }
    if stderr.len() > 0 {
        msg.push_str("\n--- stderr\n");
        msg.push_str(stderr);
    }

    return Err(msg);
}
<|endoftext|>


<commit_before>#![no_std]

extern crate num;

pub mod create;
pub use create::*;

pub mod set;
pub use set::*;

pub mod mul;
pub use mul::*;

pub mod sdiv;
pub use sdiv::*;

pub mod misc;
pub use misc::*;

pub mod transform;
pub use transform::*;
<commit_msg>dont export mods<commit_after>#![no_std]

extern crate num;

mod create;
pub use create::*;

mod set;
pub use set::*;

mod mul;
pub use mul::*;

mod sdiv;
pub use sdiv::*;

mod misc;
pub use misc::*;

mod transform;
pub use transform::*;
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! Traits for generic floats in game programming
use std::ops::*;

/// Convenience trait for floats.
pub trait Float:
    'static + Send + Sync
    + Copy + Radians + One + Zero + Sqrt
    + FromPrimitive
    + Min + Max + Signum + Powf
    + Trig
    + PartialEq
    + PartialOrd
    + Add<Self, Output = Self>
    + Mul<Self, Output = Self>
    + Sub<Self, Output = Self>
    + Div<Self, Output = Self>
    + Rem<Self, Output = Self>
    + Neg<Output = Self>
    + Trig {}

impl<T> Float for T where
    T: 'static + Send + Sync
    + Copy + Radians + One + Zero + Sqrt
    + FromPrimitive
    + Min + Max + Signum + Powf
    + Trig
    + PartialEq
    + PartialOrd
    + Add<T, Output = T>
    + Mul<T, Output = T>
    + Sub<T, Output = T>
    + Div<T, Output = T>
    + Rem<T, Output = T>
    + Neg<Output = T>
    + Trig {}

/// Minimum value.
pub trait Min {
    /// Returns the minimum value of self or other.
    fn min(self, other: Self) -> Self;
}

impl Min for f32 {
    #[inline(always)]
    fn min(self, other: Self) -> Self { self.min(other) }
}

impl Min for f64 {
    #[inline(always)]
    fn min(self, other: Self) -> Self { self.min(other) }
}

/// Maximum value.
pub trait Max {
    /// Returns the maximum value of self or other.
    fn max(self, other: Self) -> Self;
}

impl Max for f32 {
    #[inline(always)]
    fn max(self, other: Self) -> Self { self.max(other) }
}

impl Max for f64 {
    #[inline(always)]
    fn max(self, other: Self) -> Self { self.max(other) }
}

/// The sign of the number.
pub trait Signum {
    /// Returns number representing the sign of self
    fn signum(self) -> Self;
}

impl Signum for f32 {
    #[inline(always)]
    fn signum(self) -> Self { self.signum() }
}

impl Signum for f64 {
    #[inline(always)]
    fn signum(self) -> Self { self.signum() }
}

/// Floating number power.
pub trait Powf {
    /// Returns floating power of the number.
    fn powf(self, other: Self) -> Self;
}

impl Powf for f32 {
    #[inline(always)]
    fn powf(self, other: Self) -> Self { self.powf(other) }
}

impl Powf for f64 {
    #[inline(always)]
    fn powf(self, other: Self) -> Self { self.powf(other) }
}

/// Useful constants for radians.
pub trait Radians {
    /// Returns radians corresponding to 90 degrees.
    fn _90() -> Self;

    /// Returns radians corresponding to 180 degrees.
    fn _180() -> Self;

    /// Returns radians corresponding to 360 degrees.
    fn _360() -> Self;

    /// Convert a value to radians from degrees.
    /// Equivalent to ```value * (π / 180)```.
    fn deg_to_rad(self) -> Self;

    /// Convert a value to degrees from radians.
    /// Equivalent to ```value * (180 / π)```.
    fn rad_to_deg(self) -> Self;
}

impl Radians for f32 {
    #[inline(always)]
    fn _90() -> f32 {
        ::std::f32::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f32 {
        ::std::f32::consts::PI
    }

    #[inline(always)]
    fn _360() -> f32 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f32::consts::PI / 180.0f32)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f32 / ::std::f32::consts::PI)
    }
}

impl Radians for f64 {
    #[inline(always)]
    fn _90() -> f64 {
        ::std::f64::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f64 {
        ::std::f64::consts::PI
    }

    #[inline(always)]
    fn _360() -> f64 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f64::consts::PI / 180.0f64)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f64 / ::std::f64::consts::PI)
    }
}

/// Number 1.
pub trait One {
    /// Returns 1.
    fn one() -> Self;
}

/// Number 0.
pub trait Zero {
    /// Returns 0.
    fn zero() -> Self;
}

impl One for f32 {
    #[inline(always)]
    fn one() -> f32 { 1.0 }
}

impl One for f64 {
    #[inline(always)]
    fn one() -> f64 { 1.0 }
}

impl Zero for f32 {
    #[inline(always)]
    fn zero() -> f32 { 0.0 }
}

impl Zero for f64 {
    #[inline(always)]
    fn zero() -> f64 { 0.0 }
}

/// Square root.
pub trait Sqrt {
    /// Returns square root.
    fn sqrt(self) -> Self;
}

impl Sqrt for f32 {
    #[inline(always)]
    fn sqrt(self) -> f32 { self.sqrt() }
}

impl Sqrt for f64 {
    #[inline(always)]
    fn sqrt(self) -> f64 { self.sqrt() }
}

/// Basic trigonometry functions
pub trait Trig {
    /// Returns sine of self
    fn sin(self) -> Self;
    /// Returns cosine of self
    fn cos(self) -> Self;
    /// Returns tangent of self
    fn tan(self) -> Self;
}

impl Trig for f32 {
    #[inline(always)]
    fn sin(self) -> f32 { self.sin() }

    #[inline(always)]
    fn cos(self) -> f32 { self.cos() }

    #[inline(always)]
    fn tan(self) -> f32 { self.tan() }
}

impl Trig for f64 {
    #[inline(always)]
    fn sin(self) -> f64 { self.sin() }

    #[inline(always)]
    fn cos(self) -> f64 { self.cos() }

    #[inline(always)]
    fn tan(self) -> f64 { self.tan() }
}

/// Casts into another type.
pub trait Cast<T> {
    /// Casts into other type.
    fn cast(self) -> T;
}

impl Cast<f32> for f64 {
    #[inline(always)]
    fn cast(self) -> f32 { self as f32 }
}

impl Cast<f64> for f32 {
    #[inline(always)]
    fn cast(self) -> f64 { self as f64 }
}

impl Cast<f32> for f32 {
    #[inline(always)]
    fn cast(self) -> f32 { self }
}

impl Cast<f64> for f64 {
    #[inline(always)]
    fn cast(self) -> f64 { self }
}

/// Trait for converting from different numeric types
pub trait FromPrimitive {
    /// from a f64
    fn from_f64(t: f64) -> Self;
    /// from a f32
    fn from_f32(t: f32) -> Self;
    /// from a isze
    fn from_isize(t: isize) -> Self;
    /// from a u32
    fn from_u32(t: u32) -> Self;
    /// from a i32
    fn from_i32(t: i32) -> Self;
    // Add more as needed..
}

impl FromPrimitive for f64 {
    #[inline(always)]
    fn from_f64(t: f64) -> Self { t }
    #[inline(always)]
    fn from_f32(t: f32) -> Self { t as f64 }
    #[inline(always)]
    fn from_isize(t: isize) -> Self { t as f64 }
    #[inline(always)]
    fn from_u32(t: u32) -> Self { t as f64 }
    #[inline(always)]
    fn from_i32(t: i32) -> Self { t as f64 }
}

impl FromPrimitive for f32 {
    #[inline(always)]
    fn from_f64(t: f64) -> Self { t as f32 }
    #[inline(always)]
    fn from_f32(t: f32) -> Self { t }
    #[inline(always)]
    fn from_isize(t: isize) -> Self { t as f32 }
    #[inline(always)]
    fn from_u32(t: u32) -> Self { t as f32 }
    #[inline(always)]
    fn from_i32(t: i32) -> Self { t as f32 }
}

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

    #[test]
    fn test_f32_sqrt() {
        let a = 4.0f32;
        let b = <f32 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f32);
    }

    #[test]
    fn test_f64_sqrt() {
        let a = 4.0f64;
        let b = <f64 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f64);
    }

    #[test]
    fn test_f32_deg_to_rad() {
        let degrees = 23.0f32;
        let radians = degrees.deg_to_rad();
        assert!((radians - 0.401425).abs() > ::std::f32::EPSILON);
    }

    #[test]
    fn test_f64_deg_to_rad() {
        let degrees = 60.0f64;
        let radians = degrees.deg_to_rad();
        assert!((radians - 1.047197).abs()  > ::std::f64::EPSILON);
    }
}
<commit_msg>Made `Float` inherit assign operators<commit_after>#![deny(missing_docs)]

//! Traits for generic floats in game programming
use std::ops::*;

/// Convenience trait for floats.
pub trait Float:
    'static + Send + Sync
    + Copy + Radians + One + Zero + Sqrt
    + FromPrimitive
    + Min + Max + Signum + Powf
    + Trig
    + PartialEq
    + PartialOrd
    + Add<Self, Output = Self> + AddAssign<Self>
    + Mul<Self, Output = Self> + MulAssign<Self>
    + Sub<Self, Output = Self> + SubAssign<Self>
    + Div<Self, Output = Self> + DivAssign<Self>
    + Rem<Self, Output = Self> + RemAssign<Self>
    + Neg<Output = Self>
    + Trig {}

impl<T> Float for T where
    T: 'static + Send + Sync
    + Copy + Radians + One + Zero + Sqrt
    + FromPrimitive
    + Min + Max + Signum + Powf
    + Trig
    + PartialEq
    + PartialOrd
    + Add<T, Output = T> + AddAssign<T>
    + Mul<T, Output = T> + MulAssign<T>
    + Sub<T, Output = T> + SubAssign<T>
    + Div<T, Output = T> + DivAssign<T>
    + Rem<T, Output = T> + RemAssign<T>
    + Neg<Output = T>
    + Trig {}

/// Minimum value.
pub trait Min {
    /// Returns the minimum value of self or other.
    fn min(self, other: Self) -> Self;
}

impl Min for f32 {
    #[inline(always)]
    fn min(self, other: Self) -> Self { self.min(other) }
}

impl Min for f64 {
    #[inline(always)]
    fn min(self, other: Self) -> Self { self.min(other) }
}

/// Maximum value.
pub trait Max {
    /// Returns the maximum value of self or other.
    fn max(self, other: Self) -> Self;
}

impl Max for f32 {
    #[inline(always)]
    fn max(self, other: Self) -> Self { self.max(other) }
}

impl Max for f64 {
    #[inline(always)]
    fn max(self, other: Self) -> Self { self.max(other) }
}

/// The sign of the number.
pub trait Signum {
    /// Returns number representing the sign of self
    fn signum(self) -> Self;
}

impl Signum for f32 {
    #[inline(always)]
    fn signum(self) -> Self { self.signum() }
}

impl Signum for f64 {
    #[inline(always)]
    fn signum(self) -> Self { self.signum() }
}

/// Floating number power.
pub trait Powf {
    /// Returns floating power of the number.
    fn powf(self, other: Self) -> Self;
}

impl Powf for f32 {
    #[inline(always)]
    fn powf(self, other: Self) -> Self { self.powf(other) }
}

impl Powf for f64 {
    #[inline(always)]
    fn powf(self, other: Self) -> Self { self.powf(other) }
}

/// Useful constants for radians.
pub trait Radians {
    /// Returns radians corresponding to 90 degrees.
    fn _90() -> Self;

    /// Returns radians corresponding to 180 degrees.
    fn _180() -> Self;

    /// Returns radians corresponding to 360 degrees.
    fn _360() -> Self;

    /// Convert a value to radians from degrees.
    /// Equivalent to ```value * (π / 180)```.
    fn deg_to_rad(self) -> Self;

    /// Convert a value to degrees from radians.
    /// Equivalent to ```value * (180 / π)```.
    fn rad_to_deg(self) -> Self;
}

impl Radians for f32 {
    #[inline(always)]
    fn _90() -> f32 {
        ::std::f32::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f32 {
        ::std::f32::consts::PI
    }

    #[inline(always)]
    fn _360() -> f32 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f32::consts::PI / 180.0f32)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f32 / ::std::f32::consts::PI)
    }
}

impl Radians for f64 {
    #[inline(always)]
    fn _90() -> f64 {
        ::std::f64::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f64 {
        ::std::f64::consts::PI
    }

    #[inline(always)]
    fn _360() -> f64 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f64::consts::PI / 180.0f64)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f64 / ::std::f64::consts::PI)
    }
}

/// Number 1.
pub trait One {
    /// Returns 1.
    fn one() -> Self;
}

/// Number 0.
pub trait Zero {
    /// Returns 0.
    fn zero() -> Self;
}

impl One for f32 {
    #[inline(always)]
    fn one() -> f32 { 1.0 }
}

impl One for f64 {
    #[inline(always)]
    fn one() -> f64 { 1.0 }
}

impl Zero for f32 {
    #[inline(always)]
    fn zero() -> f32 { 0.0 }
}

impl Zero for f64 {
    #[inline(always)]
    fn zero() -> f64 { 0.0 }
}

/// Square root.
pub trait Sqrt {
    /// Returns square root.
    fn sqrt(self) -> Self;
}

impl Sqrt for f32 {
    #[inline(always)]
    fn sqrt(self) -> f32 { self.sqrt() }
}

impl Sqrt for f64 {
    #[inline(always)]
    fn sqrt(self) -> f64 { self.sqrt() }
}

/// Basic trigonometry functions
pub trait Trig {
    /// Returns sine of self
    fn sin(self) -> Self;
    /// Returns cosine of self
    fn cos(self) -> Self;
    /// Returns tangent of self
    fn tan(self) -> Self;
}

impl Trig for f32 {
    #[inline(always)]
    fn sin(self) -> f32 { self.sin() }

    #[inline(always)]
    fn cos(self) -> f32 { self.cos() }

    #[inline(always)]
    fn tan(self) -> f32 { self.tan() }
}

impl Trig for f64 {
    #[inline(always)]
    fn sin(self) -> f64 { self.sin() }

    #[inline(always)]
    fn cos(self) -> f64 { self.cos() }

    #[inline(always)]
    fn tan(self) -> f64 { self.tan() }
}

/// Casts into another type.
pub trait Cast<T> {
    /// Casts into other type.
    fn cast(self) -> T;
}

impl Cast<f32> for f64 {
    #[inline(always)]
    fn cast(self) -> f32 { self as f32 }
}

impl Cast<f64> for f32 {
    #[inline(always)]
    fn cast(self) -> f64 { self as f64 }
}

impl Cast<f32> for f32 {
    #[inline(always)]
    fn cast(self) -> f32 { self }
}

impl Cast<f64> for f64 {
    #[inline(always)]
    fn cast(self) -> f64 { self }
}

/// Trait for converting from different numeric types
pub trait FromPrimitive {
    /// from a f64
    fn from_f64(t: f64) -> Self;
    /// from a f32
    fn from_f32(t: f32) -> Self;
    /// from a isze
    fn from_isize(t: isize) -> Self;
    /// from a u32
    fn from_u32(t: u32) -> Self;
    /// from a i32
    fn from_i32(t: i32) -> Self;
    // Add more as needed..
}

impl FromPrimitive for f64 {
    #[inline(always)]
    fn from_f64(t: f64) -> Self { t }
    #[inline(always)]
    fn from_f32(t: f32) -> Self { t as f64 }
    #[inline(always)]
    fn from_isize(t: isize) -> Self { t as f64 }
    #[inline(always)]
    fn from_u32(t: u32) -> Self { t as f64 }
    #[inline(always)]
    fn from_i32(t: i32) -> Self { t as f64 }
}

impl FromPrimitive for f32 {
    #[inline(always)]
    fn from_f64(t: f64) -> Self { t as f32 }
    #[inline(always)]
    fn from_f32(t: f32) -> Self { t }
    #[inline(always)]
    fn from_isize(t: isize) -> Self { t as f32 }
    #[inline(always)]
    fn from_u32(t: u32) -> Self { t as f32 }
    #[inline(always)]
    fn from_i32(t: i32) -> Self { t as f32 }
}

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

    #[test]
    fn test_f32_sqrt() {
        let a = 4.0f32;
        let b = <f32 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f32);
    }

    #[test]
    fn test_f64_sqrt() {
        let a = 4.0f64;
        let b = <f64 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f64);
    }

    #[test]
    fn test_f32_deg_to_rad() {
        let degrees = 23.0f32;
        let radians = degrees.deg_to_rad();
        assert!((radians - 0.401425).abs() > ::std::f32::EPSILON);
    }

    #[test]
    fn test_f64_deg_to_rad() {
        let degrees = 60.0f64;
        let radians = degrees.deg_to_rad();
        assert!((radians - 1.047197).abs()  > ::std::f64::EPSILON);
    }
}
<|endoftext|>


<commit_before>#![feature(box_syntax, box_patterns)]

use std::fmt;

// Nock(a)          *a
// [a b c]          [a [b c]]
//
// ?[a b]           0
// ?a               1
// +[a b]           +[a b]
// +a               1 + a
// =[a a]           0
// =[a b]           1
// =a               =a
//
// /[1 a]           a
// /[2 a b]         a
// /[3 a b]         b
// /[(a + a) b]     /[2 /[a b]]
// /[(a + a + 1) b] /[3 /[a b]]
// /a               /a
//
// *[a [b c] d]     [*[a b c] *[a d]]
//
// *[a 0 b]         /[b a]
// *[a 1 b]         b
// *[a 2 b c]       *[*[a b] *[a c]]
// *[a 3 b]         ?*[a b]
// *[a 4 b]         +*[a b]
// *[a 5 b]         =*[a b]
//
// *[a 6 b c d]     *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]
// *[a 7 b c]       *[a 2 b 1 c]
// *[a 8 b c]       *[a 7 [[7 [0 1] b] 0 1] c]
// *[a 9 b c]       *[a 7 c 2 [0 1] 0 b]
// *[a 10 [b c] d]  *[a 8 c 7 [0 3] d]
// *[a 10 b c]      *[a c]
//
// *a               *a

#[derive(Clone, PartialEq, Eq)]
pub enum Noun {
    Atom(u64), // TODO: Need bigints?
    Cell(Box<Noun>, Box<Noun>),
}

impl fmt::Display for Noun {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Atom(ref n) => write!(f, "{}", n),
            &Cell(ref a, ref b) => {
                try!(write!(f, "[{} ", a));
                // List pretty-printer.
                let mut cur = b;
                loop {
                    match cur {
                        &box Cell(ref a, ref b) => {
                            try!(write!(f, "{} ", a));
                            cur = &b;
                        }
                        &box Atom(ref n) => {
                            return write!(f, "{}]", n);
                        }
                    }
                }
            }
        }
    }
}

impl fmt::Debug for Noun {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self) }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Op {
    Wut, // ?
    Lus, // +
    Tis, // =
    Fas, // /
    Tar, // *
}

use Op::*;
use Noun::*;

fn eval(op: Op, noun: Noun) -> Result<Noun, Noun> {
    match (op, noun) {
        (Wut, Cell(_, _)) => Ok(Atom(0)),
        (Wut, Atom(_)) => Ok(Atom(1)),
        (Lus, Atom(a)) => Ok(Atom(1 + a)),
        (Lus, a) => Err(a),
        (Tis, Cell(a, b)) => Ok(Atom(if a == b { 0 } else { 1 })),
        (Tis, a) => Err(a),

        (Fas, Cell(box Atom(1), box a)) => Ok(a),
        (Fas, Cell(box Atom(2), box Cell(box a, _))) => Ok(a),
        (Fas, Cell(box Atom(3), box Cell(_, box b))) => Ok(b),
        (Fas, Cell(box Atom(a), b)) => {
            let x = try!(eval(Fas, Cell(box Atom(a / 2), b)));
            eval(Fas, Cell(box Atom(if a % 2 == 0 { 2 } else { 3 }), box x))
        }
        (Fas, a) => Err(a),

        (Tar, Cell(a, box Cell(box Cell(b, c), d))) => {
            let x = try!(eval(Tar, Cell(a.clone(), box Cell(b, c))));
            let y = try!(eval(Tar, Cell(a, d)));
            Ok(Cell(box x, box y))
        }

        // TODO: Numbered tar ops.

        (Tar, a) => Err(a)
    }
}

pub fn nock(noun: Noun) -> Result<Noun, Noun> { eval(Wut, noun) }

#[test]
fn it_works() {
    println!("{}", Cell(box Atom(1), box Cell(box Atom(2), box Atom(3))));
    println!("{:?}", eval(Tis, Cell(box Atom(2), box Atom(2))));
    println!("{:?}", eval(Fas, Cell(box Atom(7), box Cell(box Cell(box Atom(4), box Atom(5)), box Cell(box Atom(6), box Cell(box Atom(14), box Atom(15)))))));
    assert!(false);
}
<commit_msg>Noun macro and parse stub<commit_after>#![crate_name="nock"]

#![feature(box_syntax, box_patterns)]

use std::fmt;
use std::str;

// Nock(a)          *a
// [a b c]          [a [b c]]
//
// ?[a b]           0
// ?a               1
// +[a b]           +[a b]
// +a               1 + a
// =[a a]           0
// =[a b]           1
// =a               =a
//
// /[1 a]           a
// /[2 a b]         a
// /[3 a b]         b
// /[(a + a) b]     /[2 /[a b]]
// /[(a + a + 1) b] /[3 /[a b]]
// /a               /a
//
// *[a [b c] d]     [*[a b c] *[a d]]
//
// *[a 0 b]         /[b a]
// *[a 1 b]         b
// *[a 2 b c]       *[*[a b] *[a c]]
// *[a 3 b]         ?*[a b]
// *[a 4 b]         +*[a b]
// *[a 5 b]         =*[a b]
//
// *[a 6 b c d]     *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]
// *[a 7 b c]       *[a 2 b 1 c]
// *[a 8 b c]       *[a 7 [[7 [0 1] b] 0 1] c]
// *[a 9 b c]       *[a 7 c 2 [0 1] 0 b]
// *[a 10 [b c] d]  *[a 8 c 7 [0 3] d]
// *[a 10 b c]      *[a c]
//
// *a               *a

#[derive(Clone, PartialEq, Eq)]
pub enum Noun {
    Atom(u64), // TODO: Need bigints?
    Cell(Box<Noun>, Box<Noun>),
}

impl Noun {
    pub fn new<T: Into<Noun>>(val: T) -> Noun {
        val.into()
    }
}

impl Into<Noun> for u64 {
    fn into(self) -> Noun { Noun::Atom(self) }
}

impl fmt::Display for Noun {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Atom(ref n) => write!(f, "{}", n),
            &Cell(ref a, ref b) => {
                try!(write!(f, "[{} ", a));
                // List pretty-printer.
                let mut cur = b;
                loop {
                    match cur {
                        &box Cell(ref a, ref b) => {
                            try!(write!(f, "{} ", a));
                            cur = &b;
                        }
                        &box Atom(ref n) => {
                            return write!(f, "{}]", n);
                        }
                    }
                }
            }
        }
    }
}

impl fmt::Debug for Noun {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self) }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct ParseNockError;

impl str::FromStr for Noun {
    type Err = ParseNockError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        unimplemented!();
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Op {
    Wut, // ?
    Lus, // +
    Tis, // =
    Fas, // /
    Tar, // *
}

use Op::*;
use Noun::*;

pub fn eval(op: Op, noun: Noun) -> Result<Noun, Noun> {
    match (op, noun) {
        (Wut, Cell(_, _)) => Ok(Atom(0)),
        (Wut, Atom(_)) => Ok(Atom(1)),
        (Lus, Atom(a)) => Ok(Atom(1 + a)),
        (Lus, a) => Err(a),
        (Tis, Cell(a, b)) => Ok(Atom(if a == b { 0 } else { 1 })),
        (Tis, a) => Err(a),

        (Fas, Cell(box Atom(1), box a)) => Ok(a),
        (Fas, Cell(box Atom(2), box Cell(box a, _))) => Ok(a),
        (Fas, Cell(box Atom(3), box Cell(_, box b))) => Ok(b),
        (Fas, Cell(box Atom(a), b)) => {
            let x = try!(eval(Fas, Cell(box Atom(a / 2), b)));
            eval(Fas, Cell(box Atom(if a % 2 == 0 { 2 } else { 3 }), box x))
        }
        (Fas, a) => Err(a),

        (Tar, Cell(a, box Cell(box Cell(b, c), d))) => {
            let x = try!(eval(Tar, Cell(a.clone(), box Cell(b, c))));
            let y = try!(eval(Tar, Cell(a, d)));
            Ok(Cell(box x, box y))
        }

        // TODO: Numbered tar ops.

        (Tar, a) => Err(a)
    }
}

pub fn nock(noun: Noun) -> Result<Noun, Noun> { eval(Wut, noun) }

/*
/// Helper macro for defining nouns.
macro_rules! noun {
    [[$x:expr, $($xs:expr),+], [$y:expr, $($ys:expr),+]] => { ::nock::Noun::Cell(box noun![$x, $($xs),+], box noun![$y, $($ys),+]) };
    [[$x:expr, $($xs:expr),+], $y:expr] => { ::nock::Noun::Cell(box noun![$x, $($xs),+], box ::nock::Noun::Atom($y)) };
    [$x:expr, [$y:expr, $($ys:expr),+]] => { ::nock::Noun::Cell(box ::nock::Noun::Atom($x), box noun![$y, $($ys),+]) };
    [$x:expr, $y:expr] => { ::nock::Noun::Cell(box ::nock::Noun::Atom($x), box ::nock::Noun::Atom($y)) };
    [$x:expr, $y:expr, $($ys:expr),+] => { ::nock::Noun::Cell(box ::nock::Noun::Atom($x), box noun![$y, $($ys),+]) };
    [$x:expr] => { ::nock::Noun::Atom($x) };
}
*/

pub fn a(val: u64) -> Noun { Noun::Atom(val) }

macro_rules! n {
    [$x:expr, $y:expr] => { ::nock::Noun::Cell(box ::nock::Noun::new($x), box ::nock::Noun::new($y)) };
    [$x:expr, $y:expr, $($ys:expr),+] => { ::nock::Noun::Cell(box ::nock::Noun::new($x), box n![$y, $($ys),+]) };
}

// Re-export hack for testing macros.
mod nock {
    pub use Noun;
}

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

        assert_eq!(n![1, 2], Cell(box Atom(1), box Atom(2)));
        assert_eq!(n![1, n![2, 3]], Cell(box Atom(1), box Cell(box Atom(2), box Atom(3))));
        assert_eq!(n![1, 2, 3], Cell(box Atom(1), box Cell(box Atom(2), box Atom(3))));
        assert_eq!(n![n![1, 2], 3], Cell(box Cell(box Atom(1), box Atom(2)), box Atom(3)));
        assert_eq!(n![n![1, 2], n![3, 4]], Cell(box Cell(box Atom(1), box Atom(2)), box Cell(box Atom(3), box Atom(4))));
        assert_eq!(n![n![1, 2], n![3, 4], n![5, 6]],
                   Cell(box Cell(box Atom(1), box Atom(2)),
                   box Cell(box Cell(box Atom(3), box Atom(4)),
                   box Cell(box Atom(5), box Atom(6)))));
    }
#[test]
    fn test_eval() {
        use super::Op::*;
        use super::{a, eval};

        // Examples from https://github.com/cgyarvin/urbit/blob/master/doc/book/1-nock.markdown

        assert_eq!(eval(Tis, n![0, 0]), Ok(a(0)));
        assert_eq!(eval(Tis, n![2, 2]), Ok(a(0)));
        assert_eq!(eval(Tis, n![0, 1]), Ok(a(1)));

        assert_eq!(eval(Fas, n![1, n![n![4, 5], n![6, 14, 15]]]), Ok(n![n![4, 5], n![6, 14, 15]]));
        assert_eq!(eval(Fas, n![2, n![n![4, 5], n![6, 14, 15]]]), Ok(n![4, 5]));
        assert_eq!(eval(Fas, n![3, n![n![4, 5], n![6, 14, 15]]]), Ok(n![6, 14, 15]));
        assert_eq!(eval(Fas, n![7, n![n![4, 5], n![6, 14, 15]]]), Ok(n![14, 15]));
    }

#[test]
    fn test_parse() {
        use super::Noun;

        assert!("".parse::<Noun>().is_err());
        assert!("[]".parse::<Noun>().is_err());
        assert!("[1]".parse::<Noun>().is_err());
        assert!("[x y]".parse::<Noun>().is_err());
        assert_eq!("[1 2]".parse::<Noun>(), Ok(n![1, 2]));
        assert_eq!("[1 2 3]".parse::<Noun>(), Ok(n![1, 2, 3]));
        assert_eq!("[[1 2] 3]".parse::<Noun>(), Ok(n![n![1, 2], 3]));
        assert_eq!("[1 [2 3]]".parse::<Noun>(), Ok(n![1, n![2, 3]]));
    }
}
<|endoftext|>


<commit_before>//! A machine learning library for supervised regression trainings
//!
//! This library wants to enable its user to write training algorithms
//! independent of the model trained or the cost function tried to
//! minimize.
//! Consequently its two main traits are currently `Model` and `Cost`.
//! The two submodules `model` and `cost` provide ready to use
//! implementations of said traits.

#![warn(missing_docs)]

extern crate num;

use std::iter::Iterator;
use num::{Zero, One, Float};

/// A Model is defines how to predict a target from an input
///
/// A model usually depends on several coefficents whose values
/// are derived using a training algorithm
pub trait Model : Clone{
    /// Input features
    type Input;
    /// Target type
    type Target : Float;

    /// Predicts a target for the inputs based on the internal coefficents
    fn predict(&self, &Self::Input) -> Self::Target;

    /// The number of internal coefficents this model depends on
    fn num_coefficents(&self) -> usize;

    /// Value predict derived by the n-th `coefficent` at `input`
    fn gradient(&self, coefficent : usize, input : &Self::Input) -> Self::Target;

    /// Mutable reference to the n-th `coefficent`
    fn coefficent(& mut self, coefficent : usize) -> & mut Self::Target;
}

/// Cost functions those value is supposed be minimized by the training algorithm
pub trait Cost{

    /// Error type used by the cost function
    ///
    /// Usually `f64` or `f32`
    type Error : Float;

    /// Value of the cost function derived by the n-th coefficent at x expressed in Error(x) and dY(x)/dx
    ///
    /// This method is called by SGD based training algorithm in order to
    /// determine the delta of the coefficents
    fn gradient(&self, error : Self::Error, gradient_error_by_coefficent : Self::Error) -> Self::Error;
}

/// Changes all coefficents of model based on their derivation of the cost function at features
///
/// Can be used to implement stochastic or batch gradient descent
pub fn inert_gradient_descent_step<C, M>(
    cost : &C,
    model : &mut M,
    features : &M::Input,
    truth : M::Target,
    learning_rate : M::Target,
    inertia : M::Target,
    velocity : & mut Vec<M::Target>
)
    where C : Cost, M : Model<Target=C::Error>
{
    let inv_inertia = M::Target::one() - inertia;
    let prediction = model.predict(&features);
    let error = prediction - truth;

    for ci in 0..model.num_coefficents(){

        velocity[ci] = inertia * velocity[ci] - inv_inertia * learning_rate * cost.gradient(error, model.gradient(ci, features));
        *model.coefficent(ci) = *model.coefficent(ci) + velocity[ci];
    }
}

/// An SGD training step with a velocity term
///
/// Will not get stuck on saddle points as easily as a plain SGD and will converge quicker in general.
/// A good default for `inertia` is 0.9
pub fn gradient_descent_step<C, M>(cost : &C, model : &mut M, features : &M::Input, truth : M::Target, learning_rate : M::Target)
    where C : Cost, M : Model<Target=C::Error>
{
    let prediction = model.predict(&features);
    let error = prediction - truth;

    for ci in 0..model.num_coefficents(){
        *model.coefficent(ci) = *model.coefficent(ci) - learning_rate * cost.gradient(error, model.gradient(ci, features));
    }
}

/// Applies a plain SGD training step to model once for every event in history using a constant learning rate
pub fn stochastic_gradient_descent<C, M, H>(cost : &C, start : M, history : H, learning_rate : M::Target) -> M
    where C : Cost,
    M : Model<Target=C::Error>,
    H : Iterator<Item=(M::Input, M::Target)>
{

    let mut next = start.clone();
    for (features, truth) in history{

        gradient_descent_step(cost, & mut next, &features, truth, learning_rate);
    }

    next
}

/// SGD tranining with constant learning rate and velocity
///
/// Velocity avoids being stuck on saddle points during optimization
/// A good default for `inertia` is 0.9
pub fn inert_stochastic_gradient_descent<C, M, H>(
    cost : &C,
    start : M,
    history : H,
    learning_rate : M::Target,
    inertia : M::Target
) -> M
    where C : Cost,
    M : Model<Target=C::Error>,
    H : Iterator<Item=(M::Input, M::Target)>
{

    let mut velocity = Vec::new();
    velocity.resize(start.num_coefficents(), M::Target::zero());
    let mut next = start.clone();
    for (features, truth) in history{

        inert_gradient_descent_step(cost, & mut next, &features, truth, learning_rate, inertia, & mut velocity);
    }

    next
}

/// Implementations of `Model` trait
pub mod model;
/// Implementations of `Cost` trait
pub mod cost;
/// Defines linear algebra traits used for some model parameters
pub mod linear_algebra;

#[cfg(test)]
mod tests {

    #[test]
    fn estimate_median() {

        use model::Constant;
        use cost::LeastAbsoluteDeviation;
        use gradient_descent_step;

        let features = ();
        let history = [1.0, 3.0, 4.0, 7.0, 8.0, 11.0, 29.0]; //median is seven

        let cost = LeastAbsoluteDeviation{};
        let mut model = Constant{c : 0.0};

        let learning_rate_start = 0.4;
        let learning_rate_stop = 0.001;
        let num_steps = 200;
        let learning_rate_gradient = (learning_rate_start - learning_rate_stop) / (num_steps as f64);

        for (count_step, &truth) in history.iter().cycle().take(num_steps).enumerate(){

            let adapted_learning_rate = learning_rate_stop + learning_rate_gradient * (num_steps - count_step) as f64;
            gradient_descent_step(&cost, & mut model, &features, truth, adapted_learning_rate);
            println!("model: {:?}, learning_rate: {:?}", model, adapted_learning_rate);
        }

        assert!(model.c < 7.1);
        assert!(model.c > 6.9);
    }

    #[test]
    fn estimate_mean() {

        use model::Constant;
        use cost::LeastSquares;
        use gradient_descent_step;

        let features = ();
        let history = [1f64, 3.0, 4.0, 7.0, 8.0, 11.0, 29.0]; //mean is 9

        let cost = LeastSquares{};
        let mut model = Constant{c : 0.0};

        let learning_rate_start = 0.4;
        let learning_rate_stop = 0.001;
        let num_steps = 60;
        let learning_rate_gradient = (learning_rate_start - learning_rate_stop) / (num_steps as f64);

        for (count_step, &truth) in history.iter().cycle().take(num_steps).enumerate(){

            let adapted_learning_rate = learning_rate_stop + learning_rate_gradient * (num_steps - count_step) as f64;
            gradient_descent_step(&cost, & mut model, &features, truth, adapted_learning_rate);
            println!("model: {:?}, learning_rate: {:?}", model, adapted_learning_rate);
        }

        assert!(model.c < 9.1);
        assert!(model.c > 8.9);
    }

    #[test]
    fn linear_stochastic_gradient_descent() {

        use cost::LeastSquares;
        use model::Linear;
        use stochastic_gradient_descent;

        let history = [(0f64, 3f64), (1.0, 4.0), (2.0, 5.0)];

        let start = Linear{m : 0.0, c : 0.0};

        let learning_rate = 0.2;

        let cost = LeastSquares{};
        let model = stochastic_gradient_descent(&cost, start, history.iter().cycle().take(20).cloned(), learning_rate);

        assert!(model.m < 1.1);
        assert!(model.m > 0.9);
        assert!(model.c < 3.1);
        assert!(model.c > 2.9);
    }

    #[test]
    fn linear_stochastic_gradient_descent_iter() {

        use model::Linear;
        use gradient_descent_step;
        use cost::LeastSquares;

        let history = [(0f64, 3f64), (1.0, 4.0), (2.0, 5.0)];

        let cost = LeastSquares{};
        let mut model = Linear{m : 0.0, c : 0.0};

        let learning_rate = 0.2;

        for &(features, truth) in history.iter().cycle().take(20){

            gradient_descent_step(&cost, & mut model, &features, truth, learning_rate);
            println!("model: {:?}", model);
        }

        assert!(model.m < 1.1);
        assert!(model.m > 0.9);
        assert!(model.c < 3.1);
        assert!(model.c > 2.9);
    }

    #[test]
    fn linear_sgd_2d(){
        use cost::LeastSquares;
        use model::Linear;
        use inert_stochastic_gradient_descent;

        let history = [([0.0, 7.0], 17.0), ([1.0, 2.0], 8.0), ([2.0, -2.0], 1.0)];

        let start = Linear{m : [0.0, 0.0], c : 0.0};

        let learning_rate = 0.1;

        let cost = LeastSquares{};
        let model = inert_stochastic_gradient_descent(
            &cost, start,
            history.iter().cycle().take(15000).cloned(),
            learning_rate, 0.9
        );

        println!("{:?}", model);

        assert!(model.m[0] < 1.1);
        assert!(model.m[0] > 0.9);
        assert!(model.m[1] < 2.1);
        assert!(model.m[1] > 1.9);
        assert!(model.c < 3.1);
        assert!(model.c > 2.9);
    }

    #[test]
    fn logistic_sgd_2d(){
        use cost::LeastSquares;
        use model::{Logicstic, Linear};
        use stochastic_gradient_descent;

        use Model;

        let history = [
            ([2.7810836, 2.550537003], 0.0),
            ([1.465489372, 2.362125076], 0.0),
            ([3.396561688, 4.400293529], 0.0),
            ([1.38807019, 1.850220317], 0.0),
            ([3.06407232, 3.005305973], 0.0),
            ([7.627531214, 2.759262235], 1.0),
            ([5.332441248, 2.088626775], 1.0),
            ([6.922596716, 1.77106367], 1.0),
            ([8.675418651, -0.242068655], 1.0),
            ([7.673756466, 3.508563011], 1.0)
        ];

        let start = Logicstic{ linear: Linear{m : [0.0, 0.0], c : 0.0}};

        let learning_rate = 0.3;

        let cost = LeastSquares{};
        let model = stochastic_gradient_descent(
            &cost, start,
            history.iter().cycle().take(40).cloned(),
            learning_rate
        );

        println!("{:?}", model.linear);

        let classification_errors = history.iter()
            .map(|&(input, truth)| model.predict(&input).round() == truth)
            .fold(0, |errors, correct| if correct { errors } else { errors + 1 });

        assert_eq!(0, classification_errors);
    }
}
<commit_msg>fix: documentation of sgd and inert_sgd switched<commit_after>//! A machine learning library for supervised regression trainings
//!
//! This library wants to enable its user to write training algorithms
//! independent of the model trained or the cost function tried to
//! minimize.
//! Consequently its two main traits are currently `Model` and `Cost`.
//! The two submodules `model` and `cost` provide ready to use
//! implementations of said traits.

#![warn(missing_docs)]

extern crate num;

use std::iter::Iterator;
use num::{Zero, One, Float};

/// A Model is defines how to predict a target from an input
///
/// A model usually depends on several coefficents whose values
/// are derived using a training algorithm
pub trait Model : Clone{
    /// Input features
    type Input;
    /// Target type
    type Target : Float;

    /// Predicts a target for the inputs based on the internal coefficents
    fn predict(&self, &Self::Input) -> Self::Target;

    /// The number of internal coefficents this model depends on
    fn num_coefficents(&self) -> usize;

    /// Value predict derived by the n-th `coefficent` at `input`
    fn gradient(&self, coefficent : usize, input : &Self::Input) -> Self::Target;

    /// Mutable reference to the n-th `coefficent`
    fn coefficent(& mut self, coefficent : usize) -> & mut Self::Target;
}

/// Cost functions those value is supposed be minimized by the training algorithm
pub trait Cost{

    /// Error type used by the cost function
    ///
    /// Usually `f64` or `f32`
    type Error : Float;

    /// Value of the cost function derived by the n-th coefficent at x expressed in Error(x) and dY(x)/dx
    ///
    /// This method is called by SGD based training algorithm in order to
    /// determine the delta of the coefficents
    fn gradient(&self, error : Self::Error, gradient_error_by_coefficent : Self::Error) -> Self::Error;
}

/// Changes all coefficents of model based on their derivation of the cost function at features
///
/// Will not get stuck on saddle points as easily as a plain SGD and will converge quicker in general.
/// A good default for `inertia` is 0.9
pub fn inert_gradient_descent_step<C, M>(
    cost : &C,
    model : &mut M,
    features : &M::Input,
    truth : M::Target,
    learning_rate : M::Target,
    inertia : M::Target,
    velocity : & mut Vec<M::Target>
)
    where C : Cost, M : Model<Target=C::Error>
{
    let inv_inertia = M::Target::one() - inertia;
    let prediction = model.predict(&features);
    let error = prediction - truth;

    for ci in 0..model.num_coefficents(){

        velocity[ci] = inertia * velocity[ci] - inv_inertia * learning_rate * cost.gradient(error, model.gradient(ci, features));
        *model.coefficent(ci) = *model.coefficent(ci) + velocity[ci];
    }
}

/// An SGD training step with a velocity term
///
/// Can be used to implement stochastic or batch gradient descent
pub fn gradient_descent_step<C, M>(cost : &C, model : &mut M, features : &M::Input, truth : M::Target, learning_rate : M::Target)
    where C : Cost, M : Model<Target=C::Error>
{
    let prediction = model.predict(&features);
    let error = prediction - truth;

    for ci in 0..model.num_coefficents(){
        *model.coefficent(ci) = *model.coefficent(ci) - learning_rate * cost.gradient(error, model.gradient(ci, features));
    }
}

/// Applies a plain SGD training step to model once for every event in history using a constant learning rate
pub fn stochastic_gradient_descent<C, M, H>(cost : &C, start : M, history : H, learning_rate : M::Target) -> M
    where C : Cost,
    M : Model<Target=C::Error>,
    H : Iterator<Item=(M::Input, M::Target)>
{

    let mut next = start.clone();
    for (features, truth) in history{

        gradient_descent_step(cost, & mut next, &features, truth, learning_rate);
    }

    next
}

/// SGD tranining with constant learning rate and velocity
///
/// Velocity avoids being stuck on saddle points during optimization
/// A good default for `inertia` is 0.9
pub fn inert_stochastic_gradient_descent<C, M, H>(
    cost : &C,
    start : M,
    history : H,
    learning_rate : M::Target,
    inertia : M::Target
) -> M
    where C : Cost,
    M : Model<Target=C::Error>,
    H : Iterator<Item=(M::Input, M::Target)>
{

    let mut velocity = Vec::new();
    velocity.resize(start.num_coefficents(), M::Target::zero());
    let mut next = start.clone();
    for (features, truth) in history{

        inert_gradient_descent_step(cost, & mut next, &features, truth, learning_rate, inertia, & mut velocity);
    }

    next
}

/// Implementations of `Model` trait
pub mod model;
/// Implementations of `Cost` trait
pub mod cost;
/// Defines linear algebra traits used for some model parameters
pub mod linear_algebra;

#[cfg(test)]
mod tests {

    #[test]
    fn estimate_median() {

        use model::Constant;
        use cost::LeastAbsoluteDeviation;
        use gradient_descent_step;

        let features = ();
        let history = [1.0, 3.0, 4.0, 7.0, 8.0, 11.0, 29.0]; //median is seven

        let cost = LeastAbsoluteDeviation{};
        let mut model = Constant{c : 0.0};

        let learning_rate_start = 0.4;
        let learning_rate_stop = 0.001;
        let num_steps = 200;
        let learning_rate_gradient = (learning_rate_start - learning_rate_stop) / (num_steps as f64);

        for (count_step, &truth) in history.iter().cycle().take(num_steps).enumerate(){

            let adapted_learning_rate = learning_rate_stop + learning_rate_gradient * (num_steps - count_step) as f64;
            gradient_descent_step(&cost, & mut model, &features, truth, adapted_learning_rate);
            println!("model: {:?}, learning_rate: {:?}", model, adapted_learning_rate);
        }

        assert!(model.c < 7.1);
        assert!(model.c > 6.9);
    }

    #[test]
    fn estimate_mean() {

        use model::Constant;
        use cost::LeastSquares;
        use gradient_descent_step;

        let features = ();
        let history = [1f64, 3.0, 4.0, 7.0, 8.0, 11.0, 29.0]; //mean is 9

        let cost = LeastSquares{};
        let mut model = Constant{c : 0.0};

        let learning_rate_start = 0.4;
        let learning_rate_stop = 0.001;
        let num_steps = 60;
        let learning_rate_gradient = (learning_rate_start - learning_rate_stop) / (num_steps as f64);

        for (count_step, &truth) in history.iter().cycle().take(num_steps).enumerate(){

            let adapted_learning_rate = learning_rate_stop + learning_rate_gradient * (num_steps - count_step) as f64;
            gradient_descent_step(&cost, & mut model, &features, truth, adapted_learning_rate);
            println!("model: {:?}, learning_rate: {:?}", model, adapted_learning_rate);
        }

        assert!(model.c < 9.1);
        assert!(model.c > 8.9);
    }

    #[test]
    fn linear_stochastic_gradient_descent() {

        use cost::LeastSquares;
        use model::Linear;
        use stochastic_gradient_descent;

        let history = [(0f64, 3f64), (1.0, 4.0), (2.0, 5.0)];

        let start = Linear{m : 0.0, c : 0.0};

        let learning_rate = 0.2;

        let cost = LeastSquares{};
        let model = stochastic_gradient_descent(&cost, start, history.iter().cycle().take(20).cloned(), learning_rate);

        assert!(model.m < 1.1);
        assert!(model.m > 0.9);
        assert!(model.c < 3.1);
        assert!(model.c > 2.9);
    }

    #[test]
    fn linear_stochastic_gradient_descent_iter() {

        use model::Linear;
        use gradient_descent_step;
        use cost::LeastSquares;

        let history = [(0f64, 3f64), (1.0, 4.0), (2.0, 5.0)];

        let cost = LeastSquares{};
        let mut model = Linear{m : 0.0, c : 0.0};

        let learning_rate = 0.2;

        for &(features, truth) in history.iter().cycle().take(20){

            gradient_descent_step(&cost, & mut model, &features, truth, learning_rate);
            println!("model: {:?}", model);
        }

        assert!(model.m < 1.1);
        assert!(model.m > 0.9);
        assert!(model.c < 3.1);
        assert!(model.c > 2.9);
    }

    #[test]
    fn linear_sgd_2d(){
        use cost::LeastSquares;
        use model::Linear;
        use inert_stochastic_gradient_descent;

        let history = [([0.0, 7.0], 17.0), ([1.0, 2.0], 8.0), ([2.0, -2.0], 1.0)];

        let start = Linear{m : [0.0, 0.0], c : 0.0};

        let learning_rate = 0.1;

        let cost = LeastSquares{};
        let model = inert_stochastic_gradient_descent(
            &cost, start,
            history.iter().cycle().take(15000).cloned(),
            learning_rate, 0.9
        );

        println!("{:?}", model);

        assert!(model.m[0] < 1.1);
        assert!(model.m[0] > 0.9);
        assert!(model.m[1] < 2.1);
        assert!(model.m[1] > 1.9);
        assert!(model.c < 3.1);
        assert!(model.c > 2.9);
    }

    #[test]
    fn logistic_sgd_2d(){
        use cost::LeastSquares;
        use model::{Logicstic, Linear};
        use stochastic_gradient_descent;

        use Model;

        let history = [
            ([2.7810836, 2.550537003], 0.0),
            ([1.465489372, 2.362125076], 0.0),
            ([3.396561688, 4.400293529], 0.0),
            ([1.38807019, 1.850220317], 0.0),
            ([3.06407232, 3.005305973], 0.0),
            ([7.627531214, 2.759262235], 1.0),
            ([5.332441248, 2.088626775], 1.0),
            ([6.922596716, 1.77106367], 1.0),
            ([8.675418651, -0.242068655], 1.0),
            ([7.673756466, 3.508563011], 1.0)
        ];

        let start = Logicstic{ linear: Linear{m : [0.0, 0.0], c : 0.0}};

        let learning_rate = 0.3;

        let cost = LeastSquares{};
        let model = stochastic_gradient_descent(
            &cost, start,
            history.iter().cycle().take(40).cloned(),
            learning_rate
        );

        println!("{:?}", model.linear);

        let classification_errors = history.iter()
            .map(|&(input, truth)| model.predict(&input).round() == truth)
            .fold(0, |errors, correct| if correct { errors } else { errors + 1 });

        assert_eq!(0, classification_errors);
    }
}
<|endoftext|>


<commit_before>/*!
rust-memcache is a [Memcached](https://memcached.org/) client written in pure rust.

# Install:

The crate is called `memcache` and you can depend on it via cargo:

```ini
[dependencies]
memcache = "*"
```

# Features:

- <input type="checkbox"  disabled checked /> Binary protocal
- <input type="checkbox"  disabled checked /> TCP connection
- <input type="checkbox"  disabled /> UDP connection
- <input type="checkbox"  disabled checked/> UNIX Domain socket connection
- <input type="checkbox"  disabled /> Automatically compress
- <input type="checkbox"  disabled /> Automatically serialize to JSON / msgpack etc.
- <input type="checkbox"  disabled checked /> Typed interface
- <input type="checkbox"  disabled checkbox /> Mutiple server support with custom key hash algorithm

# Basic usage:

```rust
// create connection with to memcached server node:
let mut client = memcache::Client::new("memcache://127.0.0.1:12345").unwrap();

// flush the database:
client.flush().unwrap();

// set a string value:
client.set("foo", "bar", 0).unwrap();

// retrieve from memcached:
let value: Option<String> = client.get("foo").unwrap();
assert_eq!(value, Some(String::from("bar")));
assert_eq!(value.unwrap(), "bar");

// prepend, append:
client.prepend("foo", "foo").unwrap();
client.append("foo", "baz").unwrap();
let value: String = client.get("foo").unwrap().unwrap();
assert_eq!(value, "foobarbaz");

// delete value:
client.delete("foo").unwrap();

// using counter:
client.set("counter", 40, 0).unwrap();
client.increment("counter", 2).unwrap();
let answer: i32 = client.get("counter").unwrap().unwrap();
assert_eq!(answer, 42);
```
!*/

extern crate byteorder;
extern crate url;

mod connection;
mod error;
mod value;
mod packet;
mod client;

pub use error::MemcacheError;
pub use value::{ToMemcacheValue, FromMemcacheValue};
pub use client::Client;
<commit_msg>:beers: exporse memcache::Connectable<commit_after>/*!
rust-memcache is a [Memcached](https://memcached.org/) client written in pure rust.

# Install:

The crate is called `memcache` and you can depend on it via cargo:

```ini
[dependencies]
memcache = "*"
```

# Features:

- <input type="checkbox"  disabled checked /> Binary protocal
- <input type="checkbox"  disabled checked /> TCP connection
- <input type="checkbox"  disabled /> UDP connection
- <input type="checkbox"  disabled checked/> UNIX Domain socket connection
- <input type="checkbox"  disabled /> Automatically compress
- <input type="checkbox"  disabled /> Automatically serialize to JSON / msgpack etc.
- <input type="checkbox"  disabled checked /> Typed interface
- <input type="checkbox"  disabled checkbox /> Mutiple server support with custom key hash algorithm

# Basic usage:

```rust
// create connection with to memcached server node:
let mut client = memcache::Client::new("memcache://127.0.0.1:12345").unwrap();

// flush the database:
client.flush().unwrap();

// set a string value:
client.set("foo", "bar", 0).unwrap();

// retrieve from memcached:
let value: Option<String> = client.get("foo").unwrap();
assert_eq!(value, Some(String::from("bar")));
assert_eq!(value.unwrap(), "bar");

// prepend, append:
client.prepend("foo", "foo").unwrap();
client.append("foo", "baz").unwrap();
let value: String = client.get("foo").unwrap().unwrap();
assert_eq!(value, "foobarbaz");

// delete value:
client.delete("foo").unwrap();

// using counter:
client.set("counter", 40, 0).unwrap();
client.increment("counter", 2).unwrap();
let answer: i32 = client.get("counter").unwrap().unwrap();
assert_eq!(answer, 42);
```
!*/

extern crate byteorder;
extern crate url;

mod connection;
mod error;
mod value;
mod packet;
mod client;

pub use error::MemcacheError;
pub use value::{ToMemcacheValue, FromMemcacheValue};
pub use client::{Client, Connectable};
<|endoftext|>