<commit_before>#![allow(dead_code)]
#![allow(unused_variables)]
extern crate capnp;

use std::{error, fmt, str};

use index::Index;
use key_builder::KeyBuilder;
use stems::{StemmedWord, Stems};

// TODO vmx 2016-11-02: Make it import "rocksdb" properly instead of needing to import the individual tihngs
use rocksdb::{DBIterator, SeekKey};
use rocksdb::rocksdb::Snapshot;
use records_capnp::payload;

#[derive(Debug)]
enum Error<'a> {
    Parse(&'a str),
    Capnp(capnp::Error),
}

impl<'a> error::Error for Error<'a> {
    fn description(&self) -> &str {
        match *self {
            Error::Parse(description) => description,
            Error::Capnp(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Parse(_) => None,
            Error::Capnp(ref err) => Some(err as &error::Error),
        }
    }
}

impl<'a> From<capnp::Error> for Error<'a> {
    fn from(err: capnp::Error) -> Error<'a> {
        Error::Capnp(err)
    }
}

impl<'a> fmt::Display for Error<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Parse(ref err) => write!(f, "Parse error: {}", err),
            Error::Capnp(ref err) => write!(f, "Capnproto error: {}", err),
        }
    }
}

struct DocResult {
    seq: u64,
    array_paths: Vec<Vec<u64>>,
}

impl DocResult {
    fn new() -> DocResult {
        DocResult {
            seq: 0,
            array_paths: Vec::new(),
        }
    }
}

//trait QueryRuntimeFilter {
//struct QueryRuntimeFilter {}

trait QueryRuntimeFilter {
    fn first_result(&mut self, start_id: u64) -> Result<Option<DocResult>, Error>;
    fn next_result(&mut self) -> Result<Option<DocResult>, Error>;
}

pub struct Query {}

pub struct QueryResults {
}

//struct SnapshotIteratorCreator {
//    snapshot: rocksdb::Snapshot,
//}
//
//impl SnapshotIteratorCreator {
//    fn new(db: &rocksdb::DB) {
//        let snapshot = rocksdb::Snapshot::new(db);
//        SnapshotIteratorCreator{
//            snapshot: snapshot,
//        }
//    }
//
//    fn new_iterator(&self) {
//        self.snapshot.iter()
//    }
//}

struct ExactMatchFilter<'a> {
    iter: DBIterator<'a>,
    kb: KeyBuilder,
    stemmed_offset: u64,
    suffix: String,
    suffix_offset: u64,
}

impl<'a> ExactMatchFilter<'a> {
    fn new(iter: DBIterator<'a>, stemmed_word: &StemmedWord, mut kb: KeyBuilder) -> ExactMatchFilter<'a> {
        kb.push_word(&stemmed_word.stemmed);
        ExactMatchFilter{
            iter: iter,
            kb: kb,
            stemmed_offset: stemmed_word.stemmed_offset as u64,
            suffix: stemmed_word.suffix.clone(),
            suffix_offset: stemmed_word.suffix_offset as u64,
        }
    }
}

impl<'a> QueryRuntimeFilter for ExactMatchFilter<'a> {
    fn first_result(&mut self, start_id: u64) -> Result<Option<DocResult>, Error> {
        // Build the full key
        self.kb.push_doc_seq(start_id);

        // Seek in index to >= entry
        self.iter.seek(SeekKey::from(self.kb.key().as_bytes()));

        // Revert
        self.kb.pop_doc_seq();

        self.next_result()
    }

    fn next_result(&mut self) -> Result<Option<DocResult>, Error> {
        let mut doc_result = DocResult::new();

        loop {
            if !self.iter.valid() {
                return Ok(None)
            }

            // New scope needed as the iter.next() below invalidates the
            // current key and value
            {
                let key = self.iter.key();
                if !key.starts_with(self.kb.key().as_bytes()) {
                    return Ok(None)
                }
                let seq = &key[self.kb.key().len()..];

                let value = self.iter.value();
                // NOTE vmx 2016-10-13: I'm not really sure why the dereferencing is needed
                // and why we pass on mutable reference of it to `read_message()`
                let mut ref_value = &*value;
                let message_reader = ::capnp::serialize_packed::read_message(
                    &mut ref_value, ::capnp::message::ReaderOptions::new()).unwrap();
                let payload = message_reader.get_root::<payload::Reader>().unwrap();

                for aos_wis in try!(payload.get_arrayoffsets_to_wordinfos()).iter() {
                    for wi in try!(aos_wis.get_wordinfos()).iter() {
                        if self.stemmed_offset == wi.get_stemmed_offset() &&
                            self.suffix_offset == wi.get_suffix_offset() &&
                            self.suffix == try!(wi.get_suffix_text()) {
                                // We have a candidate document to return
                                let arrayoffsets = try!(aos_wis.get_arrayoffsets());
                                doc_result.array_paths.push(arrayoffsets.iter().collect::<>());
                                doc_result.seq = str::from_utf8(&seq).unwrap().parse().unwrap();
                                break;
                            }
                    }
                }
            }
            self.iter.next();

            if doc_result.seq > 0 {
                return Ok(Some(doc_result));
            }
        }
    }
}

struct AndFilter<'a> {
    filters: Vec<Box<QueryRuntimeFilter + 'a>>,
    array_depth: u64,
}

impl<'a> AndFilter<'a> {
    fn new(filters: Vec<Box<QueryRuntimeFilter + 'a>>, array_depth: u64) -> AndFilter<'a> {
        AndFilter {
            filters: filters,
            array_depth: array_depth,
        }
   }
}

impl<'a> QueryRuntimeFilter for AndFilter<'a> {
    fn first_result(&mut self, start_id: u64) -> Result<Option<DocResult>, Error> {
        Ok(None)
    }
    fn next_result(&mut self) -> Result<Option<DocResult>, Error> {
        Ok(None)
    }
}

struct Parser<'a> {
    query: &'a str,
    offset: usize,
    kb: KeyBuilder,
    snapshot: &'a Snapshot<'a>,
}

impl<'a> Parser<'a> {
    fn new(query: &'a str, snapshot: &'a Snapshot<'a>) -> Parser<'a> {
        Parser{
            query: query,
            offset: 0,
            kb: KeyBuilder::new(),
            snapshot: &snapshot,
        }
    }

    fn whitespace(&mut self) {
        loop {
            if let Some(char) = self.query[self.offset..].chars().next() {
                // Stop when the character isn't a whitespace
                if !char.is_whitespace() {
                    break;
                }
                self.offset += char.len_utf8();
            }
        }
    }

    fn consume(&mut self, token: &str) -> bool {
        if self.could_consume(token) {
            self.offset += token.len();
            true
        } else {
            false
        }
    }

    fn could_consume(&mut self, token: &str) -> bool {
        self.query[self.offset..].starts_with(token)
    }

    fn consume_field(&mut self) -> Option<String> {
        let mut result = String::new();
        for char in self.query[self.offset..].chars() {
            if char.is_alphanumeric() {
                result.push(char);
            } else {
                break;
            }
        }
        if result.len() > 0 {
            self.offset += result.len();
            self.whitespace();
            Some(result)
        } else {
            None
        }
    }

    fn consume_string_literal(&mut self) -> Result<Option<String>, String> {
        // Does not unescape yet
        let mut lit = String::new();
        if self.consume("\"") {
            for char in self.query[self.offset..].chars() {
                if char != '"' {
                    lit.push(char);
                }
                self.offset += char.len_utf8();
            }
            if self.consume("\"") {
                self.whitespace();
                Ok(Some(lit))
            } else {
                Err("Expected \"".to_string())
            }
        } else {
            Ok(None)
        }
    }

    fn compare<'b>(&'b mut self) -> Result<Box<QueryRuntimeFilter + 'a>, String> {
        match self.consume_field() {
            Some(field) => {
                if self.consume(".") {
                    self.kb.push_object_key(field);
                    let ret = self.compare();
                    self.kb.pop_object_key();
                    ret
                } else if self.consume("=") {
                    match self.consume_string_literal() {
                        Ok(Some(literal)) => {
                            self.kb.push_object_key(field);

                            let stems = Stems::new(&literal);
                            let mut filters: Vec<Box<QueryRuntimeFilter + 'a>> = Vec::new();
                            for stem in stems {
                                let iter = self.snapshot.iter();
                                let filter = Box::new(ExactMatchFilter::new(
                                   iter, &stem, self.kb.clone()));
                                filters.push(filter);
                            }

                            self.kb.pop_object_key();

                            match filters.len() {
                                0 => panic!("Cannot create a ExactMatchFilter"),
                                1 => Ok(filters.pop().unwrap()),
                                _ => Ok(Box::new(AndFilter::<'a>::new(
                                    filters, self.kb.array_depth as u64))),
                                //_ => Ok(filters[0]),
                                //_ => Err("just get it compiled".to_string()),
                            }
                        },
                        // Empty literal
                        Ok(None) => {Err("not implemetned yet".to_string())},
                        Err(error) => {
                            Err(error)
                        }
                    }
                } else {
                    Err("not yet implemented".to_string())
                }
            },
            None => {
                Err("Expected comparison or array operator".to_string())
            }
        }
    }

    fn build_filter(&mut self) -> Result<QueryResults, String> {
        self.whitespace();
        Ok(QueryResults{})
    }
}

impl Query {
    //pub fn get_matches<'a>(query: &str, index: &'a Index) -> Result<QueryResults, String> {
    pub fn get_matches<'a>(query: &str, snapshot: &'a Snapshot) -> Result<QueryResults, String> {
    //        match &index.rocks {
//            &Some(ref rocks) => {
//                let snapshot = Snapshot::new(rocks);
//                let parser = Parser::new(query, &snapshot);
//                Ok(QueryResults{})
//            },
//            &None => {
//                Err("You must open the index first".to_string())
//            },
//        }
        //let rocks = &index.rocks.unwrap();
        // This one would work as well
        //let rocks = index.rocks.as_ref().unwrap();
        //let snapshot = Snapshot::new(rocks);
        let parser = Parser::new(query, &snapshot);
        Ok(QueryResults{})
    }
}

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

    use index::{Index, OpenOptions};

    use rocksdb::Snapshot;

    #[test]
    fn test_whitespace() {
        let mut index = Index::new();
        index.open("test_whitespace", Some(OpenOptions::Create)).unwrap();
        let rocks = &index.rocks.unwrap();
        let snapshot = Snapshot::new(rocks);

        let mut query = " \n \t test";
        let mut parser = Parser::new(query, &snapshot);
        parser.whitespace();
        assert_eq!(parser.offset, 5);

        query = "test";
        parser = Parser::new(query, &snapshot);
        parser.whitespace();
        assert_eq!(parser.offset, 0);
    }
}
<commit_msg>Push current state<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]
extern crate capnp;

