<commit_before>use bson::Document as BsonDocument;
use bson;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use client::wire_protocol::header::{Header, OpCode};
use std::io::{Read, Write};
use std::mem;
use std::result::Result::{Ok, Err};

trait ByteLength {
    /// Calculates the number of bytes in the serialized version of the struct.
    fn byte_length(&self) -> Result<i32, String>;
}

impl ByteLength for BsonDocument {
    /// Gets the length of a BSON document.
    ///
    /// # Return value
    ///
    /// Returns the number of bytes in the serialized BSON document.
    fn byte_length(&self) -> Result<i32, String> {
        let mut temp_buffer = vec![];

        match bson::encode_document(&mut temp_buffer, self) {
            Ok(_) => Ok(temp_buffer.len() as i32),
            Err(_) => Err("unable to serialize BSON document".to_owned())
        }
    }
}

pub struct OpQueryFlags {
    tailable_cursor: bool,    // Bit 1
    slave_ok: bool,           // Bit 2
    oplog_relay: bool,        // Bit 3
    no_cursor_timeout: bool,  // Bit 4
    await_data: bool,         // Bit 5
    exhaust: bool,            // Bit 6
    partial: bool,            // Bit 7

    // All other bits are 0
}

impl OpQueryFlags {
    pub fn new(tc: bool, so: bool, or: bool, nct: bool, ad: bool, e: bool,
           p: bool) -> OpQueryFlags {
        OpQueryFlags{
            tailable_cursor: tc,
            slave_ok: so,
            oplog_relay: or,
            no_cursor_timeout: nct,
            await_data: ad,
            exhaust: e,
            partial: p,
        }
    }

    pub fn no_flags() -> OpQueryFlags {
        OpQueryFlags::new(false, false, false, false, false, false, false)
    }

    fn to_i32(&self) -> i32 {
        let mut i = 0 as i32;

        if self.tailable_cursor {
            let bit = 1 << 1;

            i &= bit;
        }

        if self.slave_ok {
            let bit = 1 << 2;

            i &= bit;
        }

        if self.oplog_relay {
            let bit = 1 << 3;

            i &= bit;
        }

        if self.no_cursor_timeout {
            let bit = 1 << 4;

            i &= bit;
        }

        if self.await_data {
            let bit = 1 << 5;

            i &= bit;
        }

        if self.exhaust {
            let bit = 1 << 6;

            i &= bit;
        }

        if self.partial {
            let bit = 1 << 7;

            i &= bit;
        }

        i
    }
}

/// Represents a message in the MongoDB Wire Protocol.
pub enum Message {
    OpReply {
        header: Header,
        flags: i32,
        cursor_id: i64,
        starting_from: i32,
        number_returned: i32,
        documents: Vec<BsonDocument>,
    },
    OpQuery {
        header: Header,
        flags: OpQueryFlags,
        full_collection_name: String,
        number_to_skip: i32,
        number_to_return: i32,
        query: BsonDocument,
        return_field_selector: Option<BsonDocument>,
    },
}

impl Message {
    /// Constructs a new message request for a query.
    ///
    /// # Arguments
    ///
    /// `header_request_id` - The request ID to be placed in the message header.
    /// `flags` - Bit vector of query options.
    /// `full_collection_name` - The full qualified name of the collection,
    ///                          beginning with the database name and a dot.
    /// `number_to_skip` - The number of initial documents to skip over in the query
    ///                    results.
    /// `number_to_return - The total number of documents that should be returned by
    ///                     the query.
    /// `return_field_selector - An optional projection of which fields should be
    ///                          present in the documents to be returned by the
    ///                          query.
    ///
    /// # Return value
    ///
    /// Returns the newly-created Message.
    pub fn with_query(header_request_id: i32, flags: OpQueryFlags,
                     full_collection_name: String, number_to_skip: i32,
                     number_to_return: i32, query: BsonDocument,
                     return_field_selector: Option<BsonDocument>) -> Result<Message, String> {
        let header_length = mem::size_of::<Header>() as i32;

        // There are three i32 fields in the an OpQuery (since OpQueryFlags is
        // represented as an 32-bit vector in the wire protocol).
        let i32_length = 3 * mem::size_of::<i32>() as i32;

        // Add an extra byte after the string for null-termination.
        let string_length = full_collection_name.len() as i32 + 1;

        let bson_length = match query.byte_length() {
            Ok(i) => i,
            Err(_) => return Err("Unable to serialize query".to_owned())
        };

        // Add the length of the optional BSON document only if it exists.
        let option_length = match return_field_selector {
            Some(ref bson) => match bson.byte_length() {
                Ok(i) => i,
                Err(_) => return Err("Unable to serialize return_field_selector".to_owned())
            },
            None => 0
        };

        let total_length = header_length + i32_length + string_length +
                           bson_length + option_length;

        let header = Header::with_query(total_length, header_request_id);

        Ok(Message::OpQuery { header: header, flags: flags,
                              full_collection_name: full_collection_name,
                              number_to_skip: number_to_skip,
                              number_to_return: number_to_return, query: query,
                              return_field_selector: return_field_selector })
    }

    /// Writes a serialized BSON document to a given buffer.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to write to.
    /// `bson` - The document to serialize and write.
    ///
    /// # Return value
    ///
    /// Returns nothing on success, or an error string on failure.
    fn write_bson_document(buffer: &mut Write, bson: &BsonDocument) -> Result<(), String>{
        let mut temp_buffer = vec![];

        match bson::encode_document(&mut temp_buffer, bson) {
            Ok(_) => match buffer.write(&temp_buffer) {
                Ok(_) => Ok(()),
                Err(_) => Err("unable to write BSON".to_owned())
            },
            Err(_) => Err("unable to encode BSON".to_owned())
        }
    }

    /// Writes a serialized query message to a given buffer.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to write to.
    /// `header` - The header for the given message.
    /// `flags` - Bit vector of query option.
    /// `full_collection_name` - The full qualified name of the collection,
    ///                          beginning with the database name and a dot.
    /// `number_to_skip` - The number of initial documents to skip over in the
    ///                    query results.
    /// `number_to_return - The total number of documents that should be
    ///                     returned by the query.
    /// `return_field_selector - An optional projection of which fields should
    ///                          be present in the documents to be returned by
    ///                          the query.
    ///
    /// # Return value
    ///
    /// Returns nothing on success, or an error string on failure.
    fn write_query(buffer: &mut Write, header: &Header,
                   flags: &OpQueryFlags, full_collection_name: &str,
                   number_to_skip: i32, number_to_return: i32, query: &BsonDocument,
                   return_field_selector: &Option<BsonDocument>) -> Result<(), String> {
        let _ = match header.write(buffer) {
            Ok(_) => (),
            Err(e) => return Err(e)
        };

        let _ = match buffer.write_i32::<LittleEndian>(flags.to_i32()) {
            Ok(_) => (),
            Err(_) => return Err("Unable to write flags".to_owned())
        };

        for byte in full_collection_name.bytes() {
            let _byte_reponse = match buffer.write_u8(byte) {
                Ok(_) => (),
                Err(_) => return Err("Unable to write full_collection_name".to_owned())
            };
        }

        // Writes the null terminator for the collection name string.
        let _ = match buffer.write_u8(0) {
            Ok(_) => (),
            Err(_) => return Err("Unable to write full_collection_name".to_owned())
        };

        let _ = match buffer.write_i32::<LittleEndian>(number_to_skip) {
            Ok(_) => (),
            Err(_) => return Err("Unable to write number_to_skip".to_owned())
        };

        let _ = match buffer.write_i32::<LittleEndian>(number_to_return) {
            Ok(_) => (),
            Err(_) => return Err("Unable to write number_to_return".to_owned())
        };

        let _ = match Message::write_bson_document(buffer, query) {
            Ok(_) => (),
            Err(s) => return Err(format!("Unable to write query: {}", s))
        };

        let _ = match return_field_selector {
            &Some(ref bson) => match Message::write_bson_document(buffer, bson) {
                Ok(_) => (),
                Err(s) => {
                    let str = format!("Unable to write return_field_selector: {}", s);

                    return Err(str)
                }
            },
            &None => ()
        };

        // match buffer.write_u8(0) {
        //     Ok(_) => (),
        //     Err(_) => return Err("Unable to write bson terminator".to_owned())
        // };

        let _ = buffer.flush();

        Ok(())
    }

    /// Attemps to write a serialized message to a buffer.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to write to.
    ///
    /// # Return value
    ///
    /// Returns nothing on success, or an error string on failure.
    pub fn write(&self, buffer: &mut Write) -> Result<(), String> {
        match self {
            /// Only the server should sent replies
            &Message::OpReply {..} => Err("OP_REPLY should not be sent by the client".to_owned()),
            &Message::OpQuery {
                header: ref h,
                flags: ref f,
                full_collection_name: ref fcn,
                number_to_skip: ns,
                number_to_return: nr,
                query: ref q,
                return_field_selector: ref rfs
            } => Message::write_query(buffer, &h, &f, &fcn, ns, nr, &q, &rfs)
        }
    }

    /// Reads a serialized reply message from a buffer
    ///
    /// FIXME: Right now, this returns only the first BSON document from the
    /// response; if there are more, it ignores the rest, and if there are none,
    /// it fails.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to read from.
    ///
    /// # Return value
    ///
    /// Returns a single BSON document on success, or an error string on
    /// failure.
    fn read_reply(buffer: &mut Read) -> Result<BsonDocument, String> {
        let _flags = match buffer.read_i32::<LittleEndian>() {
            Ok(i) => i,
            Err(_) => return Err("Unable to read flags".to_owned())
        };

        let _cid = match buffer.read_i64::<LittleEndian>() {
            Ok(i) => i,
            Err(_) => return Err("Unable to read cursor_id".to_owned())
        };

        let _sf = match buffer.read_i32::<LittleEndian>() {
            Ok(i) => i,
            Err(_) => return Err("Unable to read starting_from".to_owned())
        };

        let _nr = match buffer.read_i32::<LittleEndian>() {
            Ok(i) => i,
            Err(_) => return Err("Unable to read number_returned".to_owned())
        };

        match bson::decode_document(buffer) {
            Ok(bson) => Ok(bson),
            Err(_) => Err("Unable to read BSON".to_owned())
        }
    }

    /// Attempts to read a serialized reply Message from a buffer.
    ///
    /// NOTE: see the "FIXME" in #read_reply.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to read from.
    ///
    /// # Return value
    ///
    /// Returns a single BSON document on success, or an error string on
    /// failure.
    pub fn read(buffer: &mut Read) -> Result<BsonDocument, String> {
        let header = match Header::read(buffer) {
            Ok(h) => h,
            Err(s) => {
                let str = format!("Unable to read reply header: {}", s);

                return Err(str)
            }
        };

        match header.op_code {
            OpCode::OpReply => Message::read_reply(buffer),
            opcode => {
                let s = format!("Expected to read response but instead found: {}", opcode.to_string());
                Err(s)
            }
        }
    }
}
<commit_msg>removed fixme tag<commit_after>use bson::Document as BsonDocument;
use bson;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use client::wire_protocol::header::{Header, OpCode};
use std::io::{Read, Write};
use std::mem;
use std::result::Result::{Ok, Err};