use std::{error, fmt, str};

use index::Index;
use key_builder::KeyBuilder;
use stems::{StemmedWord, Stems};

// TODO vmx 2016-11-02: Make it import "rocksdb" properly instead of needing to import the individual tihngs
use rocksdb::{DBIterator, SeekKey};
use rocksdb::rocksdb::Snapshot;
use records_capnp::payload;

#[derive(Debug)]
enum Error {
    Parse(String),
    Capnp(capnp::Error),
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Parse(ref description) => description,
            Error::Capnp(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Parse(_) => None,
            Error::Capnp(ref err) => Some(err as &error::Error),
        }
    }
}

impl From<capnp::Error> for Error {
    fn from(err: capnp::Error) -> Error {
        Error::Capnp(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Parse(ref err) => write!(f, "Parse error: {}", err),
            Error::Capnp(ref err) => write!(f, "Capnproto error: {}", err),
        }
    }
}

struct DocResult {
    seq: u64,
    array_paths: Vec<Vec<u64>>,
}

impl DocResult {
    fn new() -> DocResult {
        DocResult {
            seq: 0,
            array_paths: Vec::new(),
        }
    }

    fn truncate_array_paths(&mut self, array_depth: usize) {
        for array_path in self.array_paths.iter_mut() {
            debug_assert!(array_path.len() >= array_depth);
            array_path.resize(array_depth, 0);
        }
    }

    fn intersect_array_paths(aa: &DocResult, bb: &DocResult) -> Option<DocResult> {
        let mut doc_result = DocResult::new();
        debug_assert_eq!(aa.seq, bb.seq);
        doc_result.seq = aa.seq;
        for array_path_a in &aa.array_paths {
            for array_path_b in &bb.array_paths {
                if array_path_a == array_path_b {
                    doc_result.array_paths.push(array_path_a.clone());
                }
            }
        }
        if doc_result.array_paths.is_empty() {
            None
        } else {
            Some(doc_result)
        }
    }
}

//trait QueryRuntimeFilter {
//struct QueryRuntimeFilter {}

trait QueryRuntimeFilter {
    fn first_result(&mut self, start_id: u64) -> Result<Option<DocResult>, Error>;
    fn next_result(&mut self) -> Result<Option<DocResult>, Error>;
}

pub struct Query {}

pub struct QueryResults {
}

//struct SnapshotIteratorCreator {
//    snapshot: rocksdb::Snapshot,
//}
//
//impl SnapshotIteratorCreator {
//    fn new(db: &rocksdb::DB) {
//        let snapshot = rocksdb::Snapshot::new(db);
//        SnapshotIteratorCreator{
//            snapshot: snapshot,
//        }
//    }
//
//    fn new_iterator(&self) {
//        self.snapshot.iter()
//    }
//}

struct ExactMatchFilter<'a> {
    iter: DBIterator<'a>,
    kb: KeyBuilder,
    stemmed_offset: u64,
    suffix: String,
    suffix_offset: u64,
}

impl<'a> ExactMatchFilter<'a> {
    fn new(iter: DBIterator<'a>, stemmed_word: &StemmedWord, mut kb: KeyBuilder) -> ExactMatchFilter<'a> {
        kb.push_word(&stemmed_word.stemmed);
        ExactMatchFilter{
            iter: iter,
            kb: kb,
            stemmed_offset: stemmed_word.stemmed_offset as u64,
            suffix: stemmed_word.suffix.clone(),
            suffix_offset: stemmed_word.suffix_offset as u64,
        }
    }
}

impl<'a> QueryRuntimeFilter for ExactMatchFilter<'a> {
    fn first_result(&mut self, start_id: u64) -> Result<Option<DocResult>, Error> {
        // Build the full key
        self.kb.push_doc_seq(start_id);

        // Seek in index to >= entry
        self.iter.seek(SeekKey::from(self.kb.key().as_bytes()));

        // Revert
        self.kb.pop_doc_seq();

        self.next_result()
    }

    fn next_result(&mut self) -> Result<Option<DocResult>, Error> {
        let mut doc_result = DocResult::new();

        loop {
            if !self.iter.valid() {
                return Ok(None)
            }

            // New scope needed as the iter.next() below invalidates the
            // current key and value
            {
                let key = self.iter.key();
                if !key.starts_with(self.kb.key().as_bytes()) {
                    return Ok(None)
                }
                let seq = &key[self.kb.key().len()..];

                let value = self.iter.value();
                // NOTE vmx 2016-10-13: I'm not really sure why the dereferencing is needed
                // and why we pass on mutable reference of it to `read_message()`
                let mut ref_value = &*value;
                let message_reader = ::capnp::serialize_packed::read_message(
                    &mut ref_value, ::capnp::message::ReaderOptions::new()).unwrap();
                let payload = message_reader.get_root::<payload::Reader>().unwrap();

                for aos_wis in try!(payload.get_arrayoffsets_to_wordinfos()).iter() {
                    for wi in try!(aos_wis.get_wordinfos()).iter() {
                        if self.stemmed_offset == wi.get_stemmed_offset() &&
                            self.suffix_offset == wi.get_suffix_offset() &&
                            self.suffix == try!(wi.get_suffix_text()) {
                                // We have a candidate document to return
                                let arrayoffsets = try!(aos_wis.get_arrayoffsets());
                                doc_result.array_paths.push(arrayoffsets.iter().collect::<>());
                                doc_result.seq = str::from_utf8(&seq).unwrap().parse().unwrap();
                                break;
                            }
                    }
                }
            }
            self.iter.next();

            if doc_result.seq > 0 {
                return Ok(Some(doc_result));
            }
        }
    }
}

struct DummyFilter {}

impl QueryRuntimeFilter for DummyFilter {
    fn first_result(&mut self, start_id: u64) -> Result<Option<DocResult>, Error> {
        Ok(None)
    }
    fn next_result(&mut self) -> Result<Option<DocResult>, Error> {
        Ok(None)
    }
}

struct AndFilter<'a> {
    filters: Vec<Box<QueryRuntimeFilter + 'a>>,
    current_filter: usize,
    array_depth: usize,
}

impl<'a> AndFilter<'a> {
    fn new(filters: Vec<Box<QueryRuntimeFilter + 'a>>, array_depth: usize) -> AndFilter<'a> {
        AndFilter {
            filters: filters,
            current_filter: 0,
            array_depth: array_depth,
        }
   }

    fn result(&mut self, base: Option<DocResult>) -> Result<Option<DocResult>, Error> {
        let mut matches_count = self.filters.len();
        // TODO vmx 2016-11-04: Make it nicer
        let mut base_result = match base {
            Some(base_result) => base_result,
            None => return Ok(None),
        };
        loop {
            base_result.truncate_array_paths(self.array_depth);

            self.current_filter += 1;
            if self.current_filter > self.filters.len() {
                self.current_filter = 0;
            }

            let next = try!(self.filters[self.current_filter].first_result(base_result.seq));
            let mut next_result = match next {
                Some(next_result) => next_result,
                None => return Ok(None),
            };
            next_result.truncate_array_paths(self.array_depth);

            if base_result.seq == next_result.seq {
                match DocResult::intersect_array_paths(&base_result, &next_result) {
                    Some(new_result) => {
                        base_result = new_result;
                        matches_count -= 1;
                    },
                    None => {
                        let new_result = try!(self.filters[self.current_filter].first_result(base_result.seq));
                        base_result = match new_result {
                            Some(base_result) => base_result,
                            None => return Ok(None),
                        };
                        matches_count = self.filters.len()
                    }
                }
            } else {
                base_result = next_result;
                matches_count = self.filters.len();
            }
        }
    }
}

impl<'a> QueryRuntimeFilter for AndFilter<'a> {
    fn first_result(&mut self, start_id: u64) -> Result<Option<DocResult>, Error> {
        let base_result = try!(self.filters[self.current_filter].first_result(start_id));
        self.result(base_result)
        //Ok(None)
    }

    fn next_result(&mut self) -> Result<Option<DocResult>, Error> {
        //let base_result = try!(self.filters[self.current_filter].next_result());
        //self.result(base_result)
        Ok(None)
    }
}

struct Parser<'a> {
    query: &'a str,
    offset: usize,
    kb: KeyBuilder,
    snapshot: &'a Snapshot<'a>,
}