trait ByteLength {
    /// Calculates the number of bytes in the serialized version of the struct.
    fn byte_length(&self) -> Result<i32, String>;
}

impl ByteLength for BsonDocument {
    /// Gets the length of a BSON document.
    ///
    /// # Return value
    ///
    /// Returns the number of bytes in the serialized BSON document.
    fn byte_length(&self) -> Result<i32, String> {
        let mut temp_buffer = vec![];

        match bson::encode_document(&mut temp_buffer, self) {
            Ok(_) => Ok(temp_buffer.len() as i32),
            Err(_) => Err("unable to serialize BSON document".to_owned())
        }
    }
}

pub struct OpQueryFlags {
    tailable_cursor: bool,    // Bit 1
    slave_ok: bool,           // Bit 2
    oplog_relay: bool,        // Bit 3
    no_cursor_timeout: bool,  // Bit 4
    await_data: bool,         // Bit 5
    exhaust: bool,            // Bit 6
    partial: bool,            // Bit 7

    // All other bits are 0
}

impl OpQueryFlags {
    pub fn new(tc: bool, so: bool, or: bool, nct: bool, ad: bool, e: bool,
           p: bool) -> OpQueryFlags {
        OpQueryFlags{
            tailable_cursor: tc,
            slave_ok: so,
            oplog_relay: or,
            no_cursor_timeout: nct,
            await_data: ad,
            exhaust: e,
            partial: p,
        }
    }

    pub fn no_flags() -> OpQueryFlags {
        OpQueryFlags::new(false, false, false, false, false, false, false)
    }

    fn to_i32(&self) -> i32 {
        let mut i = 0 as i32;

        if self.tailable_cursor {
            let bit = 1 << 1;

            i &= bit;
        }

        if self.slave_ok {
            let bit = 1 << 2;

            i &= bit;
        }

        if self.oplog_relay {
            let bit = 1 << 3;

            i &= bit;
        }

        if self.no_cursor_timeout {
            let bit = 1 << 4;

            i &= bit;
        }

        if self.await_data {
            let bit = 1 << 5;

            i &= bit;
        }

        if self.exhaust {
            let bit = 1 << 6;

            i &= bit;
        }

        if self.partial {
            let bit = 1 << 7;

            i &= bit;
        }

        i
    }
}

/// Represents a message in the MongoDB Wire Protocol.
pub enum Message {
    OpReply {
        header: Header,
        flags: i32,
        cursor_id: i64,
        starting_from: i32,
        number_returned: i32,
        documents: Vec<BsonDocument>,
    },
    OpQuery {
        header: Header,
        flags: OpQueryFlags,
        full_collection_name: String,
        number_to_skip: i32,
        number_to_return: i32,
        query: BsonDocument,
        return_field_selector: Option<BsonDocument>,
    },
}

impl Message {
    /// Constructs a new message request for a query.
    ///
    /// # Arguments
    ///
    /// `header_request_id` - The request ID to be placed in the message header.
    /// `flags` - Bit vector of query options.
    /// `full_collection_name` - The full qualified name of the collection,
    ///                          beginning with the database name and a dot.
    /// `number_to_skip` - The number of initial documents to skip over in the query
    ///                    results.
    /// `number_to_return - The total number of documents that should be returned by
    ///                     the query.
    /// `return_field_selector - An optional projection of which fields should be
    ///                          present in the documents to be returned by the
    ///                          query.
    ///
    /// # Return value
    ///
    /// Returns the newly-created Message.
    pub fn with_query(header_request_id: i32, flags: OpQueryFlags,
                     full_collection_name: String, number_to_skip: i32,
                     number_to_return: i32, query: BsonDocument,
                     return_field_selector: Option<BsonDocument>) -> Result<Message, String> {
        let header_length = mem::size_of::<Header>() as i32;

        // There are three i32 fields in the an OpQuery (since OpQueryFlags is
        // represented as an 32-bit vector in the wire protocol).
        let i32_length = 3 * mem::size_of::<i32>() as i32;

        // Add an extra byte after the string for null-termination.
        let string_length = full_collection_name.len() as i32 + 1;

        let bson_length = match query.byte_length() {
            Ok(i) => i,
            Err(_) => return Err("Unable to serialize query".to_owned())
        };

        // Add the length of the optional BSON document only if it exists.
        let option_length = match return_field_selector {
            Some(ref bson) => match bson.byte_length() {
                Ok(i) => i,
                Err(_) => return Err("Unable to serialize return_field_selector".to_owned())
            },
            None => 0
        };

        let total_length = header_length + i32_length + string_length +
                           bson_length + option_length;

        let header = Header::with_query(total_length, header_request_id);

        Ok(Message::OpQuery { header: header, flags: flags,
                              full_collection_name: full_collection_name,
                              number_to_skip: number_to_skip,
                              number_to_return: number_to_return, query: query,
                              return_field_selector: return_field_selector })
    }

    /// Writes a serialized BSON document to a given buffer.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to write to.
    /// `bson` - The document to serialize and write.
    ///
    /// # Return value
    ///
    /// Returns nothing on success, or an error string on failure.
    fn write_bson_document(buffer: &mut Write, bson: &BsonDocument) -> Result<(), String>{
        let mut temp_buffer = vec![];

        match bson::encode_document(&mut temp_buffer, bson) {
            Ok(_) => match buffer.write(&temp_buffer) {
                Ok(_) => Ok(()),
                Err(_) => Err("unable to write BSON".to_owned())
            },
            Err(_) => Err("unable to encode BSON".to_owned())
        }
    }

    /// Writes a serialized query message to a given buffer.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to write to.
    /// `header` - The header for the given message.
    /// `flags` - Bit vector of query option.
    /// `full_collection_name` - The full qualified name of the collection,
    ///                          beginning with the database name and a dot.
    /// `number_to_skip` - The number of initial documents to skip over in the
    ///                    query results.
    /// `number_to_return - The total number of documents that should be
    ///                     returned by the query.
    /// `return_field_selector - An optional projection of which fields should
    ///                          be present in the documents to be returned by
    ///                          the query.
    ///
    /// # Return value
    ///
    /// Returns nothing on success, or an error string on failure.
    fn write_query(buffer: &mut Write, header: &Header,
                   flags: &OpQueryFlags, full_collection_name: &str,
                   number_to_skip: i32, number_to_return: i32, query: &BsonDocument,
                   return_field_selector: &Option<BsonDocument>) -> Result<(), String> {
        let _ = match header.write(buffer) {
            Ok(_) => (),
            Err(e) => return Err(e)
        };

        let _ = match buffer.write_i32::<LittleEndian>(flags.to_i32()) {
            Ok(_) => (),
            Err(_) => return Err("Unable to write flags".to_owned())
        };

        for byte in full_collection_name.bytes() {
            let _byte_reponse = match buffer.write_u8(byte) {
                Ok(_) => (),
                Err(_) => return Err("Unable to write full_collection_name".to_owned())
            };
        }

        // Writes the null terminator for the collection name string.
        let _ = match buffer.write_u8(0) {
            Ok(_) => (),
            Err(_) => return Err("Unable to write full_collection_name".to_owned())
        };

        let _ = match buffer.write_i32::<LittleEndian>(number_to_skip) {
            Ok(_) => (),
            Err(_) => return Err("Unable to write number_to_skip".to_owned())
        };

        let _ = match buffer.write_i32::<LittleEndian>(number_to_return) {
            Ok(_) => (),
            Err(_) => return Err("Unable to write number_to_return".to_owned())
        };

        let _ = match Message::write_bson_document(buffer, query) {
            Ok(_) => (),
            Err(s) => return Err(format!("Unable to write query: {}", s))
        };

        let _ = match return_field_selector {
            &Some(ref bson) => match Message::write_bson_document(buffer, bson) {
                Ok(_) => (),
                Err(s) => {
                    let str = format!("Unable to write return_field_selector: {}", s);

                    return Err(str)
                }
            },
            &None => ()
        };

        // match buffer.write_u8(0) {
        //     Ok(_) => (),
        //     Err(_) => return Err("Unable to write bson terminator".to_owned())
        // };

        let _ = buffer.flush();

        Ok(())
    }

    /// Attemps to write a serialized message to a buffer.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to write to.
    ///
    /// # Return value
    ///
    /// Returns nothing on success, or an error string on failure.
    pub fn write(&self, buffer: &mut Write) -> Result<(), String> {
        match self {
            /// Only the server should sent replies
            &Message::OpReply {..} => Err("OP_REPLY should not be sent by the client".to_owned()),
            &Message::OpQuery {
                header: ref h,
                flags: ref f,
                full_collection_name: ref fcn,
                number_to_skip: ns,
                number_to_return: nr,
                query: ref q,
                return_field_selector: ref rfs
            } => Message::write_query(buffer, &h, &f, &fcn, ns, nr, &q, &rfs)
        }
    }

    /// Reads a serialized reply message from a buffer
    ///
    /// Right now, this returns only the first BSON document from the
    /// response; if there are more, it ignores the rest, and if there are none,
    /// it fails.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to read from.
    ///
    /// # Return value
    ///
    /// Returns a single BSON document on success, or an error string on
    /// failure.
    fn read_reply(buffer: &mut Read) -> Result<BsonDocument, String> {
        let _flags = match buffer.read_i32::<LittleEndian>() {
            Ok(i) => i,
            Err(_) => return Err("Unable to read flags".to_owned())
        };

        let _cid = match buffer.read_i64::<LittleEndian>() {
            Ok(i) => i,
            Err(_) => return Err("Unable to read cursor_id".to_owned())
        };

        let _sf = match buffer.read_i32::<LittleEndian>() {
            Ok(i) => i,
            Err(_) => return Err("Unable to read starting_from".to_owned())
        };

        let _nr = match buffer.read_i32::<LittleEndian>() {
            Ok(i) => i,
            Err(_) => return Err("Unable to read number_returned".to_owned())
        };

        match bson::decode_document(buffer) {
            Ok(bson) => Ok(bson),
            Err(_) => Err("Unable to read BSON".to_owned())
        }
    }