impl<'a> Parser<'a> {
    fn new(query: &'a str, snapshot: &'a Snapshot<'a>) -> Parser<'a> {
        Parser{
            query: query,
            offset: 0,
            kb: KeyBuilder::new(),
            snapshot: &snapshot,
        }
    }

    fn whitespace(&mut self) {
        loop {
            if let Some(char) = self.query[self.offset..].chars().next() {
                // Stop when the character isn't a whitespace
                if !char.is_whitespace() {
                    break;
                }
                self.offset += char.len_utf8();
            }
        }
    }

    fn consume(&mut self, token: &str) -> bool {
        if self.could_consume(token) {
            self.offset += token.len();
            true
        } else {
            false
        }
    }

    fn could_consume(&mut self, token: &str) -> bool {
        self.query[self.offset..].starts_with(token)
    }

    fn consume_field(&mut self) -> Option<String> {
        let mut result = String::new();
        for char in self.query[self.offset..].chars() {
            if char.is_alphanumeric() {
                result.push(char);
            } else {
                break;
            }
        }
        if result.len() > 0 {
            self.offset += result.len();
            self.whitespace();
            Some(result)
        } else {
            None
        }
    }

    fn consume_string_literal(&mut self) -> Result<Option<String>, String> {
        // Does not unescape yet
        let mut lit = String::new();
        if self.consume("\"") {
            for char in self.query[self.offset..].chars() {
                if char != '"' {
                    lit.push(char);
                }
                self.offset += char.len_utf8();
            }
            if self.consume("\"") {
                self.whitespace();
                Ok(Some(lit))
            } else {
                Err("Expected \"".to_string())
            }
        } else {
            Ok(None)
        }
    }

    fn array() {
        //XXX GO ON HERE 2016-11-04
    }

    fn compare<'b>(&'b mut self) -> Result<Box<QueryRuntimeFilter + 'a>, String> {
        match self.consume_field() {
            Some(field) => {
                if self.consume(".") {
                    self.kb.push_object_key(field);
                    let ret = self.compare();
                    self.kb.pop_object_key();
                    ret
                } else if self.consume("=") {
                    match self.consume_string_literal() {
                        Ok(Some(literal)) => {
                            self.kb.push_object_key(field);

                            let stems = Stems::new(&literal);
                            let mut filters: Vec<Box<QueryRuntimeFilter + 'a>> = Vec::new();
                            for stem in stems {
                                let iter = self.snapshot.iter();
                                let filter = Box::new(ExactMatchFilter::new(
                                   iter, &stem, self.kb.clone()));
                                filters.push(filter);
                            }

                            self.kb.pop_object_key();

                            match filters.len() {
                                0 => panic!("Cannot create a ExactMatchFilter"),
                                1 => Ok(filters.pop().unwrap()),
                                _ => Ok(Box::new(AndFilter::<'a>::new(
                                    filters, self.kb.array_depth))),
                            }
                        },
                        // Empty literal
                        Ok(None) => {Err("Expected string".to_string())},
                        Err(error) => {
                            Err(error)
                        }
                    }
                } else if self.could_consume("[") {
                    self.kb.push_object_key(field);
                    //let ret = self.array();
                    self.kb.pop_object_key();
                    //ret
                    Err("Not yet implemented".to_string())
                } else {
                    Err("Expected comparison or array operator".to_string())
                }
            },
            None => {
                Err("Expected comparison or array operator".to_string())
            }
        }
    }

    fn build_filter(&mut self) -> Result<QueryResults, String> {
        self.whitespace();
        Ok(QueryResults{})
    }
}

impl Query {
    //pub fn get_matches<'a>(query: &str, index: &'a Index) -> Result<QueryResults, String> {
    pub fn get_matches<'a>(query: &str, snapshot: &'a Snapshot) -> Result<QueryResults, String> {
    //        match &index.rocks {
//            &Some(ref rocks) => {
//                let snapshot = Snapshot::new(rocks);
//                let parser = Parser::new(query, &snapshot);
//                Ok(QueryResults{})
//            },
//            &None => {
//                Err("You must open the index first".to_string())
//            },
//        }
        //let rocks = &index.rocks.unwrap();
        // This one would work as well
        //let rocks = index.rocks.as_ref().unwrap();
        //let snapshot = Snapshot::new(rocks);
        let parser = Parser::new(query, &snapshot);
        Ok(QueryResults{})
    }
}

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

    use index::{Index, OpenOptions};

    use rocksdb::Snapshot;

    #[test]
    fn test_whitespace() {
        let mut index = Index::new();
        index.open("test_whitespace", Some(OpenOptions::Create)).unwrap();
        let rocks = &index.rocks.unwrap();
        let snapshot = Snapshot::new(rocks);

        let mut query = " \n \t test";
        let mut parser = Parser::new(query, &snapshot);
        parser.whitespace();
        assert_eq!(parser.offset, 5);

        query = "test";
        parser = Parser::new(query, &snapshot);
        parser.whitespace();
        assert_eq!(parser.offset, 0);
    }
}
<|endoftext|>


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

use std::fmt::Show;
use std::fmt;
use std::str::CharOffsets;

use super::version::Version;

#[deriving(PartialEq,Clone)]
pub struct VersionReq {
    predicates: Vec<Predicate>
}

#[deriving(PartialEq,Clone)]
enum Op {
    Ex,   // Exact
    Gt,   // Greater than
    GtEq, // Greater than or equal to
    Lt,   // Less than
    LtEq  // Less than or equal to
}

#[deriving(PartialEq,Clone)]
struct Predicate {
    op: Op,
    major: u32,
    minor: Option<u32>,
    patch: Option<u32>
}

struct PredBuilder {
    op: Option<Op>,
    major: Option<u32>,
    minor: Option<u32>,
    patch: Option<u32>
}

#[deriving(Show)]
pub enum ReqParseError {
    InvalidVersionRequirement,
    OpAlreadySet,
    InvalidSigil,
    VersionComponentsMustBeNumeric,
    OpRequired,
    MajorVersionRequired,
}

impl VersionReq {
    pub fn any() -> VersionReq {
        VersionReq { predicates: vec!() }
    }

    pub fn parse(input: &str) -> Result<VersionReq, ReqParseError> {
        let mut lexer = Lexer::new(input);
        let mut builder = PredBuilder::new();
        let mut predicates = Vec::new();

        for token in lexer {
            let result = match token {
                Sigil(x) => builder.set_sigil(x),
                AlphaNum(x) => builder.set_version_part(x),
                Dot => Ok(()), // Nothing to do for now
                _ => unimplemented!()
            };

            match result {
                Ok(_) => (),
                Err(e) => return Err(e),
            }
        }

        if lexer.is_error() {
            return Err(InvalidVersionRequirement);
        }

        match builder.build() {
            Ok(e) => predicates.push(e),
            Err(e) => return Err(e),
        }

        Ok(VersionReq { predicates: predicates })
    }

    pub fn exact(version: &Version) -> VersionReq {
        VersionReq { predicates: vec!(Predicate::exact(version)) }
    }

    pub fn matches(&self, version: &Version) -> bool {
        self.predicates.iter().all(|p| p.matches(version))
    }
}

impl Predicate {
    fn exact(version: &Version) -> Predicate {
        Predicate {
            op: Ex,
            major: version.major,
            minor: Some(version.minor),
            patch: Some(version.patch)
        }
    }

    fn matches(&self, ver: &Version) -> bool {
        match self.op {
            Ex => self.is_exact(ver),
            Gt => self.is_greater(ver),
            GtEq => self.is_exact(ver) || self.is_greater(ver),
            _ => false // not implemented
        }
    }

    fn is_exact(&self, ver: &Version) -> bool {
        if self.major != ver.major {
            return false;
        }

        match self.minor {
            Some(minor) => {
                if minor != ver.minor {
                    return false;
                }
            }
            None => return true
        }

        match self.patch {
            Some(patch) => {
                if patch != ver.patch {
                    return false;
                }
            }
            None => return true
        }

        true
    }

    fn is_greater(self, ver: &Version) -> bool {
        if self.major != ver.major {
            return self.major > ver.major;
        }

        match self.minor {
            Some(minor) => {
                if minor != ver.minor {
                    return minor > ver.minor
                }
            }
            None => return false
        }

        match self.patch {
            Some(patch) => {
                if patch != ver.patch {
                    return patch > ver.patch
                }
            }

            None => return false
        }

        false
    }
}

impl PredBuilder {
    fn new() -> PredBuilder {
        PredBuilder {
            op: None,
            major: None,
            minor: None,
            patch: None
        }
    }

    fn set_sigil(&mut self, sigil: &str) -> Result<(), ReqParseError> {
        if self.op.is_some() {
            return Err(OpAlreadySet);
        }

        match Op::from_sigil(sigil) {
            Some(op) => self.op = Some(op),
            _ => return Err(InvalidSigil),
        }

        Ok(())
    }

    fn set_version_part(&mut self, part: &str) -> Result<(), ReqParseError> {
        if self.op.is_none() {
            // If no op is specified, then the predicate is an exact match on
            // the version
            self.op = Some(Ex);
        }

        if self.major.is_none() {
            match parse_version_part(part) {
                Ok(e) => self.major = Some(e),
                Err(e) => return Err(e),
            }
        }
        else if self.minor.is_none() {
            match parse_version_part(part) {
                Ok(e) => self.minor = Some(e),
                Err(e) => return Err(e),
            }
        }
        else if self.patch.is_none() {
            match parse_version_part(part) {
                Ok(e) => self.patch = Some(e),
                Err(e) => return Err(e),
            }
        }

        Ok(())
    }

    /// Validates that a version predicate can be created given the present
    /// information.
    fn build(&self) -> Result<Predicate, ReqParseError> {
        let op = match self.op {
            Some(x) => x,
            None => return Err(OpRequired),
        };

        let major = match self.major {
            Some(x) => x,
            None => return Err(MajorVersionRequired),
        };

        Ok(Predicate {
            op: op,
            major: major,
            minor: self.minor,
            patch: self.patch
        })
    }
}

struct Lexer<'a> {
    c: char,
    idx: uint,
    iter: CharOffsets<'a>,
    mark: Option<uint>,
    input: &'a str,
    state: LexState
}

#[deriving(Show,PartialEq)]
enum LexState {
    LexInit,
    LexStart,
    LexAlphaNum,
    LexSigil,
    LexErr,
    LexWin
}

#[deriving(Show)]
enum Token<'a> {
    Sigil(&'a str),
    AlphaNum(&'a str),
    Comma,
    Dot
}

impl<'a> Lexer<'a> {
    fn new(input: &'a str) -> Lexer<'a> {
        Lexer {
            c: '\0',
            idx: 0,
            iter: input.char_indices(),
            mark: None,
            input: input,
            state: LexInit
        }
    }

    fn is_error(&self) -> bool {
        self.state == LexErr
    }

    fn mark(&mut self, at: uint) {
        self.mark = Some(at)
    }

    fn flush(&mut self, to: uint, kind: LexState) -> Option<Token<'a>> {
        match self.mark {
            Some(mark) => {
                if to <= mark {
                    return None;
                }

                let s = self.input.slice(mark, to);

                self.mark = None;

                match kind {
                    LexAlphaNum => Some(AlphaNum(s)),
                    LexSigil => Some(Sigil(s)),
                    _ => None // bug
                }
            }
            None => None
        }
    }
}

impl<'a> Iterator<Token<'a>> for Lexer<'a> {
    fn next(&mut self) -> Option<Token<'a>> {
        let mut c;
        let mut idx = 0;

        macro_rules! next(
            () => (
                match self.iter.next() {
                    Some((n_idx, n_char)) => {
                        c = n_char;
                        idx = n_idx;
                    }
                    _ => {
                      let s = self.state;
                      return self.flush(idx + 1, s)
                    }
                }
            ))

        macro_rules! flush(
            ($s:expr) => ({
                self.c = c;
                self.idx = idx;
                self.flush(idx, $s)
            }))

        if self.state == LexInit {
            self.state = LexStart;
            next!();
        } else {
            c = self.c;
            idx = self.idx;
        }

        loop {
            match self.state {
                LexStart => {
                    if c.is_whitespace() {
                        next!(); // Ignore
                    }
                    else if c.is_alphanumeric() {
                        self.mark(idx);
                        self.state = LexAlphaNum;
                        next!();
                    }
                    else if is_sigil(c) {
                        self.mark(idx);
                        self.state = LexSigil;
                        next!();
                    }
                    else if c == '.' {
                        self.state = LexInit;
                        return Some(Dot);
                    }
                    else if c == ',' {
                        self.state = LexInit;
                        return Some(Comma);
                    } else {
                        self.state = LexErr;
                        return None;
                    }
                }
                LexAlphaNum => {
                    if c.is_alphanumeric() {
                        next!();
                    } else {
                        self.state = LexStart;
                        return flush!(LexAlphaNum);
                    }
                }
                LexSigil => {
                    if is_sigil(c) {
                        next!();
                    } else {
                        self.state = LexStart;
                        return flush!(LexSigil);
                    }
                }
                LexErr | LexWin => return None,
                LexInit => return None // bug
            }
        }
    }
}

impl Op {
    fn from_sigil(sigil: &str) -> Option<Op> {
        match sigil {
            "=" => Some(Ex),
            ">" => Some(Gt),
            ">=" => Some(GtEq),
            "<" => Some(Lt),
            "<=" => Some(LtEq),
            _ => None
        }
    }
}

fn parse_version_part(s: &str) -> Result<u32, ReqParseError> {
    let mut ret = 0;

    for c in s.chars() {
        let n = (c as u32) - ('0' as u32);

        if n > 9 {
            return Err(VersionComponentsMustBeNumeric);
        }

        ret *= 10;
        ret +=  n;
    }

    Ok(ret)
}

fn is_sigil(c: char) -> bool {
    match c {
        '>' | '<' | '=' | '~' | '^' => true,
        _ => false
    }
}

impl fmt::Show for VersionReq {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        if self.predicates.is_empty() {
            try!(write!(fmt, "*"));
        } else {
            for (i, ref pred) in self.predicates.iter().enumerate() {
                if i == 0 {
                    try!(write!(fmt, "{}", pred));
                } else {
                    try!(write!(fmt, ", {}", pred));
                }
            }
        }

        Ok(())
    }
}

impl fmt::Show for Predicate {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "{} {}", self.op, self.major));

        match self.minor {
            Some(v) => try!(write!(fmt, ".{}", v)),
            None => ()
        }

        match self.patch {
            Some(v) => try!(write!(fmt, ".{}", v)),
            None => ()
        }

        Ok(())
    }
}

impl fmt::Show for Op {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Ex => try!(write!(fmt, "=")),
            Gt => try!(write!(fmt, ">")),
            GtEq => try!(write!(fmt, ">=")),
            Lt => try!(write!(fmt, "<")),
            LtEq => try!(write!(fmt, "<="))
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::VersionReq;
    use super::super::version::Version;

    fn req(s: &str) -> VersionReq {
        VersionReq::parse(s).unwrap()
    }

    fn version(s: &str) -> Version {
        match Version::parse(s) {
            Ok(v) => v,
            Err(e) => fail!("`{}` is not a valid version. Reason: {}", s, e)
        }
    }

    fn assert_match(req: &VersionReq, vers: &[&str]) {
        for ver in vers.iter() {
            assert!(req.matches(&version(*ver)), "did not match {}", ver);
        }
    }

    fn assert_not_match(req: &VersionReq, vers: &[&str]) {
        for ver in vers.iter() {
            assert!(!req.matches(&version(*ver)), "matched {}", ver);
        }
    }

    #[test]
    pub fn test_parsing_exact() {
        let r = req("1.0.0");

        assert!(r.to_string() == "= 1.0.0".to_string());

        assert_match(&r, ["1.0.0"]);
        assert_not_match(&r, ["1.0.1", "0.9.9", "0.10.0", "0.1.0"]);

        let r = req("0.9.0");

        assert!(r.to_string() == "= 0.9.0".to_string());

        assert_match(&r, ["0.9.0"]);
        assert_not_match(&r, ["0.9.1", "1.9.0", "0.0.9"]);
    }

    #[test]
    pub fn test_parsing_greater_than() {
        let r = req(">= 1.0.0");

        assert!(r.to_string() == ">= 1.0.0".to_string());

        assert_match(&r, ["1.0.0"]);
    }

    /* TODO:
     * - Test parse errors
     * - Handle pre releases
     */
}
<commit_msg>fix style<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt::Show;
use std::fmt;
use std::str::CharOffsets;

use super::version::Version;

#[deriving(PartialEq,Clone)]
pub struct VersionReq {
    predicates: Vec<Predicate>
}

#[deriving(PartialEq,Clone)]
enum Op {
    Ex,   // Exact
    Gt,   // Greater than
    GtEq, // Greater than or equal to
    Lt,   // Less than
    LtEq  // Less than or equal to
}

#[deriving(PartialEq,Clone)]
struct Predicate {
    op: Op,
    major: u32,
    minor: Option<u32>,
    patch: Option<u32>
}

struct PredBuilder {
    op: Option<Op>,
    major: Option<u32>,
    minor: Option<u32>,
    patch: Option<u32>
}

#[deriving(Show)]
pub enum ReqParseError {
    InvalidVersionRequirement,
    OpAlreadySet,
    InvalidSigil,
    VersionComponentsMustBeNumeric,
    OpRequired,
    MajorVersionRequired,
}

impl VersionReq {
    pub fn any() -> VersionReq {
        VersionReq { predicates: vec!() }
    }

    pub fn parse(input: &str) -> Result<VersionReq, ReqParseError> {
        let mut lexer = Lexer::new(input);
        let mut builder = PredBuilder::new();
        let mut predicates = Vec::new();

        for token in lexer {
            let result = match token {
                Sigil(x) => builder.set_sigil(x),
                AlphaNum(x) => builder.set_version_part(x),
                Dot => Ok(()), // Nothing to do for now
                _ => unimplemented!()
            };

            match result {
                Ok(_) => (),
                Err(e) => return Err(e),
            }
        }

        if lexer.is_error() {
            return Err(InvalidVersionRequirement);
        }

        match builder.build() {
            Ok(e) => predicates.push(e),
            Err(e) => return Err(e),
        }

        Ok(VersionReq { predicates: predicates })
    }

    pub fn exact(version: &Version) -> VersionReq {
        VersionReq { predicates: vec!(Predicate::exact(version)) }
    }

    pub fn matches(&self, version: &Version) -> bool {
        self.predicates.iter().all(|p| p.matches(version))
    }
}

impl Predicate {
    fn exact(version: &Version) -> Predicate {
        Predicate {
            op: Ex,
            major: version.major,
            minor: Some(version.minor),
            patch: Some(version.patch)
        }
    }

    fn matches(&self, ver: &Version) -> bool {
        match self.op {
            Ex => self.is_exact(ver),
            Gt => self.is_greater(ver),
            GtEq => self.is_exact(ver) || self.is_greater(ver),
            _ => false // not implemented
        }
    }

    fn is_exact(&self, ver: &Version) -> bool {
        if self.major != ver.major {
            return false;
        }

        match self.minor {
            Some(minor) => {
                if minor != ver.minor {
                    return false;
                }
            }
            None => return true
        }

        match self.patch {
            Some(patch) => {
                if patch != ver.patch {
                    return false;
                }
            }
            None => return true
        }

        true
    }

    fn is_greater(self, ver: &Version) -> bool {
        if self.major != ver.major {
            return self.major > ver.major;
        }

        match self.minor {
            Some(minor) => {
                if minor != ver.minor {
                    return minor > ver.minor
                }
            }
            None => return false
        }

        match self.patch {
            Some(patch) => {
                if patch != ver.patch {
                    return patch > ver.patch
                }
            }

            None => return false
        }

        false
    }
}

impl PredBuilder {
    fn new() -> PredBuilder {
        PredBuilder {
            op: None,
            major: None,
            minor: None,
            patch: None
        }
    }

    fn set_sigil(&mut self, sigil: &str) -> Result<(), ReqParseError> {
        if self.op.is_some() {
            return Err(OpAlreadySet);
        }

        match Op::from_sigil(sigil) {
            Some(op) => self.op = Some(op),
            _ => return Err(InvalidSigil),
        }

        Ok(())
    }

    fn set_version_part(&mut self, part: &str) -> Result<(), ReqParseError> {
        if self.op.is_none() {
            // If no op is specified, then the predicate is an exact match on
            // the version
            self.op = Some(Ex);
        }

        if self.major.is_none() {
            match parse_version_part(part) {
                Ok(e) => self.major = Some(e),
                Err(e) => return Err(e),
            }
        } else if self.minor.is_none() {
            match parse_version_part(part) {
                Ok(e) => self.minor = Some(e),
                Err(e) => return Err(e),
            }
        }
        else if self.patch.is_none() {
            match parse_version_part(part) {
                Ok(e) => self.patch = Some(e),
                Err(e) => return Err(e),
            }
        }

        Ok(())
    }

    /// Validates that a version predicate can be created given the present
    /// information.
    fn build(&self) -> Result<Predicate, ReqParseError> {
        let op = match self.op {
            Some(x) => x,
            None => return Err(OpRequired),
        };

        let major = match self.major {
            Some(x) => x,
            None => return Err(MajorVersionRequired),
        };

        Ok(Predicate {
            op: op,
            major: major,
            minor: self.minor,
            patch: self.patch
        })
    }
}