    /// Attempts to read a serialized reply Message from a buffer.
    ///
    /// # Arguments
    ///
    /// `buffer` - The buffer to read from.
    ///
    /// # Return value
    ///
    /// Returns a single BSON document on success, or an error string on
    /// failure.
    pub fn read(buffer: &mut Read) -> Result<BsonDocument, String> {
        let header = match Header::read(buffer) {
            Ok(h) => h,
            Err(s) => {
                let str = format!("Unable to read reply header: {}", s);

                return Err(str)
            }
        };

        match header.op_code {
            OpCode::OpReply => Message::read_reply(buffer),
            opcode => {
                let s = format!("Expected to read response but instead found: {}", opcode.to_string());
                Err(s)
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(docopt_macros)]

extern crate rustc_serialize;
extern crate docopt;
extern crate glob;
extern crate littletest;

mod tests;

docopt!(pub Args derive Debug, "
Usage: sassaurs_spec [options] [<spec-dir>]
       sassaurs_spec --help

Options:
  -c COMMAND, --command COMMAND
                     Sets a specific binary to run
                     [default: sassc]
  -s, --skip         Skip tests that fail to exit successfully.
  -t, --tap          Output TAP compatible report.
  -v, --verbose      Run verbosely.
  --limit NUMBER     Limit the number of tests run to this positive integer.
  --filter PATTERN   Run tests that match the pattern you provide
  --ignore-todo      Skip any folder named 'todo'.
  --silent           Don't show any logs.
  --nuke             Write a new expected_output for every test.
  --unexpected-pass  When running the todo tests, flag as an error when a test
                     passes which is marked as todo.
",
flag_limit: Option<usize>,
flag_filter: Option<String>,
arg_spec_dir: Option<String>);

fn main() {
    let args: Args = Args::docopt()
        .decode()
        .unwrap_or_else(|e| e.exit());

    let directory = match args.arg_spec_dir {
        None => "sass-spec/spec",
        Some(ref dir) => dir.as_ref()
    };

    if !args.flag_silent && !args.flag_tap {
        println!("Recursively searching under directory '{}' \
            for test files to test '{}' with.",
            directory,
            args.flag_command);
        println!("{}", version(&args.flag_command));
    }

    let path = std::path::Path::new(directory);
    let opts = tests::RunOptions {
        ignore_todo: args.flag_ignore_todo,
        command: args.flag_command
    };

    let runnables = tests::load(path, &opts);
}

fn version(command: &str) -> String {
    let executable = command.split(' ').next().unwrap();
    match exec(executable, &["-v"]) {
        Some(output) => output,
        None => match exec(executable, &["-V"]) {
            Some(output) => output,
            None => panic!("Could not get version of {}", executable)
        }
    }
}

fn exec(command: &str, args: &[&str]) -> Option<String> {
    use std::process::Command;
    let mut wrapper = Command::new(command);
    match wrapper.args(args).output() {
        Ok(output) => match output.status.success() {
            true => Some(String::from_utf8(output.stdout).unwrap().to_string()),
            _ => None
        },
        Err(e) => panic!("failed to execute process: '{:?}' error: '{}'", wrapper, e)
    }
}
<commit_msg>Run the tests.<commit_after>#![feature(plugin)]
#![plugin(docopt_macros)]

extern crate rustc_serialize;
extern crate docopt;
extern crate glob;
extern crate littletest;

mod tests;

docopt!(pub Args derive Debug, "
Usage: sassaurs_spec [options] [<spec-dir>]
       sassaurs_spec --help

Options:
  -c COMMAND, --command COMMAND
                     Sets a specific binary to run
                     [default: sassc]
  -s, --skip         Skip tests that fail to exit successfully.
  -t, --tap          Output TAP compatible report.
  -v, --verbose      Run verbosely.
  --limit NUMBER     Limit the number of tests run to this positive integer.
  --filter PATTERN   Run tests that match the pattern you provide
  --ignore-todo      Skip any folder named 'todo'.
  --silent           Don't show any logs.
  --nuke             Write a new expected_output for every test.
  --unexpected-pass  When running the todo tests, flag as an error when a test
                     passes which is marked as todo.
",
flag_limit: Option<usize>,
flag_filter: Option<String>,
arg_spec_dir: Option<String>);

fn main() {
    let args: Args = Args::docopt()
        .decode()
        .unwrap_or_else(|e| e.exit());

    let directory = match args.arg_spec_dir {
        None => "sass-spec/spec",
        Some(ref dir) => dir.as_ref()
    };

    if !args.flag_silent && !args.flag_tap {
        println!("Recursively searching under directory '{}' \
            for test files to test '{}' with.",
            directory,
            args.flag_command);
        println!("{}", version(&args.flag_command));
    }

    let path = std::path::Path::new(directory);
    let opts = tests::RunOptions {
        ignore_todo: args.flag_ignore_todo,
        command: args.flag_command
    };

    let runnables = tests::load(path, &opts);

    let runner = littletest::TestRunner::new(littletest::TestOptions {
        parallelism: Some(4)
    });
    runner.run(&runnables);
}

fn version(command: &str) -> String {
    let executable = command.split(' ').next().unwrap();
    match exec(executable, &["-v"]) {
        Some(output) => output,
        None => match exec(executable, &["-V"]) {
            Some(output) => output,
            None => panic!("Could not get version of {}", executable)
        }
    }
}

fn exec(command: &str, args: &[&str]) -> Option<String> {
    use std::process::Command;
    let mut wrapper = Command::new(command);
    match wrapper.args(args).output() {
        Ok(output) => match output.status.success() {
            true => Some(String::from_utf8(output.stdout).unwrap().to_string()),
            _ => None
        },
        Err(e) => panic!("failed to execute process: '{:?}' error: '{}'", wrapper, e)
    }
}
<|endoftext|>


<commit_before>use data::{Value, List, Scope, Function, RuntimeError};
use data::RuntimeError::*;
use scope::{GlobalScope, LocalScope};

pub struct BuiltinFn
{
    pub name: &'static str,
    pub do_eval: bool,
    pub func: Box<Fn(&List, &mut Scope) -> Result<Value, RuntimeError>>,
}

impl Function for BuiltinFn
{
    fn call(&self, args: &List, env: &mut Scope, do_ev: bool) -> Result<Value, RuntimeError>
    {
        if do_ev && self.do_eval
        {
            (self.func)(&try!(args.eval(env)), env)
        }
        else
        {
            (self.func)(args, env)
        }
    }

    fn get_name(&self) -> &str
    {
        self.name
    }
}

macro_rules! check_arg
{
    ($it:expr, $num:expr, $cur:expr) => (match $it.next() {
        Some(val) => val,
        None => return Err(InvalidArgNum($num, $cur)),
    });
    ($it:expr, $ty:ident, $num:expr, $cur:expr) => (match $it.next() {
        Some(Value::$ty(val)) => val,
        Some(other) => return Err(InvalidArgType(stringify!($ty), other.type_name())),
        None => return Err(InvalidArgNum($num, $cur)),
    });
}

macro_rules! map_value
{
    ($v:expr, $ty:ident, $f:expr) => (match $v {
        Value::$ty(val) => Ok($f(val)),
        _ => return Err(InvalidArgType(stringify!($ty), $v.type_name())),
    })
}

pub fn load_builtins(env: &mut GlobalScope)
{
    env.set_builtin("quote", false, |args, _| {
        args.iter().next().ok_or(InvalidArgNum(1, 0))
    });

    fn assign_impl<'a, F>(args: &List, env: &'a mut Scope, f: F) -> Result<Value, RuntimeError>
        where F: Fn(&'a mut Scope, &str, Value)
    {
        let mut iter = args.iter();
        let key = check_arg!(iter, Symbol, 2, 0);
        let val = try!(check_arg!(iter, 2, 1).eval(env));
        f(env, &key, val.clone());
        Ok(val)
    };

    env.set_builtin("let", false, |args, env| assign_impl(args, env, Scope::decl));
    env.set_builtin("set", false, |args, env| assign_impl(args, env, Scope::set));

    env.set_builtin("funcall", true, |args, env| args.call(env));

    env.set_builtin("apply", true, |args, env| {
        let mut iter = args.iter();
        let func = check_arg!(iter, 2, 0);
        let lst = check_arg!(iter, List, 2, 1);
        List::cons(func, lst).call(env)
    });

    env.set_builtin("map", true, |args, env| {
        let mut iter = args.iter();
        let func = check_arg!(iter, Function, 2, 0);
        let lst = check_arg!(iter, List, 2, 1);
        lst.iter().map(|val| func.call(&val.wrap(), env, false)).collect::<Result<_, _>>()
            .map(|lst| Value::List(lst))
    });

    env.set_builtin("fold", true, |args, env| {
        let mut iter = args.iter();
        let func = check_arg!(iter, Function, 3, 0);
        let init = check_arg!(iter, 3, 1);
        let lst = check_arg!(iter, List, 3, 2);
        lst.fold(init, |acc, val| func.call(&List::cons(acc, val.wrap()), env, false))
    });

    env.set_builtin("car", true, |args, _| {
        let mut iter = args.iter();
        let lst = check_arg!(iter, List, 1, 0);
        Ok(match lst {
            List::Node(cons) => cons.car.clone(),
            _ => Value::Nil,
        })
    });

    env.set_builtin("cdr", true, |args, _| {
        let mut iter = args.iter();
        let lst = check_arg!(iter, List, 1, 0);
        Ok(match lst {
            List::Node(cons) => Value::List(cons.cdr.clone()),
            _ => Value::Nil,
        })
    });

    env.set_builtin("cons", true, |args, _| {
        let mut iter = args.iter();
        let car = check_arg!(iter, 2, 0);
        let cdr = check_arg!(iter, List, 2, 1);
        Ok(Value::List(List::cons(car, cdr)))
    });

    env.set_builtin("list", true, |args, _| {
        Ok(Value::List(args.clone()))
    });

    env.set_builtin("not", true, |args, _| {
        let mut iter = args.iter();
        let val = check_arg!(iter, 1, 0);
        Ok(Value::Bool(match val {
            Value::Nil | Value::Bool(false) => true,
            _ => false,
        }))
    });

    env.set_builtin("and", false, |args, env| {
        let mut iter = args.iter();
        let mut last = Value::Bool(true);
        while let Some(val) = iter.next()
        {
            match try!(val.eval(env)) {
                v @ Value::Nil | v @ Value::Bool(false) => return Ok(v),
                other => last = other,
            }
        }
        Ok(last)
    });

    env.set_builtin("or", false, |args, env| {
        let mut iter = args.iter();
        let mut last = Value::Bool(false);
        while let Some(val) = iter.next()
        {
            match try!(val.eval(env)) {
                v @ Value::Nil | v @ Value::Bool(false) => last = v,
                other => return Ok(other),
            }
        }
        Ok(last)
    });

    env.set_builtin("if", false, |args, env| {
        let mut iter = args.iter();
        let cond = check_arg!(iter, 2, 0);
        let then = check_arg!(iter, 2, 1);
        match try!(cond.eval(env)) {
            Value::Nil | Value::Bool(false) => iter.next().unwrap_or(Value::Nil).eval(env),
            _ => then.eval(env),
        }
    });

    env.set_builtin("begin", false, |args, env| {
        let mut local = LocalScope::new(env);
        args.iter().map(|val| val.eval(&mut local)).last().unwrap_or(Ok(Value::Nil))
    });

    env.set_builtin("eval", true, |args, env| {
        let mut iter = args.iter();
        let expr = check_arg!(iter, 1, 0);
        expr.eval(env)
    });

    env.set_builtin("+", true, |args, _| {
        args.fold(0.0, |acc, val| map_value!(val, Number, |n| acc + n)).map(|n| Value::Number(n))
    });

    env.set_builtin("*", true, |args, _| {
        args.fold(1.0, |acc, val| map_value!(val, Number, |n| acc * n)).map(|n| Value::Number(n))
    });
}
<commit_msg>removed reduntant return<commit_after>use data::{Value, List, Scope, Function, RuntimeError};
use data::RuntimeError::*;
use scope::{GlobalScope, LocalScope};

pub struct BuiltinFn
{
    pub name: &'static str,
    pub do_eval: bool,
    pub func: Box<Fn(&List, &mut Scope) -> Result<Value, RuntimeError>>,
}

impl Function for BuiltinFn
{
    fn call(&self, args: &List, env: &mut Scope, do_ev: bool) -> Result<Value, RuntimeError>
    {
        if do_ev && self.do_eval
        {
            (self.func)(&try!(args.eval(env)), env)
        }
        else
        {
            (self.func)(args, env)
        }
    }

    fn get_name(&self) -> &str
    {
        self.name
    }
}

macro_rules! check_arg
{
    ($it:expr, $num:expr, $cur:expr) => (match $it.next() {
        Some(val) => val,
        None => return Err(InvalidArgNum($num, $cur)),
    });
    ($it:expr, $ty:ident, $num:expr, $cur:expr) => (match $it.next() {
        Some(Value::$ty(val)) => val,
        Some(other) => return Err(InvalidArgType(stringify!($ty), other.type_name())),
        None => return Err(InvalidArgNum($num, $cur)),
    });
}

macro_rules! map_value
{
    ($v:expr, $ty:ident, $f:expr) => (match $v {
        Value::$ty(val) => Ok($f(val)),
        _ => Err(InvalidArgType(stringify!($ty), $v.type_name())),
    })
}

pub fn load_builtins(env: &mut GlobalScope)
{
    env.set_builtin("quote", false, |args, _| {
        args.iter().next().ok_or(InvalidArgNum(1, 0))
    });

    fn assign_impl<'a, F>(args: &List, env: &'a mut Scope, f: F) -> Result<Value, RuntimeError>
        where F: Fn(&'a mut Scope, &str, Value)
    {
        let mut iter = args.iter();
        let key = check_arg!(iter, Symbol, 2, 0);
        let val = try!(check_arg!(iter, 2, 1).eval(env));
        f(env, &key, val.clone());
        Ok(val)
    };

    env.set_builtin("let", false, |args, env| assign_impl(args, env, Scope::decl));
    env.set_builtin("set", false, |args, env| assign_impl(args, env, Scope::set));

    env.set_builtin("funcall", true, |args, env| args.call(env));

    env.set_builtin("apply", true, |args, env| {
        let mut iter = args.iter();
        let func = check_arg!(iter, 2, 0);
        let lst = check_arg!(iter, List, 2, 1);
        List::cons(func, lst).call(env)
    });

    env.set_builtin("map", true, |args, env| {
        let mut iter = args.iter();
        let func = check_arg!(iter, Function, 2, 0);
        let lst = check_arg!(iter, List, 2, 1);
        lst.iter().map(|val| func.call(&val.wrap(), env, false)).collect::<Result<_, _>>()
            .map(|lst| Value::List(lst))
    });

    env.set_builtin("fold", true, |args, env| {
        let mut iter = args.iter();
        let func = check_arg!(iter, Function, 3, 0);
        let init = check_arg!(iter, 3, 1);
        let lst = check_arg!(iter, List, 3, 2);
        lst.fold(init, |acc, val| func.call(&List::cons(acc, val.wrap()), env, false))
    });

    env.set_builtin("car", true, |args, _| {
        let mut iter = args.iter();
        let lst = check_arg!(iter, List, 1, 0);
        Ok(match lst {
            List::Node(cons) => cons.car.clone(),
            _ => Value::Nil,
        })
    });

    env.set_builtin("cdr", true, |args, _| {
        let mut iter = args.iter();
        let lst = check_arg!(iter, List, 1, 0);
        Ok(match lst {
            List::Node(cons) => Value::List(cons.cdr.clone()),
            _ => Value::Nil,
        })
    });

    env.set_builtin("cons", true, |args, _| {
        let mut iter = args.iter();
        let car = check_arg!(iter, 2, 0);
        let cdr = check_arg!(iter, List, 2, 1);
        Ok(Value::List(List::cons(car, cdr)))
    });

    env.set_builtin("list", true, |args, _| {
        Ok(Value::List(args.clone()))
    });

    env.set_builtin("not", true, |args, _| {
        let mut iter = args.iter();
        let val = check_arg!(iter, 1, 0);
        Ok(Value::Bool(match val {
            Value::Nil | Value::Bool(false) => true,
            _ => false,
        }))
    });

    env.set_builtin("and", false, |args, env| {
        let mut iter = args.iter();
        let mut last = Value::Bool(true);
        while let Some(val) = iter.next()
        {
            match try!(val.eval(env)) {
                v @ Value::Nil | v @ Value::Bool(false) => return Ok(v),
                other => last = other,
            }
        }
        Ok(last)
    });

    env.set_builtin("or", false, |args, env| {
        let mut iter = args.iter();
        let mut last = Value::Bool(false);
        while let Some(val) = iter.next()
        {
            match try!(val.eval(env)) {
                v @ Value::Nil | v @ Value::Bool(false) => last = v,
                other => return Ok(other),
            }
        }
        Ok(last)
    });

    env.set_builtin("if", false, |args, env| {
        let mut iter = args.iter();
        let cond = check_arg!(iter, 2, 0);
        let then = check_arg!(iter, 2, 1);
        match try!(cond.eval(env)) {
            Value::Nil | Value::Bool(false) => iter.next().unwrap_or(Value::Nil).eval(env),
            _ => then.eval(env),
        }
    });

    env.set_builtin("begin", false, |args, env| {
        let mut local = LocalScope::new(env);
        args.iter().map(|val| val.eval(&mut local)).last().unwrap_or(Ok(Value::Nil))
    });

    env.set_builtin("eval", true, |args, env| {
        let mut iter = args.iter();
        let expr = check_arg!(iter, 1, 0);
        expr.eval(env)
    });

    env.set_builtin("+", true, |args, _| {
        args.fold(0.0, |acc, val| map_value!(val, Number, |n| acc + n)).map(|n| Value::Number(n))
    });

    env.set_builtin("*", true, |args, _| {
        args.fold(1.0, |acc, val| map_value!(val, Number, |n| acc * n)).map(|n| Value::Number(n))
    });
}
<|endoftext|>


<commit_before>use std::any::Any;
use std::mem;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use slab::Slab;

use na::Real;
use math::Point;
use utils::{DeterministicState, SortedPair};
use bounding_volume::{BoundingVolume, BoundingVolumeInterferencesCollector};
use partitioning::{DBVTLeaf, DBVTLeafId, DBVT};
use query::{PointInterferencesCollector, PointQuery, Ray, RayCast, RayInterferencesCollector};
use pipeline::broad_phase::{BroadPhase, ProxyHandle};

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum ProxyStatus {
    OnStaticTree(DBVTLeafId),
    OnDynamicTree(DBVTLeafId, usize),
    Detached(Option<usize>), // The usize is the location of the corresponding on proxies_to_update
    Deleted,
}

struct DBVTBroadPhaseProxy<T> {
    data: T,
    status: ProxyStatus,
    updated: bool,
}

impl<T> DBVTBroadPhaseProxy<T> {
    fn new(data: T) -> DBVTBroadPhaseProxy<T> {
        DBVTBroadPhaseProxy {
            data: data,
            status: ProxyStatus::Detached(None),
            updated: true,
        }
    }

    fn is_detached(&self) -> bool {
        match self.status {
            ProxyStatus::Detached(_) => true,
            _ => false,
        }
    }
}

const DEACTIVATION_THRESHOLD: usize = 100;

/// Broad phase based on a Dynamic Bounding Volume Tree.
///
/// It uses two separate trees: one for static objects and which is never updated, and one for
/// moving objects.
pub struct DBVTBroadPhase<N: Real, BV, T> {
    proxies: Slab<DBVTBroadPhaseProxy<T>>,
    tree: DBVT<N, ProxyHandle, BV>,  // DBVT for moving objects.
    stree: DBVT<N, ProxyHandle, BV>, // DBVT for static objects.
    pairs: HashMap<SortedPair<ProxyHandle>, bool, DeterministicState>, // Pairs detected.
    margin: N,                       // The margin added to each bounding volume.
    purge_all: bool,

    // Just to avoid dynamic allocations.
    collector: Vec<ProxyHandle>,
    pairs_to_remove: Vec<SortedPair<ProxyHandle>>,
    leaves_to_update: Vec<DBVTLeaf<N, ProxyHandle, BV>>,
    proxies_to_update: Vec<(ProxyHandle, BV)>,
}

impl<N, BV, T> DBVTBroadPhase<N, BV, T>
where
    N: Real,
    BV: 'static + BoundingVolume<N> + Clone,
{
    /// Creates a new broad phase based on a Dynamic Bounding Volume Tree.
    pub fn new(margin: N) -> DBVTBroadPhase<N, BV, T> {
        DBVTBroadPhase {
            proxies: Slab::new(),
            tree: DBVT::new(),
            stree: DBVT::new(),
            pairs: HashMap::with_hasher(DeterministicState::new()),
            purge_all: false,
            collector: Vec::new(),
            leaves_to_update: Vec::new(),
            pairs_to_remove: Vec::new(),
            proxies_to_update: Vec::new(),
            margin: margin,
        }
    }

    /// Number of interferences detected by this broad phase.
    #[inline]
    pub fn num_interferences(&self) -> usize {
        self.pairs.len()
    }

    fn purge_some_contact_pairs(
        &mut self,
        allow_proximity: &mut FnMut(&T, &T) -> bool,
        handler: &mut FnMut(&T, &T, bool),
    ) {
        for (pair, up_to_date) in &mut self.pairs {
            if self.purge_all || !*up_to_date {
                *up_to_date = true;
                let mut remove = true;

                let proxy1 = self.proxies
                    .get(pair.0.uid())
                    .expect("DBVT broad phase: internal error.");
                let proxy2 = self.proxies
                    .get(pair.1.uid())
                    .expect("DBVT broad phase: internal error.");

                if self.purge_all || proxy1.updated || proxy2.updated {
                    if allow_proximity(&proxy1.data, &proxy2.data) {
                        let l1 = match proxy1.status {
                            ProxyStatus::OnStaticTree(leaf) => &self.stree[leaf],
                            ProxyStatus::OnDynamicTree(leaf, _) => &self.tree[leaf],
                            _ => panic!("DBVT broad phase: internal error."),
                        };

                        let l2 = match proxy2.status {
                            ProxyStatus::OnStaticTree(leaf) => &self.stree[leaf],
                            ProxyStatus::OnDynamicTree(leaf, _) => &self.tree[leaf],
                            _ => panic!("DBVT broad phase: internal error."),
                        };

                        if l1.bounding_volume.intersects(&l2.bounding_volume) {
                            remove = false
                        }
                    }
                } else {
                    remove = false;
                }

                if remove {
                    handler(&proxy1.data, &proxy2.data, false);
                    self.pairs_to_remove.push(*pair);
                }
            }

            *up_to_date = false;
        }

        /*
         * Actually remove the pairs.
         */
        for pair in self.pairs_to_remove.drain(..) {
            let _ = self.pairs.remove(&pair);
        }
    }

    fn update_activation_states(&mut self) {
        /*
         * Update activation states.
         * FIXME: could we avoid having to iterate through _all_ the proxies at each update?
         */
        for (_, proxy) in self.proxies.iter_mut() {
            if let ProxyStatus::OnDynamicTree(leaf, energy) = proxy.status {
                if energy == 1 {
                    let old_leaf = self.tree.remove(leaf);
                    let new_leaf = self.stree.insert(old_leaf);
                    proxy.status = ProxyStatus::OnStaticTree(new_leaf);
                } else {
                    proxy.status = ProxyStatus::OnDynamicTree(leaf, energy - 1)
                }
            }
        }
    }
}

impl<N, BV, T> BroadPhase<N, BV, T> for DBVTBroadPhase<N, BV, T>
where
    N: Real,
    BV: BoundingVolume<N> + RayCast<N> + PointQuery<N> + Any + Send + Sync + Clone,
    T: Any + Send + Sync,
{
    fn update(
        &mut self,
        allow_proximity: &mut FnMut(&T, &T) -> bool,
        handler: &mut FnMut(&T, &T, bool),
    ) {
        /*
         * Remove from the trees all nodes that have been deleted or modified.
         */
        for (handle, bv) in self.proxies_to_update.drain(..) {
            if let Some(proxy) = self.proxies.get_mut(handle.uid()) {
                let mut set_status = true;
                match proxy.status {
                    ProxyStatus::OnStaticTree(leaf) => {
                        let mut leaf = self.stree.remove(leaf);
                        leaf.bounding_volume = bv;
                        self.leaves_to_update.push(leaf);
                    }
                    ProxyStatus::OnDynamicTree(leaf, _) => {
                        let mut leaf = self.tree.remove(leaf);
                        leaf.bounding_volume = bv;
                        self.leaves_to_update.push(leaf);
                    }
                    ProxyStatus::Detached(None) => {
                        let leaf = DBVTLeaf::new(bv, handle);
                        self.leaves_to_update.push(leaf);
                    }
                    ProxyStatus::Detached(Some(id)) => {
                        let leaf = DBVTLeaf::new(bv, handle);
                        self.leaves_to_update[id] = leaf;
                        set_status = false;
                    }
                    ProxyStatus::Deleted => {
                        panic!("DBVT broad phase internal error: the proxy was deleted.")
                    }
                }

                proxy.updated = true;

                if set_status {
                    proxy.status = ProxyStatus::Detached(Some(self.leaves_to_update.len() - 1));
                }
            }
        }

        /*
         * Re-insert outdated nodes one by one and collect interferences at the same time.
         */
        let some_leaves_updated = self.leaves_to_update.len() != 0;
        for leaf in self.leaves_to_update.drain(..) {
            {
                let proxy1 = &self.proxies[leaf.data.uid()];
                {
                    let mut visitor = BoundingVolumeInterferencesCollector::new(
                        &leaf.bounding_volume,
                        &mut self.collector,
                    );

                    self.tree.visit(&mut visitor);
                    self.stree.visit(&mut visitor);
                }

                // Event generation.
                for proxy_key2 in self.collector.iter() {
                    let proxy2 = &self.proxies[proxy_key2.uid()];

                    if allow_proximity(&proxy1.data, &proxy2.data) {
                        match self.pairs.entry(SortedPair::new(leaf.data, *proxy_key2)) {
                            Entry::Occupied(entry) => *entry.into_mut() = true,
                            Entry::Vacant(entry) => {
                                handler(&proxy1.data, &proxy2.data, true);
                                let _ = entry.insert(true);
                            }
                        }
                    }
                }

                self.collector.clear();
            }

            let proxy1 = &mut self.proxies[leaf.data.uid()];
            assert!(proxy1.is_detached());
            let leaf = self.tree.insert(leaf);
            proxy1.status = ProxyStatus::OnDynamicTree(leaf, DEACTIVATION_THRESHOLD);
        }

        if some_leaves_updated {
            self.purge_some_contact_pairs(allow_proximity, handler);
        }
        self.update_activation_states();
    }

    fn create_proxy(&mut self, bv: BV, data: T) -> ProxyHandle {
        let proxy = DBVTBroadPhaseProxy::new(data);
        let handle = ProxyHandle(self.proxies.insert(proxy));
        self.proxies_to_update.push((handle, bv));
        handle
    }

    fn remove(&mut self, handles: &[ProxyHandle], handler: &mut FnMut(&T, &T)) {
        for handle in handles {
            if let Some(proxy) = self.proxies.get_mut(handle.uid()) {
                match proxy.status {
                    ProxyStatus::OnStaticTree(leaf) => {
                        let _ = self.stree.remove(leaf);
                    }
                    ProxyStatus::OnDynamicTree(leaf, _) => {
                        let _ = self.tree.remove(leaf);
                    }
                    _ => {}
                }

                proxy.status = ProxyStatus::Deleted;
            } else {
                panic!("Attempting to remove an object that does not exist.");
            }
        }

        for (pair, _) in &mut self.pairs {
            let proxy1 = self.proxies
                .get(pair.0.uid())
                .expect("DBVT broad phase: internal error.");
            let proxy2 = self.proxies
                .get(pair.1.uid())
                .expect("DBVT broad phase: internal error.");

            if proxy1.status == ProxyStatus::Deleted || proxy2.status == ProxyStatus::Deleted {
                handler(&proxy1.data, &proxy2.data);
                self.pairs_to_remove.push(*pair)
            }
        }

        for pair in self.pairs_to_remove.iter() {
            let _ = self.pairs.remove(pair);
        }
        self.pairs_to_remove.clear();

        for handle in handles {
            let _ = self.proxies.remove(handle.uid());
        }
    }

    fn deferred_set_bounding_volume(&mut self, handle: ProxyHandle, bounding_volume: BV) {
        if let Some(proxy) = self.proxies.get(handle.uid()) {
            let needs_update = match proxy.status {
                ProxyStatus::OnStaticTree(leaf) => {
                    !self.stree[leaf].bounding_volume.contains(&bounding_volume)
                }
                ProxyStatus::OnDynamicTree(leaf, _) => {
                    !self.tree[leaf].bounding_volume.contains(&bounding_volume)
                }
                ProxyStatus::Detached(_) => true,
                ProxyStatus::Deleted => {
                    panic!("DBVT broad phase: internal error, proxy not found.")
                }
            };

            if needs_update {
                let new_bv = bounding_volume.loosened(self.margin);
                self.proxies_to_update.push((handle, new_bv));
            }
        } else {
            panic!("Attempting to set the bounding volume of an object that does not exist.");
        }
    }

    fn deferred_recompute_all_proximities_with(&mut self, handle: ProxyHandle) {
        if let Some(proxy) = self.proxies.get(handle.uid()) {
            let bv = match proxy.status {
                ProxyStatus::OnStaticTree(leaf) => self.stree[leaf].bounding_volume.clone(),
                ProxyStatus::OnDynamicTree(leaf, _) => self.tree[leaf].bounding_volume.clone(),
                ProxyStatus::Detached(_) => return,
                ProxyStatus::Deleted => {
                    panic!("DBVT broad phase: internal error, proxy not found.")
                }
            };

            self.proxies_to_update.push((handle, bv));
        }
    }

    fn deferred_recompute_all_proximities(&mut self) {
        let mut user_updates = mem::replace(&mut self.proxies_to_update, Vec::new());

        for (handle, proxy) in self.proxies.iter() {
            let bv;
            match proxy.status {
                ProxyStatus::OnStaticTree(leaf) => {
                    bv = self.stree[leaf].bounding_volume.clone();
                }
                ProxyStatus::OnDynamicTree(leaf, _) => {
                    bv = self.tree[leaf].bounding_volume.clone();
                }
                ProxyStatus::Detached(_) => continue,
                ProxyStatus::Deleted => {
                    panic!("DBVT broad phase: internal error, proxy not found.")
                }
            }

            self.proxies_to_update.push((ProxyHandle(handle), bv));
        }

        self.proxies_to_update.append(&mut user_updates);
        self.purge_all = true;
    }

    fn interferences_with_bounding_volume<'a>(&'a self, bv: &BV, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = BoundingVolumeInterferencesCollector::new(bv, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l.uid()].data)
        }
    }