struct Lexer<'a> {
    c: char,
    idx: uint,
    iter: CharOffsets<'a>,
    mark: Option<uint>,
    input: &'a str,
    state: LexState
}

#[deriving(Show,PartialEq)]
enum LexState {
    LexInit,
    LexStart,
    LexAlphaNum,
    LexSigil,
    LexErr,
    LexWin
}

#[deriving(Show)]
enum Token<'a> {
    Sigil(&'a str),
    AlphaNum(&'a str),
    Comma,
    Dot
}

impl<'a> Lexer<'a> {
    fn new(input: &'a str) -> Lexer<'a> {
        Lexer {
            c: '\0',
            idx: 0,
            iter: input.char_indices(),
            mark: None,
            input: input,
            state: LexInit
        }
    }

    fn is_error(&self) -> bool {
        self.state == LexErr
    }

    fn mark(&mut self, at: uint) {
        self.mark = Some(at)
    }

    fn flush(&mut self, to: uint, kind: LexState) -> Option<Token<'a>> {
        match self.mark {
            Some(mark) => {
                if to <= mark {
                    return None;
                }

                let s = self.input.slice(mark, to);

                self.mark = None;

                match kind {
                    LexAlphaNum => Some(AlphaNum(s)),
                    LexSigil => Some(Sigil(s)),
                    _ => None // bug
                }
            }
            None => None
        }
    }
}

impl<'a> Iterator<Token<'a>> for Lexer<'a> {
    fn next(&mut self) -> Option<Token<'a>> {
        let mut c;
        let mut idx = 0;

        macro_rules! next(
            () => (
                match self.iter.next() {
                    Some((n_idx, n_char)) => {
                        c = n_char;
                        idx = n_idx;
                    }
                    _ => {
                      let s = self.state;
                      return self.flush(idx + 1, s)
                    }
                }
            ))

        macro_rules! flush(
            ($s:expr) => ({
                self.c = c;
                self.idx = idx;
                self.flush(idx, $s)
            }))

        if self.state == LexInit {
            self.state = LexStart;
            next!();
        } else {
            c = self.c;
            idx = self.idx;
        }

        loop {
            match self.state {
                LexStart => {
                    if c.is_whitespace() {
                        next!(); // Ignore
                    }
                    else if c.is_alphanumeric() {
                        self.mark(idx);
                        self.state = LexAlphaNum;
                        next!();
                    }
                    else if is_sigil(c) {
                        self.mark(idx);
                        self.state = LexSigil;
                        next!();
                    }
                    else if c == '.' {
                        self.state = LexInit;
                        return Some(Dot);
                    }
                    else if c == ',' {
                        self.state = LexInit;
                        return Some(Comma);
                    } else {
                        self.state = LexErr;
                        return None;
                    }
                }
                LexAlphaNum => {
                    if c.is_alphanumeric() {
                        next!();
                    } else {
                        self.state = LexStart;
                        return flush!(LexAlphaNum);
                    }
                }
                LexSigil => {
                    if is_sigil(c) {
                        next!();
                    } else {
                        self.state = LexStart;
                        return flush!(LexSigil);
                    }
                }
                LexErr | LexWin => return None,
                LexInit => return None // bug
            }
        }
    }
}

impl Op {
    fn from_sigil(sigil: &str) -> Option<Op> {
        match sigil {
            "=" => Some(Ex),
            ">" => Some(Gt),
            ">=" => Some(GtEq),
            "<" => Some(Lt),
            "<=" => Some(LtEq),
            _ => None
        }
    }
}

fn parse_version_part(s: &str) -> Result<u32, ReqParseError> {
    let mut ret = 0;

    for c in s.chars() {
        let n = (c as u32) - ('0' as u32);

        if n > 9 {
            return Err(VersionComponentsMustBeNumeric);
        }

        ret *= 10;
        ret +=  n;
    }

    Ok(ret)
}

fn is_sigil(c: char) -> bool {
    match c {
        '>' | '<' | '=' | '~' | '^' => true,
        _ => false
    }
}

impl fmt::Show for VersionReq {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        if self.predicates.is_empty() {
            try!(write!(fmt, "*"));
        } else {
            for (i, ref pred) in self.predicates.iter().enumerate() {
                if i == 0 {
                    try!(write!(fmt, "{}", pred));
                } else {
                    try!(write!(fmt, ", {}", pred));
                }
            }
        }

        Ok(())
    }
}

impl fmt::Show for Predicate {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "{} {}", self.op, self.major));

        match self.minor {
            Some(v) => try!(write!(fmt, ".{}", v)),
            None => ()
        }

        match self.patch {
            Some(v) => try!(write!(fmt, ".{}", v)),
            None => ()
        }

        Ok(())
    }
}

impl fmt::Show for Op {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Ex => try!(write!(fmt, "=")),
            Gt => try!(write!(fmt, ">")),
            GtEq => try!(write!(fmt, ">=")),
            Lt => try!(write!(fmt, "<")),
            LtEq => try!(write!(fmt, "<="))
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::VersionReq;
    use super::super::version::Version;

    fn req(s: &str) -> VersionReq {
        VersionReq::parse(s).unwrap()
    }

    fn version(s: &str) -> Version {
        match Version::parse(s) {
            Ok(v) => v,
            Err(e) => fail!("`{}` is not a valid version. Reason: {}", s, e)
        }
    }

    fn assert_match(req: &VersionReq, vers: &[&str]) {
        for ver in vers.iter() {
            assert!(req.matches(&version(*ver)), "did not match {}", ver);
        }
    }

    fn assert_not_match(req: &VersionReq, vers: &[&str]) {
        for ver in vers.iter() {
            assert!(!req.matches(&version(*ver)), "matched {}", ver);
        }
    }

    #[test]
    pub fn test_parsing_exact() {
        let r = req("1.0.0");

        assert!(r.to_string() == "= 1.0.0".to_string());

        assert_match(&r, ["1.0.0"]);
        assert_not_match(&r, ["1.0.1", "0.9.9", "0.10.0", "0.1.0"]);

        let r = req("0.9.0");

        assert!(r.to_string() == "= 0.9.0".to_string());

        assert_match(&r, ["0.9.0"]);
        assert_not_match(&r, ["0.9.1", "1.9.0", "0.0.9"]);
    }

    #[test]
    pub fn test_parsing_greater_than() {
        let r = req(">= 1.0.0");

        assert!(r.to_string() == ">= 1.0.0".to_string());

        assert_match(&r, ["1.0.0"]);
    }

    /* TODO:
     * - Test parse errors
     * - Handle pre releases
     */
}
<|endoftext|>


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

// Test that the lifetime of rvalues in for loops is extended
// to the for loop itself.

#[feature(macro_rules)];

use std::ops::Drop;

static mut FLAGS: u64 = 0;

struct Box<T> { f: T }
struct AddFlags { bits: u64 }

fn AddFlags(bits: u64) -> AddFlags {
    AddFlags { bits: bits }
}

fn arg(exp: u64, _x: &AddFlags) {
    check_flags(exp);
}

fn pass<T>(v: T) -> T {
    v
}

fn check_flags(exp: u64) {
    unsafe {
        let x = FLAGS;
        FLAGS = 0;
        println!("flags {}, expected {}", x, exp);
        assert_eq!(x, exp);
    }
}

impl AddFlags {
    fn check_flags<'a>(&'a self, exp: u64) -> &'a AddFlags {
        check_flags(exp);
        self
    }

    fn bits(&self) -> u64 {
        self.bits
    }
}

impl Drop for AddFlags {
    fn drop(&mut self) {
        unsafe {
            FLAGS = FLAGS + self.bits;
        }
    }
}

pub fn main() {
    // The array containing [AddFlags] should not be dropped until
    // after the for loop:
    for x in [AddFlags(1)].iter() {
        check_flags(0);
    }
    check_flags(1);
}
<commit_msg>Update year on license header<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that the lifetime of rvalues in for loops is extended
// to the for loop itself.

#[feature(macro_rules)];

use std::ops::Drop;

static mut FLAGS: u64 = 0;

struct Box<T> { f: T }
struct AddFlags { bits: u64 }

fn AddFlags(bits: u64) -> AddFlags {
    AddFlags { bits: bits }
}

fn arg(exp: u64, _x: &AddFlags) {
    check_flags(exp);
}

fn pass<T>(v: T) -> T {
    v
}

fn check_flags(exp: u64) {
    unsafe {
        let x = FLAGS;
        FLAGS = 0;
        println!("flags {}, expected {}", x, exp);
        assert_eq!(x, exp);
    }
}

impl AddFlags {
    fn check_flags<'a>(&'a self, exp: u64) -> &'a AddFlags {
        check_flags(exp);
        self
    }

    fn bits(&self) -> u64 {
        self.bits
    }
}

impl Drop for AddFlags {
    fn drop(&mut self) {
        unsafe {
            FLAGS = FLAGS + self.bits;
        }
    }
}

pub fn main() {
    // The array containing [AddFlags] should not be dropped until
    // after the for loop:
    for x in [AddFlags(1)].iter() {
        check_flags(0);
    }
    check_flags(1);
}
<|endoftext|>


<commit_before>use std::fmt;
use std::f64;
use std::f64::consts::PI;
use std::cmp::Ordering;

use radians::Radians;
use rand::{Rand, Rng};
use {Distance};

const MIN_SPEED: i32 = 1;
const MAX_SPEED: i32 = 25;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, Hash, Serialize, Deserialize)]
pub(crate) enum SpeedLevel {
    Value(i32),
    Instant,
}

impl PartialOrd for SpeedLevel {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::SpeedLevel::*;
        match (*self, *other) {
            (Value(value), Value(ref other_value)) => value.partial_cmp(other_value),
            (Instant, Instant) => Some(Ordering::Equal),
            (Value(_), Instant) => Some(Ordering::Less),
            (Instant, Value(_)) => Some(Ordering::Greater),
        }
    }
}