    fn interferences_with_ray<'a>(&'a self, ray: &Ray<N>, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = RayInterferencesCollector::new(ray, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l.uid()].data)
        }
    }

    fn interferences_with_point<'a>(&'a self, point: &Point<N>, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = PointInterferencesCollector::new(point, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l.uid()].data)
        }
    }
}
<commit_msg>Make DBVTBroadPhase::pairs_to_remove obsolete via HashMap::retain().<commit_after>use std::any::Any;
use std::mem;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use slab::Slab;

use na::Real;
use math::Point;
use utils::{DeterministicState, SortedPair};
use bounding_volume::{BoundingVolume, BoundingVolumeInterferencesCollector};
use partitioning::{DBVTLeaf, DBVTLeafId, DBVT};
use query::{PointInterferencesCollector, PointQuery, Ray, RayCast, RayInterferencesCollector};
use pipeline::broad_phase::{BroadPhase, ProxyHandle};

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum ProxyStatus {
    OnStaticTree(DBVTLeafId),
    OnDynamicTree(DBVTLeafId, usize),
    Detached(Option<usize>), // The usize is the location of the corresponding on proxies_to_update
    Deleted,
}

struct DBVTBroadPhaseProxy<T> {
    data: T,
    status: ProxyStatus,
    updated: bool,
}