/// Represents both the movement and rotation speed of the turtle.
///
/// # Creating Speeds
///
/// You can create a `Speed` value by converting either strings or numbers.
///
/// ```rust
/// # use turtle::Speed;
/// // This value is of type `Speed` and it is converted from an `i32`
/// let speed: Speed = 1.into();
///
/// // This value is of type `Speed` and it is converted from a `&str`
/// let slowest_speed: Speed = "slowest".into();
/// assert_eq!(speed, slowest_speed);
/// ```
///
/// There is no need to call `.into()` when passing a speed into the [`set_speed` method].
/// See the [`set_speed` method] for more information about how that works.
///
/// ```rust
/// # use turtle::{Turtle};
/// let mut turtle = Turtle::new();
/// turtle.set_speed(22); // Same as `turtle.set_speed(22.into())`
/// ```
///
/// **The minimum speed value is 1 and the maximum speed value (currently) is 25.**
///
/// Trying to set the speed to a value out of that range will cause a panic.
///
/// ```rust,should_panic
/// # use turtle::{Turtle};
/// let mut turtle = Turtle::new();
/// turtle.set_speed(26); // panic!
/// ```
///
/// While the minimum speed will not change, the maximum speed may grow larger if the need arises.
/// That is why we chose to panic for invalid speeds instead of defaulting to another value.
///
/// ### String Conversion
///
/// Strings are converted as follows:
///
/// | String      | Value |
/// | ----------- | ----- |
/// | `"slowest"` | `1`   |
/// | `"slower"`  | `5`   |
/// | `"slow"`    | `8`   |
/// | `"normal"`  | `10`  |
/// | `"fast"`    | `12`  |
/// | `"faster"`  | `15`  |
/// | `"instant"` | [see below](#instant) |
///
/// You can use strings to create `Speed` values in the same way numbers were used above. All
/// three of the following are equivalent:
///
/// ```rust
/// # use turtle::{Turtle, Speed};
/// # let mut turtle = Turtle::new();
/// turtle.set_speed(5);
/// turtle.set_speed("slower");
/// turtle.set_speed(Speed::from("slower")); // Not recommended!
/// ```
///
/// # Instant
///
/// There is one special speed value `"instant"` which makes it so that movement and rotation
/// are not animated at all. Instead, the turtle immediately moves and rotates to the position that
/// you directed it to. It will still draw along the way if its pen is down.
///
/// ```rust
/// # use turtle::{Turtle};
/// let mut turtle = Turtle::new();
/// turtle.set_speed("instant");
/// turtle.forward(100.0); // A line will be drawn instantly!
/// ```
///
/// # Comparing Speed Values
///
/// `Speed` values can be compared for equality with `i32` values. This is a little more convenient
/// than converting the `i32` to `Speed` every time you want to make a comparison.
///
/// ```rust
/// # use turtle::Speed;
/// let speed: Speed = 1.into();
/// // Speed values can be compared to integers
/// assert_eq!(speed, 1);
/// // This is equivalent to the following
/// assert_eq!(speed, Speed::from(1));
///
/// // This value is of type `Speed` and it is converted from a `&str`
/// let speed: Speed = "slowest".into();
/// // Speed values can be compared to integers
/// assert_eq!(speed, 1);
/// // This is equivalent to the following
/// assert_eq!(speed, Speed::from("slowest"));
/// ```
///
/// You can use the `<`, `<=`, `==`, `>=`, `>` with `Speed` values and `i32` values or other
/// `Speed` values.
///
/// ```rust,no_run
/// # use turtle::{Turtle, Speed};
/// let turtle = Turtle::new();
/// let speed = turtle.speed();
/// if speed == 12 && speed >= 5 && speed < Speed::instant() {
///     println!("Super fast!!");
/// }
/// // This is equivalent, but requires more typing
/// if speed == Speed::from(12) && speed >= Speed::from(5) && speed < Speed::from("instant") {
///     println!("Super fast!!");
/// }
/// ```
///
/// Notice that you can compare `Speed` values to numeric values, but not the other way around.
///
/// ```rust,compile_fail
/// # use turtle::Speed;
/// let speed: Speed = 7.into();
/// if 8 > speed { // This doesn't make sense and won't compile!
///     // ...
/// }
/// ```
///
/// To check if a speed is instant, use the [`is_instant()` method] or compare the speed to
/// [`Speed::instant()`].
///
/// ```rust
/// # use turtle::Speed;
/// let speed = Speed::instant();
/// if speed.is_instant() {
///     println!("Instant!!");
/// }
/// # else { panic!("Speed::instant() was not instant!"); }
/// ```
///
/// [`set_speed` method]: struct.Turtle.html#method.set_speed
/// [`Speed::instant()`]: struct.Speed.html#method.instant
/// [`is_instant()` method]: struct.Speed.html#method.is_instant
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Speed(SpeedLevel);

impl Speed {
    /// Returns the speed value that will make the turtle move and rotate instantly. This means
    /// that instead of the turtle's movements being animated, it will directly move to wherever
    /// you direct it to go.
    ///
    /// ```rust
    /// # use turtle::{Turtle, Speed};
    /// let mut turtle = Turtle::new();
    /// turtle.set_speed(Speed::instant());
    /// turtle.forward(100.0); // A line will be drawn instantly!
    /// ```
    ///
    /// Whenever possible, you should prefer to use the string `"instant"` instead of calling this
    /// method.
    ///
    /// ```rust
    /// # use turtle::{Turtle};
    /// # let mut turtle = Turtle::new();
    /// turtle.set_speed("instant"); // equivalent to typing `Speed::instant()`
    /// ```
    pub fn instant() -> Self {
        Speed(SpeedLevel::Instant)
    }

    /// Returns true if this speed is the same as `Speed::instant()`
    ///
    /// ```rust
    /// use turtle::{Speed};
    /// let speed: Speed = "instant".into();
    /// assert!(speed.is_instant());
    ///
    /// let speed = Speed::instant();
    /// assert!(speed.is_instant());
    /// ```
    pub fn is_instant(self) -> bool {
        match self {
            Speed(SpeedLevel::Instant) => true,
            _ => false,
        }
    }

    /// Converts a speed to its value as a movement speed in pixels per second
    pub(crate) fn to_movement(self) -> Distance {
        use self::SpeedLevel::*;
        match self.0 {
            Value(speed) => speed as f64 * 50.0,
            Instant => f64::INFINITY,
        }
    }

    /// Converts a speed to its value as radians per second
    pub(crate) fn to_rotation(self) -> Radians {
        use self::SpeedLevel::*;
        Radians::from_radians_value(match self.0 {
            Value(speed) => speed as f64 * (3.0*PI),
            Instant => f64::INFINITY,
        })
    }
}

impl fmt::Display for Speed {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::SpeedLevel::*;
        match self.0 {
            Value(speed) => write!(f, "Speed::from({})", speed),
            Instant => write!(f, "Speed::instant()"),
        }
    }
}

impl PartialEq<i32> for Speed {
    fn eq(&self, other: &i32) -> bool {
        self.eq(&Speed::from(*other))
    }
}

impl PartialOrd<i32> for Speed {
    fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
        return self.partial_cmp(&Speed::from(*other));
    }
}

impl Rand for Speed {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        rng.gen_range(MIN_SPEED, MAX_SPEED + 1).into()
    }
}

impl<'a> From<&'a str> for Speed {
    fn from(s: &'a str) -> Self {
        use self::SpeedLevel::*;

        Speed(match s {
            "slowest" => Value(1),
            "slower" => Value(5),
            "slow" => Value(8),
            "normal" => Value(10),
            "fast" => Value(12),
            "faster" => Value(15),
            "instant" => Instant,
            _ => panic!("Invalid speed specified, use one of the words: \"slowest\", \"slower\", \"slow\", \"normal\", \"fast\", \"faster\", \"instant\""),
        })
    }
}

impl From<i32> for Speed {
    fn from(n: i32) -> Self {
        use self::SpeedLevel::*;

        Speed(match n {
            // Special error message for 0 because this used to be a valid speed
            0 => panic!("Invalid speed: 0. If you wanted to set the speed to instant, please use the string \"instant\" or Speed::instant()"),
            n if n >= MIN_SPEED && n <= MAX_SPEED => Value(n),
            n => panic!("Invalid speed: {}. Must be a value between {} and {}", n, MIN_SPEED, MAX_SPEED),
        })
    }
}

// We include this implementation because we use f64 in the rest of the library.
// It makes sense to implement this so that they don't get messed up if they accidentally use a
// floating point literal with set_speed.
impl From<f64> for Speed {
    fn from(n: f64) -> Self {
        (n.round() as i32).into()
    }
}

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

    #[test]
    fn display() {
        let speed: Speed = "instant".into();
        assert_eq!(format!("{}", speed), "Speed::instant()");
        for value in 1..MAX_SPEED {
            let speed: Speed = value.into();
            assert_eq!(format!("{}", speed), format!("Speed::from({})", value));
        }
    }

    #[test]
    fn speed_strings() {
        let mut turtle = Turtle::new();
        turtle.set_speed("slowest");
        assert_eq!(turtle.speed(), 1);
        turtle.set_speed("slower");
        assert_eq!(turtle.speed(), 5);
        turtle.set_speed("slow");
        assert_eq!(turtle.speed(), 8);
        turtle.set_speed("normal");
        assert_eq!(turtle.speed(), 10);
        turtle.set_speed("fast");
        assert_eq!(turtle.speed(), 12);
        turtle.set_speed("faster");
        assert_eq!(turtle.speed(), 15);
        turtle.set_speed("instant");
        assert_eq!(turtle.speed(), Speed::instant());
    }

    #[test]
    #[should_panic(expected = "Invalid speed specified, use one of the words: \"slowest\", \"slower\", \"slow\", \"normal\", \"fast\", \"faster\", \"instant\"")]
    fn invalid_speed() {
        let mut turtle = Turtle::new();
        turtle.set_speed("wrong");
    }

    #[test]
    fn speed_values() {
        let mut turtle = Turtle::new();
        for speed in 1..(MAX_SPEED + 1) {
            turtle.set_speed(speed);
            assert_eq!(turtle.speed(), speed);
        }
    }

    #[test]
    #[should_panic(expected = "Invalid speed: 26. Must be a value between 1 and 25")]
    fn speed_value_out_of_range() {
        let mut turtle = Turtle::new();
        turtle.set_speed(26);
    }

    #[test]
    #[should_panic(expected = "Invalid speed: 20394. Must be a value between 1 and 25")]
    fn speed_value_out_of_range2() {
        let mut turtle = Turtle::new();
        turtle.set_speed(20394);
    }

    #[test]
    #[should_panic(expected = "Invalid speed: -1. Must be a value between 1 and 25")]
    fn speed_value_out_of_range_negative() {
        let mut turtle = Turtle::new();
        turtle.set_speed(-1);
    }

    #[test]
    #[should_panic(expected = "Invalid speed: 0. If you wanted to set the speed to instant, please use the string \"instant\" or Speed::instant()")]
    fn disallow_zero() {
        let mut turtle = Turtle::new();
        turtle.set_speed(0);
    }

    #[test]
    fn speed_values_f64() {
        let mut turtle = Turtle::new();
        for speed in 1..MAX_SPEED {
            turtle.set_speed(speed as f64 + 0.4);
            assert_eq!(turtle.speed(), speed);
        }
    }
}
<commit_msg>Documentation tweaks<commit_after>use std::fmt;
use std::f64;
use std::f64::consts::PI;
use std::cmp::Ordering;