impl<T> DBVTBroadPhaseProxy<T> {
    fn new(data: T) -> DBVTBroadPhaseProxy<T> {
        DBVTBroadPhaseProxy {
            data: data,
            status: ProxyStatus::Detached(None),
            updated: true,
        }
    }

    fn is_detached(&self) -> bool {
        match self.status {
            ProxyStatus::Detached(_) => true,
            _ => false,
        }
    }
}

const DEACTIVATION_THRESHOLD: usize = 100;

/// Broad phase based on a Dynamic Bounding Volume Tree.
///
/// It uses two separate trees: one for static objects and which is never updated, and one for
/// moving objects.
pub struct DBVTBroadPhase<N: Real, BV, T> {
    proxies: Slab<DBVTBroadPhaseProxy<T>>,
    tree: DBVT<N, ProxyHandle, BV>,  // DBVT for moving objects.
    stree: DBVT<N, ProxyHandle, BV>, // DBVT for static objects.
    pairs: HashMap<SortedPair<ProxyHandle>, bool, DeterministicState>, // Pairs detected.
    margin: N,                       // The margin added to each bounding volume.
    purge_all: bool,

    // Just to avoid dynamic allocations.
    collector: Vec<ProxyHandle>,
    leaves_to_update: Vec<DBVTLeaf<N, ProxyHandle, BV>>,
    proxies_to_update: Vec<(ProxyHandle, BV)>,
}