use radians::Radians;
use rand::{Rand, Rng};
use {Distance};

const MIN_SPEED: i32 = 1;
const MAX_SPEED: i32 = 25;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, Hash, Serialize, Deserialize)]
pub(crate) enum SpeedLevel {
    Value(i32),
    Instant,
}

impl PartialOrd for SpeedLevel {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        use self::SpeedLevel::*;
        match (*self, *other) {
            (Value(value), Value(ref other_value)) => value.partial_cmp(other_value),
            (Instant, Instant) => Some(Ordering::Equal),
            (Value(_), Instant) => Some(Ordering::Less),
            (Instant, Value(_)) => Some(Ordering::Greater),
        }
    }
}

/// Represents both the movement and rotation speed of the turtle.
///
/// # Creating Speeds
///
/// You can create a `Speed` value by converting either strings or numbers.
///
/// ```rust
/// # use turtle::Speed;
/// // This value is of type `Speed` and it is converted from an `i32`
/// let speed: Speed = 1.into();
///
/// // This value is of type `Speed` and it is converted from a `&str`
/// let slowest_speed: Speed = "slowest".into();
/// # assert_eq!(speed, slowest_speed);
/// ```
///
/// There is no need to call `.into()` when passing a speed into the [`set_speed` method].
/// See the [`set_speed` method] for more information about how that works.
///
/// ```rust
/// # use turtle::{Turtle};
/// let mut turtle = Turtle::new();
/// turtle.set_speed(22); // Same as `turtle.set_speed(22.into())`
/// ```
///
/// **The minimum speed value is 1 and the maximum speed value (currently) is 25.**
///
/// Trying to set the speed to a value out of that range will cause a panic.
///
/// ```rust,should_panic
/// # use turtle::{Turtle};
/// let mut turtle = Turtle::new();
/// turtle.set_speed(26); // panic!
/// ```
///
/// While the minimum speed will not change, the maximum speed may grow larger if the need arises.
/// That is why we chose to panic for invalid speeds instead of defaulting to another value.
///
/// ### String Conversion
///
/// Strings are converted as follows:
///
/// | String      | Value |
/// | ----------- | ----- |
/// | `"slowest"` | `1`   |
/// | `"slower"`  | `5`   |
/// | `"slow"`    | `8`   |
/// | `"normal"`  | `10`  |
/// | `"fast"`    | `12`  |
/// | `"faster"`  | `15`  |
/// | `"instant"` | [see below](#instant) |
///
/// You can use strings to create `Speed` values in the same way numbers were used above. Each of
/// the following is an equivalent way to set the speed to `5`:
///
/// ```rust
/// # use turtle::{Turtle, Speed};
/// # let mut turtle = Turtle::new();
/// turtle.set_speed(5);
/// turtle.set_speed("slower");
/// turtle.set_speed(Speed::from(5)); // Not recommended!
/// turtle.set_speed(Speed::from("slower")); // Not recommended!
/// ```
///
/// # Instant
///
/// There is one special speed value `"instant"` which makes it so that movement and rotation
/// are not animated at all. Instead, the turtle immediately moves and rotates to the position that
/// you directed it to. It will still draw along the way if its pen is down.
///
/// ```rust
/// # use turtle::{Turtle};
/// let mut turtle = Turtle::new();
/// turtle.set_speed("instant");
/// turtle.forward(100.0); // A line will be drawn instantly!
/// ```
///
/// # Comparing Speed Values
///
/// `Speed` values can be compared for equality with `i32` values. This is a little more convenient
/// than converting the `i32` to `Speed` every time you want to make a comparison.
///
/// ```rust
/// # use turtle::Speed;
/// let speed: Speed = 1.into();
/// // Speed values can be compared to integers
/// assert_eq!(speed, 1);
/// // This is equivalent to the following
/// assert_eq!(speed, Speed::from(1));
///
/// // This value is of type `Speed` and it is converted from a `&str`
/// let speed: Speed = "slowest".into();
/// // Speed values can be compared to other speed values
/// assert_eq!(speed, Speed::from("slowest"));
/// // This is equivalent to the following since the slowest speed is 1
/// assert_eq!(speed, 1);
/// ```
///
/// You can use the `<`, `<=`, `==`, `>=`, `>` with `Speed` values and `i32` values (or other
/// `Speed` values).
///
/// ```rust,no_run
/// # use turtle::{Turtle, Speed};
/// let turtle = Turtle::new();
/// let speed = turtle.speed();
/// if speed == 12 && speed >= 5 && speed < Speed::instant() {
///     println!("Super fast!!");
/// }
/// // This is equivalent, but requires more typing
/// if speed == Speed::from(12) && speed >= Speed::from(5) && speed < Speed::from("instant") {
///     println!("Super fast!!");
/// }
/// ```
///
/// Notice that you can compare `Speed` values to numeric values, but not the other way around.
///
/// ```rust,compile_fail
/// # use turtle::Speed;
/// let speed: Speed = 7.into();
/// if 8 > speed { // This doesn't make sense and won't compile!
///     // ...
/// }
/// ```
///
/// To check if a speed is instant, use the [`is_instant()` method] or compare the speed to
/// [`Speed::instant()`].
///
/// ```rust
/// # use turtle::Speed;
/// let speed = Speed::instant();
/// if speed.is_instant() {
///     println!("Instant!!");
/// }
/// # else { panic!("Speed::instant() was not instant!"); }
/// ```
///
/// [`set_speed` method]: struct.Turtle.html#method.set_speed
/// [`Speed::instant()`]: struct.Speed.html#method.instant
/// [`is_instant()` method]: struct.Speed.html#method.is_instant
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Speed(SpeedLevel);

impl Speed {
    /// Returns the speed value that will make the turtle move and rotate instantly. This means
    /// that instead of the turtle's movements being animated, it will directly move to wherever
    /// you direct it to go.
    ///
    /// ```rust
    /// # use turtle::{Turtle, Speed};
    /// let mut turtle = Turtle::new();
    /// turtle.set_speed(Speed::instant());
    /// turtle.forward(100.0); // A line will be drawn instantly!
    /// ```
    ///
    /// Whenever possible, you should prefer to use the string `"instant"` instead of calling this
    /// method.
    ///
    /// ```rust
    /// # use turtle::{Turtle};
    /// # let mut turtle = Turtle::new();
    /// turtle.set_speed("instant"); // equivalent to typing `Speed::instant()`
    /// ```
    pub fn instant() -> Self {
        Speed(SpeedLevel::Instant)
    }

    /// Returns true if this speed is the same as `Speed::instant()`
    ///
    /// ```rust
    /// use turtle::{Speed};
    /// let speed: Speed = "instant".into();
    /// assert!(speed.is_instant());
    ///
    /// let speed = Speed::instant();
    /// assert!(speed.is_instant());
    /// ```
    pub fn is_instant(self) -> bool {
        match self {
            Speed(SpeedLevel::Instant) => true,
            _ => false,
        }
    }

    /// Converts a speed to its value as a movement speed in pixels per second
    pub(crate) fn to_movement(self) -> Distance {
        use self::SpeedLevel::*;
        match self.0 {
            Value(speed) => speed as f64 * 50.0,
            Instant => f64::INFINITY,
        }
    }

    /// Converts a speed to its value as radians per second
    pub(crate) fn to_rotation(self) -> Radians {
        use self::SpeedLevel::*;
        Radians::from_radians_value(match self.0 {
            Value(speed) => speed as f64 * (3.0*PI),
            Instant => f64::INFINITY,
        })
    }
}

impl fmt::Display for Speed {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::SpeedLevel::*;
        match self.0 {
            Value(speed) => write!(f, "Speed::from({})", speed),
            Instant => write!(f, "Speed::instant()"),
        }
    }
}

impl PartialEq<i32> for Speed {
    fn eq(&self, other: &i32) -> bool {
        self.eq(&Speed::from(*other))
    }
}

impl PartialOrd<i32> for Speed {
    fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
        return self.partial_cmp(&Speed::from(*other));
    }
}

impl Rand for Speed {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        rng.gen_range(MIN_SPEED, MAX_SPEED + 1).into()
    }
}

impl<'a> From<&'a str> for Speed {
    fn from(s: &'a str) -> Self {
        use self::SpeedLevel::*;

        Speed(match s {
            "slowest" => Value(1),
            "slower" => Value(5),
            "slow" => Value(8),
            "normal" => Value(10),
            "fast" => Value(12),
            "faster" => Value(15),
            "instant" => Instant,
            _ => panic!("Invalid speed specified, use one of the words: \"slowest\", \"slower\", \"slow\", \"normal\", \"fast\", \"faster\", \"instant\""),
        })
    }
}

impl From<i32> for Speed {
    fn from(n: i32) -> Self {
        use self::SpeedLevel::*;

        Speed(match n {
            // Special error message for 0 because this used to be a valid speed
            0 => panic!("Invalid speed: 0. If you wanted to set the speed to instant, please use the string \"instant\" or Speed::instant()"),
            n if n >= MIN_SPEED && n <= MAX_SPEED => Value(n),
            n => panic!("Invalid speed: {}. Must be a value between {} and {}", n, MIN_SPEED, MAX_SPEED),
        })
    }
}

// We include this implementation because we use f64 in the rest of the library.
// It makes sense to implement this so that they don't get messed up if they accidentally use a
// floating point literal with set_speed.
impl From<f64> for Speed {
    fn from(n: f64) -> Self {
        (n.round() as i32).into()
    }
}

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

    #[test]
    fn display() {
        let speed: Speed = "instant".into();
        assert_eq!(format!("{}", speed), "Speed::instant()");
        for value in 1..MAX_SPEED {
            let speed: Speed = value.into();
            assert_eq!(format!("{}", speed), format!("Speed::from({})", value));
        }
    }

    #[test]
    fn speed_strings() {
        let mut turtle = Turtle::new();
        turtle.set_speed("slowest");
        assert_eq!(turtle.speed(), 1);
        turtle.set_speed("slower");
        assert_eq!(turtle.speed(), 5);
        turtle.set_speed("slow");
        assert_eq!(turtle.speed(), 8);
        turtle.set_speed("normal");
        assert_eq!(turtle.speed(), 10);
        turtle.set_speed("fast");
        assert_eq!(turtle.speed(), 12);
        turtle.set_speed("faster");
        assert_eq!(turtle.speed(), 15);
        turtle.set_speed("instant");
        assert_eq!(turtle.speed(), Speed::instant());
    }

    #[test]
    #[should_panic(expected = "Invalid speed specified, use one of the words: \"slowest\", \"slower\", \"slow\", \"normal\", \"fast\", \"faster\", \"instant\"")]
    fn invalid_speed() {
        let mut turtle = Turtle::new();
        turtle.set_speed("wrong");
    }

    #[test]
    fn speed_values() {
        let mut turtle = Turtle::new();
        for speed in 1..(MAX_SPEED + 1) {
            turtle.set_speed(speed);
            assert_eq!(turtle.speed(), speed);
        }
    }

    #[test]
    #[should_panic(expected = "Invalid speed: 26. Must be a value between 1 and 25")]
    fn speed_value_out_of_range() {
        let mut turtle = Turtle::new();
        turtle.set_speed(26);
    }

    #[test]
    #[should_panic(expected = "Invalid speed: 20394. Must be a value between 1 and 25")]
    fn speed_value_out_of_range2() {
        let mut turtle = Turtle::new();
        turtle.set_speed(20394);
    }

    #[test]
    #[should_panic(expected = "Invalid speed: -1. Must be a value between 1 and 25")]
    fn speed_value_out_of_range_negative() {
        let mut turtle = Turtle::new();
        turtle.set_speed(-1);
    }

    #[test]
    #[should_panic(expected = "Invalid speed: 0. If you wanted to set the speed to instant, please use the string \"instant\" or Speed::instant()")]
    fn disallow_zero() {
        let mut turtle = Turtle::new();
        turtle.set_speed(0);
    }

    #[test]
    fn speed_values_f64() {
        let mut turtle = Turtle::new();
        for speed in 1..MAX_SPEED {
            turtle.set_speed(speed as f64 + 0.4);
            assert_eq!(turtle.speed(), speed);
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Error, Formatter};
use std::rc::Rc;
use std::result::Result;

pub trait Stack<T> {
    fn empty() -> Self;
    fn is_empty(&self) -> bool;

    fn cons(&self, v: T) -> Self;
    fn head(&self) -> T;
    fn tail(&self) -> Self;

    fn append(&self, y: &Self) -> Self where Self: Clone + Sized {
        if self.is_empty() {
            (*y).clone()
        } else {
            self.tail().append(y).cons(self.head())
        }
    }

    fn update(&self, i: usize, y: T) -> Self where Self: Sized {
        if self.is_empty() {
            panic!("index out of bounds");
        }

        if i == 0 {
            self.tail().cons(y)
        } else {
            self.tail().update(i - 1, y).cons(self.head())
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum List<T> {
    Nil,
    Cons(T, Rc<List<T>>)
}

use stack::List::{Cons, Nil};

impl<T: Clone> Stack<T> for List<T> {
    fn empty() -> List<T> {
        Nil
    }

    fn is_empty(&self) -> bool {
        match *self {
            Nil => true,
            _ => false
        }
    }

    fn cons(&self, v: T) -> List<T> {
        match *self {
            Cons(ref h, ref t) => Cons(v, Rc::new(Cons(h.clone(), t.clone()))),
            Nil => Cons(v, Rc::new(Nil))
        }
    }

    fn head(&self) -> T {
        match *self {
            Cons(ref v, _) => v.clone(),
            Nil => panic!("head of empty list")
        }
    }

    fn tail(&self) -> List<T> {
        match *self {
            Nil => panic!("tail of empty list"),
            Cons(_, ref t) => (**t).clone()
        }
    }
}

impl<T: Display> Display for List<T> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        try!(write!(f, "["));

        fn _loop<T: Display>(f: &mut Formatter, l: &List<T>, first: bool) -> Result<(), Error> {
            match *l {
                Cons(ref h, ref t) => {
                    if first { try!(write!(f, "{}", *h)); }
                    else { try!(write!(f, ", {}", *h)); }

                    _loop(f, t, false)
                },
                Nil => Result::Ok(())
            }
        }

        try!(_loop(f, self, true));

        write!(f, "]")
    }
}

#[test]
fn list() {
    let l1: List<usize> = Stack::empty();
    let l2 = l1.cons(3).cons(2).cons(1);
    let l3 = l1.cons(5).cons(4);

    assert!(l1.is_empty());
    assert!(!l2.is_empty());
    assert_eq!(l2, Cons(1, Rc::new(Cons(2, Rc::new(Cons(3, Rc::new(Nil)))))));
    assert_eq!(l2.head(), 1);
    assert_eq!(l2.tail(), Cons(2, Rc::new(Cons(3, Rc::new(Nil)))));

    assert_eq!(l1.append(&l2), l2);
    assert_eq!(l2.append(&l1), l2);

    assert_eq!(l2.append(&l3),
               Cons(1, Rc::new(Cons(2, Rc::new(Cons(3, Rc::new(Cons(4, Rc::new(Cons(5, Rc::new(Nil)))))))))));

    assert_eq!(l3.append(&l2),
               Cons(4, Rc::new(Cons(5, Rc::new(Cons(1, Rc::new(Cons(2, Rc::new(Cons(3, Rc::new(Nil)))))))))));

    assert_eq!(l3.update(0, 0),
               Cons(0, Rc::new(Cons(5, Rc::new(Nil)))));

    assert_eq!(l3.update(1, 0),
               Cons(4, Rc::new(Cons(0, Rc::new(Nil)))));
}
<commit_msg>stack: rename args<commit_after>use std::fmt::{Display, Error, Formatter};
use std::rc::Rc;

pub trait Stack<T> {
    fn empty() -> Self;
    fn is_empty(&self) -> bool;

    fn cons(&self, x: T) -> Self;
    fn head(&self) -> T;
    fn tail(&self) -> Self;

    fn append(&self, y: &Self) -> Self where Self: Clone + Sized {
        if self.is_empty() {
            (*y).clone()
        } else {
            self.tail().append(y).cons(self.head())
        }
    }

    fn update(&self, i: usize, x: T) -> Self where Self: Sized {
        if self.is_empty() {
            panic!("index out of bounds");
        }

        if i == 0 {
            self.tail().cons(x)
        } else {
            self.tail().update(i - 1, x).cons(self.head())
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum List<T> {
    Nil,
    Cons(T, Rc<List<T>>)
}

use stack::List::{Cons, Nil};

impl<T: Clone> Stack<T> for List<T> {
    fn empty() -> List<T> {
        Nil
    }

    fn is_empty(&self) -> bool {
        match *self {
            Nil => true,
            _ => false
        }
    }

    fn cons(&self, x: T) -> List<T> {
        match *self {
            Cons(ref h, ref t) => Cons(x, Rc::new(Cons(h.clone(), t.clone()))),
            Nil => Cons(x, Rc::new(Nil))
        }
    }

    fn head(&self) -> T {
        match *self {
            Cons(ref h, _) => h.clone(),
            Nil => panic!("head of empty list")
        }
    }

    fn tail(&self) -> List<T> {
        match *self {
            Nil => panic!("tail of empty list"),
            Cons(_, ref t) => (**t).clone()
        }
    }
}

impl<T: Display> Display for List<T> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        try!(write!(f, "["));

        fn _loop<T: Display>(f: &mut Formatter, l: &List<T>, first: bool) -> Result<(), Error> {
            match *l {
                Cons(ref h, ref t) => {
                    if first { try!(write!(f, "{}", *h)); }
                    else { try!(write!(f, ", {}", *h)); }

                    _loop(f, t, false)
                },
                Nil => Result::Ok(())
            }
        }

        try!(_loop(f, self, true));

        write!(f, "]")
    }
}

#[test]
fn list() {
    let l1: List<usize> = Stack::empty();
    let l2 = l1.cons(3).cons(2).cons(1);
    let l3 = l1.cons(5).cons(4);

    assert!(l1.is_empty());
    assert!(!l2.is_empty());
    assert_eq!(l2, Cons(1, Rc::new(Cons(2, Rc::new(Cons(3, Rc::new(Nil)))))));
    assert_eq!(l2.head(), 1);
    assert_eq!(l2.tail(), Cons(2, Rc::new(Cons(3, Rc::new(Nil)))));

    assert_eq!(l1.append(&l2), l2);
    assert_eq!(l2.append(&l1), l2);

    assert_eq!(l2.append(&l3),
               Cons(1, Rc::new(Cons(2, Rc::new(Cons(3, Rc::new(Cons(4, Rc::new(Cons(5, Rc::new(Nil)))))))))));

    assert_eq!(l3.append(&l2),
               Cons(4, Rc::new(Cons(5, Rc::new(Cons(1, Rc::new(Cons(2, Rc::new(Cons(3, Rc::new(Nil)))))))))));

    assert_eq!(l3.update(0, 0),
               Cons(0, Rc::new(Cons(5, Rc::new(Nil)))));

    assert_eq!(l3.update(1, 0),
               Cons(4, Rc::new(Cons(0, Rc::new(Nil)))));
}
<|endoftext|>