impl<N, BV, T> DBVTBroadPhase<N, BV, T>
where
    N: Real,
    BV: 'static + BoundingVolume<N> + Clone,
{
    /// Creates a new broad phase based on a Dynamic Bounding Volume Tree.
    pub fn new(margin: N) -> DBVTBroadPhase<N, BV, T> {
        DBVTBroadPhase {
            proxies: Slab::new(),
            tree: DBVT::new(),
            stree: DBVT::new(),
            pairs: HashMap::with_hasher(DeterministicState::new()),
            purge_all: false,
            collector: Vec::new(),
            leaves_to_update: Vec::new(),
            proxies_to_update: Vec::new(),
            margin: margin,
        }
    }

    /// Number of interferences detected by this broad phase.
    #[inline]
    pub fn num_interferences(&self) -> usize {
        self.pairs.len()
    }

    fn purge_some_contact_pairs(
        &mut self,
        allow_proximity: &mut FnMut(&T, &T) -> bool,
        handler: &mut FnMut(&T, &T, bool),
    ) {
        let purge_all = self.purge_all;
        let proxies = &self.proxies;
        let stree = &self.stree;
        let tree = &self.tree;
        self.pairs.retain(|pair, up_to_date| {
            let mut retain = true;

            if purge_all || !*up_to_date {
                *up_to_date = true;

                let proxy1 = proxies
                    .get(pair.0.uid())
                    .expect("DBVT broad phase: internal error.");
                let proxy2 = proxies
                    .get(pair.1.uid())
                    .expect("DBVT broad phase: internal error.");

                if purge_all || proxy1.updated || proxy2.updated {
                    if allow_proximity(&proxy1.data, &proxy2.data) {
                        let l1 = match proxy1.status {
                            ProxyStatus::OnStaticTree(leaf) => &stree[leaf],
                            ProxyStatus::OnDynamicTree(leaf, _) => &tree[leaf],
                            _ => panic!("DBVT broad phase: internal error."),
                        };

                        let l2 = match proxy2.status {
                            ProxyStatus::OnStaticTree(leaf) => &stree[leaf],
                            ProxyStatus::OnDynamicTree(leaf, _) => &tree[leaf],
                            _ => panic!("DBVT broad phase: internal error."),
                        };

                        if !l1.bounding_volume.intersects(&l2.bounding_volume) {
                            handler(&proxy1.data, &proxy2.data, false);
                            retain = false;
                        }
                    }
                }
            }

            *up_to_date = false;
            retain
        });
    }

    fn update_activation_states(&mut self) {
        /*
         * Update activation states.
         * FIXME: could we avoid having to iterate through _all_ the proxies at each update?
         */
        for (_, proxy) in self.proxies.iter_mut() {
            if let ProxyStatus::OnDynamicTree(leaf, energy) = proxy.status {
                if energy == 1 {
                    let old_leaf = self.tree.remove(leaf);
                    let new_leaf = self.stree.insert(old_leaf);
                    proxy.status = ProxyStatus::OnStaticTree(new_leaf);
                } else {
                    proxy.status = ProxyStatus::OnDynamicTree(leaf, energy - 1)
                }
            }
        }
    }
}

impl<N, BV, T> BroadPhase<N, BV, T> for DBVTBroadPhase<N, BV, T>
where
    N: Real,
    BV: BoundingVolume<N> + RayCast<N> + PointQuery<N> + Any + Send + Sync + Clone,
    T: Any + Send + Sync,
{
    fn update(
        &mut self,
        allow_proximity: &mut FnMut(&T, &T) -> bool,
        handler: &mut FnMut(&T, &T, bool),
    ) {
        /*
         * Remove from the trees all nodes that have been deleted or modified.
         */
        for (handle, bv) in self.proxies_to_update.drain(..) {
            if let Some(proxy) = self.proxies.get_mut(handle.uid()) {
                let mut set_status = true;
                match proxy.status {
                    ProxyStatus::OnStaticTree(leaf) => {
                        let mut leaf = self.stree.remove(leaf);
                        leaf.bounding_volume = bv;
                        self.leaves_to_update.push(leaf);
                    }
                    ProxyStatus::OnDynamicTree(leaf, _) => {
                        let mut leaf = self.tree.remove(leaf);
                        leaf.bounding_volume = bv;
                        self.leaves_to_update.push(leaf);
                    }
                    ProxyStatus::Detached(None) => {
                        let leaf = DBVTLeaf::new(bv, handle);
                        self.leaves_to_update.push(leaf);
                    }
                    ProxyStatus::Detached(Some(id)) => {
                        let leaf = DBVTLeaf::new(bv, handle);
                        self.leaves_to_update[id] = leaf;
                        set_status = false;
                    }
                    ProxyStatus::Deleted => {
                        panic!("DBVT broad phase internal error: the proxy was deleted.")
                    }
                }

                proxy.updated = true;

                if set_status {
                    proxy.status = ProxyStatus::Detached(Some(self.leaves_to_update.len() - 1));
                }
            }
        }

        /*
         * Re-insert outdated nodes one by one and collect interferences at the same time.
         */
        let some_leaves_updated = self.leaves_to_update.len() != 0;
        for leaf in self.leaves_to_update.drain(..) {
            {
                let proxy1 = &self.proxies[leaf.data.uid()];
                {
                    let mut visitor = BoundingVolumeInterferencesCollector::new(
                        &leaf.bounding_volume,
                        &mut self.collector,
                    );

                    self.tree.visit(&mut visitor);
                    self.stree.visit(&mut visitor);
                }

                // Event generation.
                for proxy_key2 in self.collector.iter() {
                    let proxy2 = &self.proxies[proxy_key2.uid()];

                    if allow_proximity(&proxy1.data, &proxy2.data) {
                        match self.pairs.entry(SortedPair::new(leaf.data, *proxy_key2)) {
                            Entry::Occupied(entry) => *entry.into_mut() = true,
                            Entry::Vacant(entry) => {
                                handler(&proxy1.data, &proxy2.data, true);
                                let _ = entry.insert(true);
                            }
                        }
                    }
                }

                self.collector.clear();
            }

            let proxy1 = &mut self.proxies[leaf.data.uid()];
            assert!(proxy1.is_detached());
            let leaf = self.tree.insert(leaf);
            proxy1.status = ProxyStatus::OnDynamicTree(leaf, DEACTIVATION_THRESHOLD);
        }

        if some_leaves_updated {
            self.purge_some_contact_pairs(allow_proximity, handler);
        }
        self.update_activation_states();
    }

    fn create_proxy(&mut self, bv: BV, data: T) -> ProxyHandle {
        let proxy = DBVTBroadPhaseProxy::new(data);
        let handle = ProxyHandle(self.proxies.insert(proxy));
        self.proxies_to_update.push((handle, bv));
        handle
    }

    fn remove(&mut self, handles: &[ProxyHandle], handler: &mut FnMut(&T, &T)) {
        for handle in handles {
            if let Some(proxy) = self.proxies.get_mut(handle.uid()) {
                match proxy.status {
                    ProxyStatus::OnStaticTree(leaf) => {
                        let _ = self.stree.remove(leaf);
                    }
                    ProxyStatus::OnDynamicTree(leaf, _) => {
                        let _ = self.tree.remove(leaf);
                    }
                    _ => {}
                }

                proxy.status = ProxyStatus::Deleted;
            } else {
                panic!("Attempting to remove an object that does not exist.");
            }
        }

        {
            let proxies = &self.proxies;
            self.pairs.retain(|pair, _| {
                let proxy1 = proxies
                    .get(pair.0.uid())
                    .expect("DBVT broad phase: internal error.");
                let proxy2 = proxies
                    .get(pair.1.uid())
                    .expect("DBVT broad phase: internal error.");

                if proxy1.status == ProxyStatus::Deleted || proxy2.status == ProxyStatus::Deleted {
                    handler(&proxy1.data, &proxy2.data);
                    false
                } else {
                    true
                }
            });
        }

        for handle in handles {
            let _ = self.proxies.remove(handle.uid());
        }
    }

    fn deferred_set_bounding_volume(&mut self, handle: ProxyHandle, bounding_volume: BV) {
        if let Some(proxy) = self.proxies.get(handle.uid()) {
            let needs_update = match proxy.status {
                ProxyStatus::OnStaticTree(leaf) => {
                    !self.stree[leaf].bounding_volume.contains(&bounding_volume)
                }
                ProxyStatus::OnDynamicTree(leaf, _) => {
                    !self.tree[leaf].bounding_volume.contains(&bounding_volume)
                }
                ProxyStatus::Detached(_) => true,
                ProxyStatus::Deleted => {
                    panic!("DBVT broad phase: internal error, proxy not found.")
                }
            };

            if needs_update {
                let new_bv = bounding_volume.loosened(self.margin);
                self.proxies_to_update.push((handle, new_bv));
            }
        } else {
            panic!("Attempting to set the bounding volume of an object that does not exist.");
        }
    }

    fn deferred_recompute_all_proximities_with(&mut self, handle: ProxyHandle) {
        if let Some(proxy) = self.proxies.get(handle.uid()) {
            let bv = match proxy.status {
                ProxyStatus::OnStaticTree(leaf) => self.stree[leaf].bounding_volume.clone(),
                ProxyStatus::OnDynamicTree(leaf, _) => self.tree[leaf].bounding_volume.clone(),
                ProxyStatus::Detached(_) => return,
                ProxyStatus::Deleted => {
                    panic!("DBVT broad phase: internal error, proxy not found.")
                }
            };

            self.proxies_to_update.push((handle, bv));
        }
    }

    fn deferred_recompute_all_proximities(&mut self) {
        let mut user_updates = mem::replace(&mut self.proxies_to_update, Vec::new());

        for (handle, proxy) in self.proxies.iter() {
            let bv;
            match proxy.status {
                ProxyStatus::OnStaticTree(leaf) => {
                    bv = self.stree[leaf].bounding_volume.clone();
                }
                ProxyStatus::OnDynamicTree(leaf, _) => {
                    bv = self.tree[leaf].bounding_volume.clone();
                }
                ProxyStatus::Detached(_) => continue,
                ProxyStatus::Deleted => {
                    panic!("DBVT broad phase: internal error, proxy not found.")
                }
            }

            self.proxies_to_update.push((ProxyHandle(handle), bv));
        }

        self.proxies_to_update.append(&mut user_updates);
        self.purge_all = true;
    }

    fn interferences_with_bounding_volume<'a>(&'a self, bv: &BV, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = BoundingVolumeInterferencesCollector::new(bv, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l.uid()].data)
        }
    }

    fn interferences_with_ray<'a>(&'a self, ray: &Ray<N>, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = RayInterferencesCollector::new(ray, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l.uid()].data)
        }
    }

    fn interferences_with_point<'a>(&'a self, point: &Point<N>, out: &mut Vec<&'a T>) {
        let mut collector = Vec::new();

        {
            let mut visitor = PointInterferencesCollector::new(point, &mut collector);

            self.tree.visit(&mut visitor);
            self.stree.visit(&mut visitor);
        }

        for l in collector.into_iter() {
            out.push(&self.proxies[l.uid()].data)
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp;

use CliResult;
use config::{Config, Delimiter};
use select::SelectColumns;
use util;
use std::str::from_utf8;

use self::Number::{Float, Int};

static USAGE: &'static str = "
Sorts CSV data lexicographically.

Note that this requires reading all of the CSV data into memory.

Usage:
    xsv sort [options] [<input>]

sort options:
    -s, --select <arg>     Select a subset of columns to sort.
                           See 'xsv select --help' for the format details.
    -N, --numeric          Compare according to string numerical value
    -R, --reverse          Reverse order

Common options:
    -h, --help             Display this message
    -o, --output <file>    Write output to <file> instead of stdout.
    -n, --no-headers       When set, the first row will not be interpreted
                           as headers. Namely, it will be sorted with the rest
                           of the rows. Otherwise, the first row will always
                           appear as the header row in the output.
    -d, --delimiter <arg>  The field delimiter for reading CSV data.
                           Must be a single character. (default: ,)
";

#[derive(Deserialize)]
struct Args {
    arg_input: Option<String>,
    flag_select: SelectColumns,
    flag_numeric: bool,
    flag_reverse: bool,
    flag_output: Option<String>,
    flag_no_headers: bool,
    flag_delimiter: Option<Delimiter>,
}

pub fn run(argv: &[&str]) -> CliResult<()> {
    let args: Args = util::get_args(USAGE, argv)?;
    let numeric = args.flag_numeric;
    let reverse = args.flag_reverse;
    let rconfig = Config::new(&args.arg_input)
        .delimiter(args.flag_delimiter)
        .no_headers(args.flag_no_headers)
        .select(args.flag_select);

    let mut rdr = rconfig.reader()?;
    let mut wtr = Config::new(&args.flag_output).writer()?;

    let headers = rdr.byte_headers()?.clone();
    let sel = rconfig.selection(&headers)?;

    let mut all = rdr.byte_records().collect::<Result<Vec<_>, _>>()?;
    match (numeric, reverse) {
        (false, false) =>
            all.sort_by(|r1, r2| {
                let a = sel.select(r1);
                let b = sel.select(r2);
                iter_cmp(a, b)
            }),
        (true, false) =>
            all.sort_by(|r1, r2| {
                let a = sel.select(r1);
                let b = sel.select(r2);
                iter_cmp_num(a, b)
            }),
        (false, true) =>
            all.sort_by(|r1, r2| {
                let a = sel.select(r1);
                let b = sel.select(r2);
                iter_cmp(b, a)
            }),
        (true, true) =>
            all.sort_by(|r1, r2| {
                let a = sel.select(r1);
                let b = sel.select(r2);
                iter_cmp_num(b, a)
            }),
    }

    rconfig.write_headers(&mut rdr, &mut wtr)?;
    for r in all.into_iter() {
        wtr.write_byte_record(&r)?;
    }
    Ok(wtr.flush()?)
}

/// Order `a` and `b` lexicographically using `Ord`
pub fn iter_cmp<A, L, R>(mut a: L, mut b: R) -> cmp::Ordering
        where A: Ord, L: Iterator<Item=A>, R: Iterator<Item=A> {
    loop {
        match (a.next(), b.next()) {
            (None, None) => return cmp::Ordering::Equal,
            (None, _   ) => return cmp::Ordering::Less,
            (_   , None) => return cmp::Ordering::Greater,
            (Some(x), Some(y)) => match x.cmp(&y) {
                cmp::Ordering::Equal => (),
                non_eq => return non_eq,
            },
        }
    }
}

/// Try parsing `a` and `b` as numbers when ordering
pub fn iter_cmp_num<'a, L, R>(mut a: L, mut b: R) -> cmp::Ordering
        where L: Iterator<Item=&'a [u8]>, R: Iterator<Item=&'a [u8]> {
    loop {
        match (next_num(&mut a), next_num(&mut b)) {
            (None, None) => return cmp::Ordering::Equal,
            (None, _   ) => return cmp::Ordering::Less,
            (_   , None) => return cmp::Ordering::Greater,
            (Some(x), Some(y)) => match compare_num(x, y) {
                cmp::Ordering::Equal => (),
                non_eq => return non_eq,
            },
        }
    }
}

#[derive(Clone, Copy, PartialEq)]
enum Number {
    Int(i64),
    Float(f64),
}

fn compare_num(n1: Number, n2: Number) -> cmp::Ordering{
    match (n1, n2) {
        (Int(i1), Int(i2)) => i1.cmp(&i2),
        (Int(i1), Float(f2)) => compare_float(i1 as f64, f2),
        (Float(f1), Int(i2)) => compare_float(f1, i2 as f64),
        (Float(f1), Float(f2)) => compare_float(f1, f2),
    }
}

fn compare_float(f1: f64, f2: f64) -> cmp::Ordering {
    f1.partial_cmp(&f2).unwrap_or(cmp::Ordering::Equal)
}

fn next_num<'a, X>(xs: &mut X) -> Option<Number>
        where X: Iterator<Item=&'a [u8]> {
    xs.next()
        .and_then(|bytes| from_utf8(bytes).ok())
        .and_then(|s| {
            if let Ok(i) = s.parse::<i64>() { Some(Number::Int(i)) }
            else if let Ok(f) = s.parse::<f64>() { Some(Number::Float(f)) }
            else { None }
        })
}
<commit_msg>cmd/sort: open writer after consuming reader<commit_after>use std::cmp;

use CliResult;
use config::{Config, Delimiter};
use select::SelectColumns;
use util;
use std::str::from_utf8;

use self::Number::{Float, Int};

static USAGE: &'static str = "
Sorts CSV data lexicographically.

Note that this requires reading all of the CSV data into memory.

Usage:
    xsv sort [options] [<input>]

sort options:
    -s, --select <arg>     Select a subset of columns to sort.
                           See 'xsv select --help' for the format details.
    -N, --numeric          Compare according to string numerical value
    -R, --reverse          Reverse order

Common options:
    -h, --help             Display this message
    -o, --output <file>    Write output to <file> instead of stdout.
    -n, --no-headers       When set, the first row will not be interpreted
                           as headers. Namely, it will be sorted with the rest
                           of the rows. Otherwise, the first row will always
                           appear as the header row in the output.
    -d, --delimiter <arg>  The field delimiter for reading CSV data.
                           Must be a single character. (default: ,)
";

#[derive(Deserialize)]
struct Args {
    arg_input: Option<String>,
    flag_select: SelectColumns,
    flag_numeric: bool,
    flag_reverse: bool,
    flag_output: Option<String>,
    flag_no_headers: bool,
    flag_delimiter: Option<Delimiter>,
}

pub fn run(argv: &[&str]) -> CliResult<()> {
    let args: Args = util::get_args(USAGE, argv)?;
    let numeric = args.flag_numeric;
    let reverse = args.flag_reverse;
    let rconfig = Config::new(&args.arg_input)
        .delimiter(args.flag_delimiter)
        .no_headers(args.flag_no_headers)
        .select(args.flag_select);

    let mut rdr = rconfig.reader()?;

    let headers = rdr.byte_headers()?.clone();
    let sel = rconfig.selection(&headers)?;

    let mut all = rdr.byte_records().collect::<Result<Vec<_>, _>>()?;
    match (numeric, reverse) {
        (false, false) =>
            all.sort_by(|r1, r2| {
                let a = sel.select(r1);
                let b = sel.select(r2);
                iter_cmp(a, b)
            }),
        (true, false) =>
            all.sort_by(|r1, r2| {
                let a = sel.select(r1);
                let b = sel.select(r2);
                iter_cmp_num(a, b)
            }),
        (false, true) =>
            all.sort_by(|r1, r2| {
                let a = sel.select(r1);
                let b = sel.select(r2);
                iter_cmp(b, a)
            }),
        (true, true) =>
            all.sort_by(|r1, r2| {
                let a = sel.select(r1);
                let b = sel.select(r2);
                iter_cmp_num(b, a)
            }),
    }

    let mut wtr = Config::new(&args.flag_output).writer()?;
    rconfig.write_headers(&mut rdr, &mut wtr)?;
    for r in all.into_iter() {
        wtr.write_byte_record(&r)?;
    }
    Ok(wtr.flush()?)
}

/// Order `a` and `b` lexicographically using `Ord`
pub fn iter_cmp<A, L, R>(mut a: L, mut b: R) -> cmp::Ordering
        where A: Ord, L: Iterator<Item=A>, R: Iterator<Item=A> {
    loop {
        match (a.next(), b.next()) {
            (None, None) => return cmp::Ordering::Equal,
            (None, _   ) => return cmp::Ordering::Less,
            (_   , None) => return cmp::Ordering::Greater,
            (Some(x), Some(y)) => match x.cmp(&y) {
                cmp::Ordering::Equal => (),
                non_eq => return non_eq,
            },
        }
    }
}

/// Try parsing `a` and `b` as numbers when ordering
pub fn iter_cmp_num<'a, L, R>(mut a: L, mut b: R) -> cmp::Ordering
        where L: Iterator<Item=&'a [u8]>, R: Iterator<Item=&'a [u8]> {
    loop {
        match (next_num(&mut a), next_num(&mut b)) {
            (None, None) => return cmp::Ordering::Equal,
            (None, _   ) => return cmp::Ordering::Less,
            (_   , None) => return cmp::Ordering::Greater,
            (Some(x), Some(y)) => match compare_num(x, y) {
                cmp::Ordering::Equal => (),
                non_eq => return non_eq,
            },
        }
    }
}

#[derive(Clone, Copy, PartialEq)]
enum Number {
    Int(i64),
    Float(f64),
}

fn compare_num(n1: Number, n2: Number) -> cmp::Ordering{
    match (n1, n2) {
        (Int(i1), Int(i2)) => i1.cmp(&i2),
        (Int(i1), Float(f2)) => compare_float(i1 as f64, f2),
        (Float(f1), Int(i2)) => compare_float(f1, i2 as f64),
        (Float(f1), Float(f2)) => compare_float(f1, f2),
    }
}

fn compare_float(f1: f64, f2: f64) -> cmp::Ordering {
    f1.partial_cmp(&f2).unwrap_or(cmp::Ordering::Equal)
}

fn next_num<'a, X>(xs: &mut X) -> Option<Number>
        where X: Iterator<Item=&'a [u8]> {
    xs.next()
        .and_then(|bytes| from_utf8(bytes).ok())
        .and_then(|s| {
            if let Ok(i) = s.parse::<i64>() { Some(Number::Int(i)) }
            else if let Ok(f) = s.parse::<f64>() { Some(Number::Float(f)) }
            else { None }
        })
}
<|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.

/*!
 * Computes the restrictions that result from a borrow.
 */

use middle::borrowck::*;
use middle::expr_use_visitor as euv;
use middle::mem_categorization as mc;
use middle::ty;
use syntax::codemap::Span;
use util::ppaux::Repr;

use std::rc::Rc;

pub enum RestrictionResult {
    Safe,
    SafeIf(Rc<LoanPath>, Vec<Rc<LoanPath>>)
}

pub fn compute_restrictions(bccx: &BorrowckCtxt,
                            span: Span,
                            cause: euv::LoanCause,
                            cmt: mc::cmt,
                            loan_region: ty::Region) -> RestrictionResult {
    let ctxt = RestrictionsContext {
        bccx: bccx,
        span: span,
        cause: cause,
        loan_region: loan_region,
    };

    ctxt.restrict(cmt)
}

///////////////////////////////////////////////////////////////////////////
// Private

struct RestrictionsContext<'a> {
    bccx: &'a BorrowckCtxt<'a>,
    span: Span,
    loan_region: ty::Region,
    cause: euv::LoanCause,
}

impl<'a> RestrictionsContext<'a> {
    fn restrict(&self,
                cmt: mc::cmt) -> RestrictionResult {
        debug!("restrict(cmt={})", cmt.repr(self.bccx.tcx));

        match cmt.cat.clone() {
            mc::cat_rvalue(..) => {
                // Effectively, rvalues are stored into a
                // non-aliasable temporary on the stack. Since they
                // are inherently non-aliasable, they can only be
                // accessed later through the borrow itself and hence
                // must inherently comply with its terms.
                Safe
            }

            mc::cat_local(local_id) |
            mc::cat_arg(local_id) => {
                // R-Variable, locally declared
                let lp = Rc::new(LpVar(local_id));
                SafeIf(lp.clone(), vec!(lp))
            }

            mc::cat_upvar(upvar_id, _) => {
                // R-Variable, captured into closure
                let lp = Rc::new(LpUpvar(upvar_id));
                SafeIf(lp.clone(), vec!(lp))
            }

            mc::cat_copied_upvar(..) => {
                // FIXME(#2152) allow mutation of upvars
                Safe
            }

            mc::cat_downcast(cmt_base) => {
                // When we borrow the interior of an enum, we have to
                // ensure the enum itself is not mutated, because that
                // could cause the type of the memory to change.
                self.restrict(cmt_base)
            }

            mc::cat_interior(cmt_base, i) => {
                // R-Field
                //
                // Overwriting the base would not change the type of
                // the memory, so no additional restrictions are
                // needed.
                let result = self.restrict(cmt_base);
                self.extend(result, cmt.mutbl, LpInterior(i))
            }

            mc::cat_deref(cmt_base, _, pk @ mc::OwnedPtr) |
            mc::cat_deref(cmt_base, _, pk @ mc::GcPtr) => {
                // R-Deref-Send-Pointer
                //
                // When we borrow the interior of an owned pointer, we
                // cannot permit the base to be mutated, because that
                // would cause the unique pointer to be freed.
                //
                // For a managed pointer, the rules are basically the
                // same, because this could be the last ref.
                // Eventually we should make these non-special and
                // just rely on Deref<T> implementation.
                let result = self.restrict(cmt_base);
                self.extend(result, cmt.mutbl, LpDeref(pk))
            }

            mc::cat_static_item(..) => {
                Safe
            }

            mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::ImmBorrow, lt)) |
            mc::cat_deref(cmt_base, _, mc::Implicit(ty::ImmBorrow, lt)) => {
                // R-Deref-Imm-Borrowed
                if !self.bccx.is_subregion_of(self.loan_region, lt) {
                    self.bccx.report(
                        BckError {
                            span: self.span,
                            cause: self.cause,
                            cmt: cmt_base,
                            code: err_borrowed_pointer_too_short(
                                self.loan_region, lt)});
                    return Safe;
                }
                Safe
            }

            mc::cat_deref(cmt_base, _, pk) => {
                match pk {
                    mc::BorrowedPtr(ty::MutBorrow, lt) |
                    mc::BorrowedPtr(ty::UniqueImmBorrow, lt) |
                    mc::Implicit(ty::MutBorrow, lt) |
                    mc::Implicit(ty::UniqueImmBorrow, lt) => {
                        // R-Deref-Mut-Borrowed
                        if !self.bccx.is_subregion_of(self.loan_region, lt) {
                            self.bccx.report(
                                BckError {
                                    span: self.span,
                                    cause: self.cause,
                                    cmt: cmt_base,
                                    code: err_borrowed_pointer_too_short(
                                        self.loan_region, lt)});
                            return Safe;
                        }

                        let result = self.restrict(cmt_base);
                        self.extend(result, cmt.mutbl, LpDeref(pk))
                    }
                    mc::UnsafePtr(..) => {
                        // We are very trusting when working with unsafe
                        // pointers.
                        Safe
                    }
                    _ => {
                        self.bccx.tcx.sess.span_bug(self.span,
                                                    "unhandled memcat in \
                                                     cat_deref")
                    }
                }
            }

            mc::cat_discr(cmt_base, _) => {
                self.restrict(cmt_base)
            }
        }
    }

    fn extend(&self,
              result: RestrictionResult,
              mc: mc::MutabilityCategory,
              elem: LoanPathElem) -> RestrictionResult {
        match result {
            Safe => Safe,
            SafeIf(base_lp, mut base_vec) => {
                let lp = Rc::new(LpExtend(base_lp, mc, elem));
                base_vec.push(lp.clone());
                SafeIf(lp, base_vec)
            }
        }
    }
}
<commit_msg>librustc: Properly tag upvars in proc's to stop misleading unused_mut warnings.<commit_after>// 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.

/*!
 * Computes the restrictions that result from a borrow.
 */

use middle::borrowck::*;
use middle::expr_use_visitor as euv;
use middle::mem_categorization as mc;
use middle::ty;
use syntax::codemap::Span;
use util::ppaux::Repr;

use std::rc::Rc;

pub enum RestrictionResult {
    Safe,
    SafeIf(Rc<LoanPath>, Vec<Rc<LoanPath>>)
}

pub fn compute_restrictions(bccx: &BorrowckCtxt,
                            span: Span,
                            cause: euv::LoanCause,
                            cmt: mc::cmt,
                            loan_region: ty::Region) -> RestrictionResult {
    let ctxt = RestrictionsContext {
        bccx: bccx,
        span: span,
        cause: cause,
        loan_region: loan_region,
    };

    ctxt.restrict(cmt)
}

///////////////////////////////////////////////////////////////////////////
// Private

struct RestrictionsContext<'a> {
    bccx: &'a BorrowckCtxt<'a>,
    span: Span,
    loan_region: ty::Region,
    cause: euv::LoanCause,
}

impl<'a> RestrictionsContext<'a> {
    fn restrict(&self,
                cmt: mc::cmt) -> RestrictionResult {
        debug!("restrict(cmt={})", cmt.repr(self.bccx.tcx));

        match cmt.cat.clone() {
            mc::cat_rvalue(..) => {
                // Effectively, rvalues are stored into a
                // non-aliasable temporary on the stack. Since they
                // are inherently non-aliasable, they can only be
                // accessed later through the borrow itself and hence
                // must inherently comply with its terms.
                Safe
            }

            mc::cat_local(local_id) |
            mc::cat_arg(local_id) => {
                // R-Variable, locally declared
                let lp = Rc::new(LpVar(local_id));
                SafeIf(lp.clone(), vec![lp])
            }

            mc::cat_upvar(upvar_id, _) => {
                // R-Variable, captured into closure
                let lp = Rc::new(LpUpvar(upvar_id));
                SafeIf(lp.clone(), vec![lp])
            }

            mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id, .. }) => {
                // R-Variable, copied/moved into closure
                let lp = Rc::new(LpVar(upvar_id));
                SafeIf(lp.clone(), vec![lp])
            }

            mc::cat_downcast(cmt_base) => {
                // When we borrow the interior of an enum, we have to
                // ensure the enum itself is not mutated, because that
                // could cause the type of the memory to change.
                self.restrict(cmt_base)
            }

            mc::cat_interior(cmt_base, i) => {
                // R-Field
                //
                // Overwriting the base would not change the type of
                // the memory, so no additional restrictions are
                // needed.
                let result = self.restrict(cmt_base);
                self.extend(result, cmt.mutbl, LpInterior(i))
            }

            mc::cat_deref(cmt_base, _, pk @ mc::OwnedPtr) |
            mc::cat_deref(cmt_base, _, pk @ mc::GcPtr) => {
                // R-Deref-Send-Pointer
                //
                // When we borrow the interior of an owned pointer, we
                // cannot permit the base to be mutated, because that
                // would cause the unique pointer to be freed.
                //
                // For a managed pointer, the rules are basically the
                // same, because this could be the last ref.
                // Eventually we should make these non-special and
                // just rely on Deref<T> implementation.
                let result = self.restrict(cmt_base);
                self.extend(result, cmt.mutbl, LpDeref(pk))
            }

            mc::cat_static_item(..) => {
                Safe
            }

            mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::ImmBorrow, lt)) |
            mc::cat_deref(cmt_base, _, mc::Implicit(ty::ImmBorrow, lt)) => {
                // R-Deref-Imm-Borrowed
                if !self.bccx.is_subregion_of(self.loan_region, lt) {
                    self.bccx.report(
                        BckError {
                            span: self.span,
                            cause: self.cause,
                            cmt: cmt_base,
                            code: err_borrowed_pointer_too_short(
                                self.loan_region, lt)});
                    return Safe;
                }
                Safe
            }

            mc::cat_deref(cmt_base, _, pk) => {
                match pk {
                    mc::BorrowedPtr(ty::MutBorrow, lt) |
                    mc::BorrowedPtr(ty::UniqueImmBorrow, lt) |
                    mc::Implicit(ty::MutBorrow, lt) |
                    mc::Implicit(ty::UniqueImmBorrow, lt) => {
                        // R-Deref-Mut-Borrowed
                        if !self.bccx.is_subregion_of(self.loan_region, lt) {
                            self.bccx.report(
                                BckError {
                                    span: self.span,
                                    cause: self.cause,
                                    cmt: cmt_base,
                                    code: err_borrowed_pointer_too_short(
                                        self.loan_region, lt)});
                            return Safe;
                        }

                        let result = self.restrict(cmt_base);
                        self.extend(result, cmt.mutbl, LpDeref(pk))
                    }
                    mc::UnsafePtr(..) => {
                        // We are very trusting when working with unsafe
                        // pointers.
                        Safe
                    }
                    _ => {
                        self.bccx.tcx.sess.span_bug(self.span,
                                                    "unhandled memcat in \
                                                     cat_deref")
                    }
                }
            }

            mc::cat_discr(cmt_base, _) => {
                self.restrict(cmt_base)
            }
        }
    }

    fn extend(&self,
              result: RestrictionResult,
              mc: mc::MutabilityCategory,
              elem: LoanPathElem) -> RestrictionResult {
        match result {
            Safe => Safe,
            SafeIf(base_lp, mut base_vec) => {
                let lp = Rc::new(LpExtend(base_lp, mc, elem));
                base_vec.push(lp.clone());
                SafeIf(lp, base_vec)
            }
        }
    }
}
<|endoftext|>