<commit_before>use super::{
    heap::{Heap, ObjectData, ObjectPointer},
    value::Value,
};
use crate::compiler::{
    hir,
    lir::{Chunk, ChunkIndex, Instruction},
};
use itertools::Itertools;
use log::{debug, trace};
use std::collections::HashMap;

/// A VM can execute some byte code.
pub struct Vm {
    pub(super) chunks: Vec<Chunk>,
    pub(super) status: Status,
    next_instruction: ByteCodePointer,
    pub(super) heap: Heap,
    pub(super) data_stack: Vec<ObjectPointer>,
    pub(super) function_stack: Vec<ByteCodePointer>,
    pub(super) debug_stack: Vec<DebugEntry>,
}

#[derive(Clone)]
pub enum Status {
    Running,
    Done(Value),
    Panicked(Value),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ByteCodePointer {
    chunk: ChunkIndex,
    instruction: usize,
}

#[derive(Debug, Clone)]
pub struct DebugEntry {
    pub id: hir::Id,
    pub data_stack: Vec<Value>,
}

impl Vm {
    pub fn new(chunks: Vec<Chunk>) -> Self {
        Self {
            chunks: chunks.clone(),
            status: Status::Running,
            next_instruction: ByteCodePointer {
                chunk: chunks.len() - 1,
                instruction: 0,
            },
            heap: Heap::new(),
            data_stack: vec![],
            function_stack: vec![],
            debug_stack: vec![],
        }
    }

    pub fn status(&self) -> Status {
        self.status.clone()
    }

    fn get_from_data_stack(&self, offset: usize) -> ObjectPointer {
        self.data_stack[self.data_stack.len() - 1 - offset as usize].clone()
    }

    pub fn run(&mut self, mut num_instructions: u16) {
        assert!(
            matches!(self.status, Status::Running),
            "Called Vm::run on a vm that is not ready to run."
        );
        while matches!(self.status, Status::Running) && num_instructions > 0 {
            num_instructions -= 1;
            let instruction = self.chunks[self.next_instruction.chunk].instructions
                [self.next_instruction.instruction]
                .clone();
            trace!("Running instruction: {:?}", &instruction);
            self.next_instruction.instruction += 1;
            self.run_instruction(instruction);

            trace!(
                "Stack: {}",
                self.data_stack
                    .iter()
                    .map(|address| format!("{}", self.heap.export_without_dropping(*address)))
                    .join(", ")
            );
            trace!("Heap: {:?}", self.heap);

            if self.next_instruction.instruction
                >= self.chunks[self.next_instruction.chunk].instructions.len()
            {
                self.status = Status::Done(Value::nothing());
            }
        }
    }
    pub fn run_instruction(&mut self, instruction: Instruction) {
        match instruction {
            Instruction::CreateInt(int) => {
                let address = self.heap.create(ObjectData::Int(int));
                self.data_stack.push(address);
            }
            Instruction::CreateText(text) => {
                let address = self.heap.create(ObjectData::Text(text));
                self.data_stack.push(address);
            }
            Instruction::CreateSymbol(symbol) => {
                let address = self.heap.create(ObjectData::Symbol(symbol));
                self.data_stack.push(address);
            }
            Instruction::CreateStruct { num_entries } => {
                let mut key_value_addresses = vec![];
                for _ in 0..(2 * num_entries) {
                    key_value_addresses.push(self.data_stack.pop().unwrap());
                }
                let mut entries = HashMap::new();
                for mut key_and_value in &key_value_addresses.into_iter().rev().chunks(2) {
                    let key = key_and_value.next().unwrap();
                    let value = key_and_value.next().unwrap();
                    assert_eq!(key_and_value.next(), None);
                    entries.insert(key, value);
                }
                let address = self.heap.create(ObjectData::Struct(entries));
                self.data_stack.push(address);
            }
            Instruction::CreateClosure(chunk) => {
                let captured = self.data_stack.clone();
                for address in &captured {
                    self.heap.dup(*address);
                }
                let address = self.heap.create(ObjectData::Closure {
                    captured,
                    body: chunk,
                });
                self.data_stack.push(address);
            }
            Instruction::PopMultipleBelowTop(n) => {
                let top = self.data_stack.pop().unwrap();
                for _ in 0..n {
                    let address = self.data_stack.pop().unwrap();
                    self.heap.drop(address);
                }
                self.data_stack.push(top);
            }
            Instruction::PushFromStack(offset) => {
                let address = self.get_from_data_stack(offset);
                self.heap.dup(address);
                self.data_stack.push(address);
            }
            Instruction::Call => {
                let closure_address = self.data_stack.pop().unwrap();
                let (captured, body) = match &self.heap.get(closure_address).data {
                    ObjectData::Closure { captured, body } => (captured.clone(), *body),
                    _ => panic!("Can't call non-closure."),
                };
                let num_args = self.chunks[body].num_args;
                let mut args = vec![];
                for _ in 0..num_args {
                    args.push(self.data_stack.pop().unwrap());
                }
                self.function_stack.push(self.next_instruction);
                self.data_stack.append(&mut captured.clone());
                for captured in captured {
                    self.heap.dup(captured);
                }
                self.data_stack.append(&mut args);
                self.heap.drop(closure_address);
                self.next_instruction = ByteCodePointer {
                    chunk: body,
                    instruction: 0,
                };
            }
            Instruction::Return => {
                let caller = self.function_stack.pop().unwrap();
                self.next_instruction = caller;
            }
            Instruction::Builtin(builtin_function) => {
                self.run_builtin_function(builtin_function);
            }
            Instruction::DebugValueEvaluated(id) => {
                let address = *self.data_stack.last().unwrap();
                let value = self.heap.export_without_dropping(address);
                debug!("{} = {}", id, value);
            }
            Instruction::DebugClosureEntered(id) => {
                let mut stack = vec![];
                for entry in &self.data_stack {
                    stack.push(self.heap.export_without_dropping(*entry));
                }

                self.debug_stack.push(DebugEntry {
                    id,
                    data_stack: stack,
                });
            }
            Instruction::DebugClosureExited => {
                let entry = self.debug_stack.pop().unwrap();
                trace!("Exited closure {}.", entry.id);
                trace!(
                    "Stack before: {:?}",
                    entry
                        .data_stack
                        .iter()
                        .map(|value| format!("{}", value))
                        .join(", ")
                );
                trace!(
                    "Stack after:  {:?}",
                    self.data_stack
                        .iter()
                        .map(|address| format!("{}", self.heap.export_without_dropping(*address)))
                        .join(", ")
                );
            }
            Instruction::Error(_) => {
                self.panic(
                    "The VM crashed because there was an error in previous compilation stages."
                        .to_string(),
                );
            }
        }
    }

    pub fn panic(&mut self, message: String) -> Value {
        self.status = Status::Panicked(Value::Text(message));
        Value::Symbol("Never".to_string())
    }

    pub fn current_stack_trace(&self) -> Vec<DebugEntry> {
        self.debug_stack.clone()
    }
}
<commit_msg>Fix the order of arguments in calls<commit_after>use super::{
    heap::{Heap, ObjectData, ObjectPointer},
    value::Value,
};
use crate::compiler::{
    hir,
    lir::{Chunk, ChunkIndex, Instruction},
};
use itertools::Itertools;
use log::{debug, trace};
use std::collections::HashMap;

/// A VM can execute some byte code.
pub struct Vm {
    pub(super) chunks: Vec<Chunk>,
    pub(super) status: Status,
    next_instruction: ByteCodePointer,
    pub(super) heap: Heap,
    pub(super) data_stack: Vec<ObjectPointer>,
    pub(super) function_stack: Vec<ByteCodePointer>,
    pub(super) debug_stack: Vec<DebugEntry>,
}

#[derive(Clone)]
pub enum Status {
    Running,
    Done(Value),
    Panicked(Value),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ByteCodePointer {
    chunk: ChunkIndex,
    instruction: usize,
}

#[derive(Debug, Clone)]
pub struct DebugEntry {
    pub id: hir::Id,
    pub data_stack: Vec<Value>,
}

impl Vm {
    pub fn new(chunks: Vec<Chunk>) -> Self {
        Self {
            chunks: chunks.clone(),
            status: Status::Running,
            next_instruction: ByteCodePointer {
                chunk: chunks.len() - 1,
                instruction: 0,
            },
            heap: Heap::new(),
            data_stack: vec![],
            function_stack: vec![],
            debug_stack: vec![],
        }
    }

    pub fn status(&self) -> Status {
        self.status.clone()
    }

    fn get_from_data_stack(&self, offset: usize) -> ObjectPointer {
        self.data_stack[self.data_stack.len() - 1 - offset as usize].clone()
    }

    pub fn run(&mut self, mut num_instructions: u16) {
        assert!(
            matches!(self.status, Status::Running),
            "Called Vm::run on a vm that is not ready to run."
        );
        while matches!(self.status, Status::Running) && num_instructions > 0 {
            num_instructions -= 1;
            let instruction = self.chunks[self.next_instruction.chunk].instructions
                [self.next_instruction.instruction]
                .clone();
            trace!("Running instruction: {:?}", &instruction);
            self.next_instruction.instruction += 1;
            self.run_instruction(instruction);

            trace!(
                "Stack: {}",
                self.data_stack
                    .iter()
                    .map(|address| format!("{}", self.heap.export_without_dropping(*address)))
                    .join(", ")
            );
            trace!("Heap: {:?}", self.heap);

            if self.next_instruction.instruction
                >= self.chunks[self.next_instruction.chunk].instructions.len()
            {
                self.status = Status::Done(Value::nothing());
            }
        }
    }
    pub fn run_instruction(&mut self, instruction: Instruction) {
        match instruction {
            Instruction::CreateInt(int) => {
                let address = self.heap.create(ObjectData::Int(int));
                self.data_stack.push(address);
            }
            Instruction::CreateText(text) => {
                let address = self.heap.create(ObjectData::Text(text));
                self.data_stack.push(address);
            }
            Instruction::CreateSymbol(symbol) => {
                let address = self.heap.create(ObjectData::Symbol(symbol));
                self.data_stack.push(address);
            }
            Instruction::CreateStruct { num_entries } => {
                let mut key_value_addresses = vec![];
                for _ in 0..(2 * num_entries) {
                    key_value_addresses.push(self.data_stack.pop().unwrap());
                }
                let mut entries = HashMap::new();
                for mut key_and_value in &key_value_addresses.into_iter().rev().chunks(2) {
                    let key = key_and_value.next().unwrap();
                    let value = key_and_value.next().unwrap();
                    assert_eq!(key_and_value.next(), None);
                    entries.insert(key, value);
                }
                let address = self.heap.create(ObjectData::Struct(entries));
                self.data_stack.push(address);
            }
            Instruction::CreateClosure(chunk) => {
                let captured = self.data_stack.clone();
                for address in &captured {
                    self.heap.dup(*address);
                }
                let address = self.heap.create(ObjectData::Closure {
                    captured,
                    body: chunk,
                });
                self.data_stack.push(address);
            }
            Instruction::PopMultipleBelowTop(n) => {
                let top = self.data_stack.pop().unwrap();
                for _ in 0..n {
                    let address = self.data_stack.pop().unwrap();
                    self.heap.drop(address);
                }
                self.data_stack.push(top);
            }
            Instruction::PushFromStack(offset) => {
                let address = self.get_from_data_stack(offset);
                self.heap.dup(address);
                self.data_stack.push(address);
            }
            Instruction::Call => {
                let closure_address = self.data_stack.pop().unwrap();
                let (captured, body) = match &self.heap.get(closure_address).data {
                    ObjectData::Closure { captured, body } => (captured.clone(), *body),
                    _ => panic!("Can't call non-closure."),
                };
                let num_args = self.chunks[body].num_args;
                let mut args = vec![];
                for _ in 0..num_args {
                    args.push(self.data_stack.pop().unwrap());
                }
                args.reverse();
                self.function_stack.push(self.next_instruction);
                self.data_stack.append(&mut captured.clone());
                for captured in captured {
                    self.heap.dup(captured);
                }
                self.data_stack.append(&mut args);
                self.heap.drop(closure_address);
                self.next_instruction = ByteCodePointer {
                    chunk: body,
                    instruction: 0,
                };
            }
            Instruction::Return => {
                let caller = self.function_stack.pop().unwrap();
                self.next_instruction = caller;
            }
            Instruction::Builtin(builtin_function) => {
                self.run_builtin_function(builtin_function);
            }
            Instruction::DebugValueEvaluated(id) => {
                let address = *self.data_stack.last().unwrap();
                let value = self.heap.export_without_dropping(address);
                debug!("{} = {}", id, value);
            }
            Instruction::DebugClosureEntered(id) => {
                let mut stack = vec![];
                for entry in &self.data_stack {
                    stack.push(self.heap.export_without_dropping(*entry));
                }

                self.debug_stack.push(DebugEntry {
                    id,
                    data_stack: stack,
                });
            }
            Instruction::DebugClosureExited => {
                let entry = self.debug_stack.pop().unwrap();
                trace!("Exited closure {}.", entry.id);
                trace!(
                    "Stack before: {:?}",
                    entry
                        .data_stack
                        .iter()
                        .map(|value| format!("{}", value))
                        .join(", ")
                );
                trace!(
                    "Stack after:  {:?}",
                    self.data_stack
                        .iter()
                        .map(|address| format!("{}", self.heap.export_without_dropping(*address)))
                        .join(", ")
                );
            }
            Instruction::Error(_) => {
                self.panic(
                    "The VM crashed because there was an error in previous compilation stages."
                        .to_string(),
                );
            }
        }
    }

    pub fn panic(&mut self, message: String) -> Value {
        self.status = Status::Panicked(Value::Text(message));
        Value::Symbol("Never".to_string())
    }

    pub fn current_stack_trace(&self) -> Vec<DebugEntry> {
        self.debug_stack.clone()
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]
#![allow(float_cmp)]

extern crate cql_bindgen;
extern crate num;

use std::mem;
use std::ffi::CString;

use cql_bindgen::*;

#[derive(Clone)]
struct Basic {
    bln: u32,
    flt: f32,
    dbl: f64,
    i32: i32,
    i64: i64,
}

fn print_error(future: &mut CassFuture) {
    unsafe {
        let mut message = mem::zeroed();
        let mut message_length = mem::zeroed();
        cass_future_error_message(future, &mut message, &mut message_length);
        println!("Error: {:?}", raw2utf8(message,message_length));
    }
}

fn create_cluster() -> *mut CassCluster {
    unsafe {
        let cluster = cass_cluster_new();
        let host = CString::new("127.0.0.1").unwrap();
        cass_cluster_set_contact_points(cluster, host.as_ptr());
        cluster
    }
}

fn connect_session(session: &mut CassSession, cluster: &CassCluster) -> CassError {
    unsafe {
        let future = cass_session_connect(session, cluster);
        cass_future_wait(future);
        let err = cass_future_error_code(future);
        cass_future_free(future);
        err
    }
}

fn execute_query(session: &mut CassSession, query: &str) -> Result<(), CassError> {
    unsafe {
        let query = CString::new(query).unwrap();
        let statement = cass_statement_new(query.as_ptr(), 0);
        let future = &mut*cass_session_execute(session, statement);
        cass_future_wait(future);
        cass_future_error_code(future);
        let result = match cass_future_error_code(future) {
            CASS_OK => Ok(()),
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        cass_statement_free(statement);
        result
    }
}

fn insert_into_basic(session: &mut CassSession, key: &str, basic: &Basic) -> Result<(), CassError> {
    unsafe {
        let query = CString::new("INSERT INTO examples.basic (key, bln, flt, dbl, i32, i64) VALUES (:k, :b, :f, :d, :i32, :i64);").unwrap();
        let key = CString::new(key).unwrap();
        let statement = &mut*cass_statement_new(query.as_ptr(), 6);
        let k = CString::new("k").unwrap();
        let b = CString::new("b").unwrap();
        let f = CString::new("f").unwrap();
        let d = CString::new("d").unwrap();
        let i32 = CString::new("i32").unwrap();
        let i64 = CString::new("i64").unwrap();
        cass_statement_bind_string_by_name(statement, k.as_ptr(), key.as_ptr());
        cass_statement_bind_bool_by_name(statement, b.as_ptr(), basic.bln);
        cass_statement_bind_float_by_name(statement, f.as_ptr(), basic.flt);
        cass_statement_bind_double_by_name(statement, d.as_ptr(), basic.dbl);
        cass_statement_bind_int32_by_name(statement, i32.as_ptr(), basic.i32);
        cass_statement_bind_int64_by_name(statement, i64.as_ptr(), basic.i64);

        let future = &mut* cass_session_execute(session, statement);

        cass_future_wait(future);

        let rc = cass_future_error_code(future);
        if rc != CASS_OK {
            print_error(future);
        }

        cass_future_free(future);
        cass_statement_free(statement);

        Ok(())
    }
}

fn select_from_basic(session: &mut CassSession, key: &str) -> Result<Basic, CassError> {
    unsafe {
        let key = CString::new(key).unwrap();
        let query = CString::new("SELECT * FROM examples.basic WHERE key = ?").unwrap();
        let mut output: Basic = mem::zeroed();

        let statement = &mut*cass_statement_new(query.as_ptr(), 1);

        cass_statement_bind_string_by_name(statement, CString::new("key").unwrap().as_ptr(), key.as_ptr());

        let future = &mut*cass_session_execute(session, statement);
        cass_future_wait(future);

        let rc = cass_future_error_code(future);
        if rc != CASS_OK {
            print_error(future);
        } else {
            let result = &*cass_future_get_result(future);
            let iterator = &mut*cass_iterator_from_result(result);

            if cass_iterator_next(iterator) > 0 {
                let row = &*cass_iterator_get_row(iterator);

                cass_value_get_bool(cass_row_get_column_by_name(row, CString::new("BLN").unwrap().as_ptr()),
                                    &mut output.bln);
                cass_value_get_double(cass_row_get_column_by_name(row, CString::new("dbl").unwrap().as_ptr()),
                                      &mut output.dbl);
                cass_value_get_float(cass_row_get_column_by_name(row, CString::new("flt").unwrap().as_ptr()),
                                     &mut output.flt);
                cass_value_get_int32(cass_row_get_column_by_name(row, CString::new("\"i32\"").unwrap().as_ptr()),
                                     &mut output.i32);
                cass_value_get_int64(cass_row_get_column_by_name(row, CString::new("i64").unwrap().as_ptr()),
                                     &mut output.i64);
            }

            cass_result_free(result);
            cass_iterator_free(iterator);
        }

        cass_future_free(future);
        cass_statement_free(statement);

        Ok(output)
    }
}

fn main() {
    unsafe {
        let cluster = &mut*create_cluster();
        let session = &mut*cass_session_new();
        let input = Basic { bln: cass_true, flt: 0.001f32, dbl: 0.0002, i32: 1, i64: 2 };

        if connect_session(session, cluster) != CASS_OK {
            cass_cluster_free(cluster);
            cass_session_free(session);
        }

        execute_query(session,
                "CREATE KEYSPACE IF NOT EXISTS examples WITH replication = { \
                           'class': 'SimpleStrategy', 'replication_factor': '3' };").unwrap();

        execute_query(session,
                "CREATE TABLE IF NOT EXISTS examples.basic (key text, \
                                              bln boolean, \
                                              flt float, dbl double,\
                                              i32 int, i64 bigint, \
                                              PRIMARY KEY (key));").unwrap();

        insert_into_basic(session, "named_parameters", &input).unwrap();
//  let output = select_from_basic(session, "named_parameters").unwrap();
//
//  assert!(input.bln == output.bln);
//  assert!(input.flt == output.flt);
//  assert!(input.dbl == output.dbl);
//  assert!(input.i32 == output.i32);
//  assert!(input.i64 == output.i64);

        let close_future = &mut*cass_session_close(session);
        cass_future_wait(close_future);
        cass_future_free(close_future);

        cass_cluster_free(cluster);
        cass_session_free(session);

    }
}
<commit_msg>minimally broken named_parameters.rs. problem on line 83<commit_after>#![feature(plugin)]
#![plugin(clippy)]
#![allow(float_cmp)]

extern crate cql_bindgen;
extern crate num;

use std::mem;
use std::ffi::CString;

use cql_bindgen::*;

#[derive(Clone)]
struct Basic {
    bln: u32,
    flt: f32,
    dbl: f64,
    i32: i32,
    i64: i64,
}

fn print_error(future: &mut CassFuture) {
    unsafe {
        let mut message = mem::zeroed();
        let mut message_length = mem::zeroed();
        cass_future_error_message(future, &mut message, &mut message_length);
        println!("Error: {:?}", raw2utf8(message,message_length));
    }
}

fn create_cluster() -> *mut CassCluster {
    unsafe {
        let cluster = cass_cluster_new();
        let host = CString::new("127.0.0.1").unwrap();
        cass_cluster_set_contact_points(cluster, host.as_ptr());
        cluster
    }
}

fn connect_session(session: &mut CassSession, cluster: &CassCluster) -> CassError {
    unsafe {
        let future = cass_session_connect(session, cluster);
        cass_future_wait(future);
        let err = cass_future_error_code(future);
        cass_future_free(future);
        err
    }
}

fn execute_query(session: &mut CassSession, query: &str) -> Result<(), CassError> {
    unsafe {
        let query = CString::new(query).unwrap();
        let statement = cass_statement_new(query.as_ptr(), 0);
        let future = &mut*cass_session_execute(session, statement);
        cass_future_wait(future);
        cass_future_error_code(future);
        let result = match cass_future_error_code(future) {
            CASS_OK => Ok(()),
            rc => {
                print_error(future);
                Err(rc)
            }
        };
        cass_future_free(future);
        cass_statement_free(statement);
        result
    }
}

fn insert_into_basic(session: &mut CassSession, key: &str, basic: &Basic) -> Result<(), CassError> {
    unsafe {
        //let query = CString::new("INSERT INTO examples.basic (key, bln, flt, dbl, i32, i64) VALUES (:k, :b, :f, :d, :i32, :i64);").unwrap();
        let query = CString::new("INSERT INTO examples.basic (key) VALUES (:k);").unwrap();
        let key = CString::new(key).unwrap();
        let statement = &mut*cass_statement_new(query.as_ptr(), 1);
        let k = CString::new("k").unwrap();
        let b = CString::new("b").unwrap();
        let f = CString::new("f").unwrap();
        let d = CString::new("d").unwrap();
        let i32 = CString::new("i32").unwrap();
        let i64 = CString::new("i64").unwrap();
//        cass_statement_bind_string(statement, 0, key.as_ptr());
        cass_statement_bind_string_by_name(statement, k.as_ptr(), key.as_ptr());
//        cass_statement_bind_bool_by_name(statement, b.as_ptr(), basic.bln);
//        cass_statement_bind_float_by_name(statement, f.as_ptr(), basic.flt);
//        cass_statement_bind_double_by_name(statement, d.as_ptr(), basic.dbl);
//        cass_statement_bind_int32_by_name(statement, i32.as_ptr(), basic.i32);
//        cass_statement_bind_int64_by_name(statement, i64.as_ptr(), basic.i64);

        let future = &mut* cass_session_execute(session, statement);

        cass_future_wait(future);

        let rc = cass_future_error_code(future);
        if rc != CASS_OK {
            print_error(future);
        }

        cass_future_free(future);
        cass_statement_free(statement);

        Ok(())
    }
}

fn select_from_basic(session: &mut CassSession, key: &str) -> Result<Basic, CassError> {
    unsafe {
        let key = CString::new(key).unwrap();
        let query = CString::new("SELECT * FROM examples.basic WHERE key = ?").unwrap();
        let mut output: Basic = mem::zeroed();
        let local_key = CString::new("key").unwrap();

        let statement = &mut*cass_statement_new(query.as_ptr(), 1);

        cass_statement_bind_string_by_name(statement, local_key.as_ptr(), key.as_ptr());

        let future = &mut*cass_session_execute(session, statement);
        cass_future_wait(future);

        let rc = cass_future_error_code(future);
        if rc != CASS_OK {
            print_error(future);
        } else {
            let result = &*cass_future_get_result(future);
            let iterator = &mut*cass_iterator_from_result(result);

            if cass_iterator_next(iterator) > 0 {
                let row = &*cass_iterator_get_row(iterator);

                cass_value_get_bool(cass_row_get_column_by_name(row, CString::new("BLN").unwrap().as_ptr()),
                                    &mut output.bln);
                cass_value_get_double(cass_row_get_column_by_name(row, CString::new("dbl").unwrap().as_ptr()),
                                      &mut output.dbl);
                cass_value_get_float(cass_row_get_column_by_name(row, CString::new("flt").unwrap().as_ptr()),
                                     &mut output.flt);
                cass_value_get_int32(cass_row_get_column_by_name(row, CString::new("\"i32\"").unwrap().as_ptr()),
                                     &mut output.i32);
                cass_value_get_int64(cass_row_get_column_by_name(row, CString::new("i64").unwrap().as_ptr()),
                                     &mut output.i64);
            }

            cass_result_free(result);
            cass_iterator_free(iterator);
        }

        cass_future_free(future);
        cass_statement_free(statement);

        Ok(output)
    }
}

fn main() {
    unsafe {
        let cluster = &mut*create_cluster();
        let session = &mut*cass_session_new();
        let input = Basic { bln: cass_true, flt: 0.001f32, dbl: 0.0002, i32: 1, i64: 2 };

        if connect_session(session, cluster) != CASS_OK {
            cass_cluster_free(cluster);
            cass_session_free(session);
        }

        execute_query(session,
                "CREATE KEYSPACE IF NOT EXISTS examples WITH replication = { \
                           'class': 'SimpleStrategy', 'replication_factor': '3' };").unwrap();

        execute_query(session,
                "CREATE TABLE IF NOT EXISTS examples.basic (key text, \
                                              bln boolean, \
                                              flt float, dbl double,\
                                              i32 int, i64 bigint, \
                                              PRIMARY KEY (key));").unwrap();

        insert_into_basic(session, "named_parameters", &input).unwrap();
//  let output = select_from_basic(session, "named_parameters").unwrap();
//
//  assert!(input.bln == output.bln);
//  assert!(input.flt == output.flt);
//  assert!(input.dbl == output.dbl);
//  assert!(input.i32 == output.i32);
//  assert!(input.i64 == output.i64);

        let close_future = &mut*cass_session_close(session);
        cass_future_wait(close_future);
        cass_future_free(close_future);

        cass_cluster_free(cluster);
        cass_session_free(session);

    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Generic implementations of some DOM APIs so they can be shared between Servo
//! and Gecko.

use context::QuirksMode;
use dom::{TDocument, TElement, TNode};
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
use selectors::{Element, NthIndexCache, SelectorList};
use selectors::matching::{self, MatchingContext, MatchingMode};
use selectors::parser::{Component, LocalName};
use smallvec::SmallVec;
use std::borrow::Borrow;

/// <https://dom.spec.whatwg.org/#dom-element-matches>
pub fn element_matches<E>(
    element: &E,
    selector_list: &SelectorList<E::Impl>,
    quirks_mode: QuirksMode,
) -> bool
where
    E: Element,
{
    let mut context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        None,
        quirks_mode,
    );
    context.scope_element = Some(element.opaque());
    matching::matches_selector_list(selector_list, element, &mut context)
}

/// <https://dom.spec.whatwg.org/#dom-element-closest>
pub fn element_closest<E>(
    element: E,
    selector_list: &SelectorList<E::Impl>,
    quirks_mode: QuirksMode,
) -> Option<E>
where
    E: Element,
{
    let mut nth_index_cache = NthIndexCache::default();

    let mut context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        Some(&mut nth_index_cache),
        quirks_mode,
    );
    context.scope_element = Some(element.opaque());

    let mut current = Some(element);
    while let Some(element) = current.take() {
        if matching::matches_selector_list(selector_list, &element, &mut context) {
            return Some(element);
        }
        current = element.parent_element();
    }

    return None;
}

/// A selector query abstraction, in order to be generic over QuerySelector and
/// QuerySelectorAll.
pub trait SelectorQuery<E: TElement> {
    /// The output of the query.
    type Output;

    /// Whether the query should stop after the first element has been matched.
    fn should_stop_after_first_match() -> bool;

    /// Append an element matching after the first query.
    fn append_element(output: &mut Self::Output, element: E);

    /// Returns true if the output is empty.
    fn is_empty(output: &Self::Output) -> bool;
}

/// The result of a querySelectorAll call.
pub type QuerySelectorAllResult<E> = SmallVec<[E; 128]>;

/// A query for all the elements in a subtree.
pub struct QueryAll;

impl<E: TElement> SelectorQuery<E> for QueryAll {
    type Output = QuerySelectorAllResult<E>;

    fn should_stop_after_first_match() -> bool { false }

    fn append_element(output: &mut Self::Output, element: E) {
        output.push(element);
    }

    fn is_empty(output: &Self::Output) -> bool {
        output.is_empty()
    }
}

/// A query for the first in-tree match of all the elements in a subtree.
pub struct QueryFirst;

impl<E: TElement> SelectorQuery<E> for QueryFirst {
    type Output = Option<E>;

    fn should_stop_after_first_match() -> bool { true }

    fn append_element(output: &mut Self::Output, element: E) {
        if output.is_none() {
            *output = Some(element)
        }
    }

    fn is_empty(output: &Self::Output) -> bool {
        output.is_none()
    }
}

struct QuerySelectorProcessor<'a, E, Q>
where
    E: TElement + 'a,
    Q: SelectorQuery<E>,
    Q::Output: 'a,
{
    results: &'a mut Q::Output,
    matching_context: MatchingContext<'a, E::Impl>,
    selector_list: &'a SelectorList<E::Impl>,
}

impl<'a, E, Q> InvalidationProcessor<'a, E> for QuerySelectorProcessor<'a, E, Q>
where
    E: TElement + 'a,
    Q: SelectorQuery<E>,
    Q::Output: 'a,
{
    fn light_tree_only(&self) -> bool { true }

    fn collect_invalidations(
        &mut self,
        element: E,
        self_invalidations: &mut InvalidationVector<'a>,
        descendant_invalidations: &mut InvalidationVector<'a>,
        _sibling_invalidations: &mut InvalidationVector<'a>,
    ) -> bool {
        // TODO(emilio): If the element is not a root element, and
        // selector_list has any descendant combinator, we need to do extra work
        // in order to handle properly things like:
        //
        //

        //

        //

        //

        //

        //
        // b.querySelector('#a div'); // Should return "c".
        //
        // For now, assert it's a root element.
        debug_assert!(element.parent_element().is_none());

        let target_vector =
            if self.matching_context.scope_element.is_some() {
                descendant_invalidations
            } else {
                self_invalidations
            };

        for selector in self.selector_list.0.iter() {
            target_vector.push(Invalidation::new(selector, 0))
        }

        false
    }

    fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
        &mut self.matching_context
    }

    fn should_process_descendants(&mut self, _: E) -> bool {
        if Q::should_stop_after_first_match() {
            return Q::is_empty(&self.results)
        }

        true
    }

    fn invalidated_self(&mut self, e: E) {
        Q::append_element(self.results, e);
    }

    fn recursion_limit_exceeded(&mut self, _e: E) {}
    fn invalidated_descendants(&mut self, _e: E, _child: E) {}
}

fn collect_all_elements<E, Q, F>(
    root: E::ConcreteNode,
    results: &mut Q::Output,
    mut filter: F,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
    F: FnMut(E) -> bool,
{
    for node in root.dom_descendants() {
        let element = match node.as_element() {
            Some(e) => e,
            None => continue,
        };

        if !filter(element) {
            continue;
        }

        Q::append_element(results, element);
        if Q::should_stop_after_first_match() {
            return;
        }
    }
}

/// Fast paths for querySelector with a single simple selector.
fn query_selector_single_query<E, Q>(
    root: E::ConcreteNode,
    component: &Component<E::Impl>,
    results: &mut Q::Output,
    quirks_mode: QuirksMode,
) -> Result<(), ()>
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    match *component {
        Component::ExplicitUniversalType => {
            collect_all_elements::<E, Q, _>(root, results, |_| true)
        }
        Component::ID(ref id) => {
            // TODO(emilio): We may want to reuse Gecko's document ID table.
            let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
            collect_all_elements::<E, Q, _>(root, results, |element| {
                element.has_id(id, case_sensitivity)
            })
        }
        Component::Class(ref class) => {
            let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
            collect_all_elements::<E, Q, _>(root, results, |element| {
                element.has_class(class, case_sensitivity)
            })
        }
        Component::LocalName(LocalName { ref name, ref lower_name }) => {
            collect_all_elements::<E, Q, _>(root, results, |element| {
                if element.is_html_element_in_html_document() {
                    element.get_local_name() == lower_name.borrow()
                } else {
                    element.get_local_name() == name.borrow()
                }
            })
        }
        // TODO(emilio): More fast paths?
        _ => {
            return Err(())
        }
    }

    Ok(())
}

/// Fast paths for a given selector query.
///
/// FIXME(emilio, nbp): This may very well be a good candidate for code to be
/// replaced by HolyJit :)
fn query_selector_fast<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    quirks_mode: QuirksMode,
) -> Result<(), ()>
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    // We need to return elements in document order, and reordering them
    // afterwards is kinda silly.
    if selector_list.0.len() > 1 {
        return Err(());
    }

    let selector = &selector_list.0[0];

    // Let's just care about the easy cases for now.
    if selector.len() == 1 {
        return query_selector_single_query::<E, Q>(
            root,
            selector.iter().next().unwrap(),
            results,
            quirks_mode,
        );
    }

    // FIXME(emilio): Implement better optimizations for compound selectors and
    // such.
    Err(())
}

// Slow path for a given selector query.
fn query_selector_slow<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    matching_context: &mut MatchingContext<E::Impl>,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    collect_all_elements::<E, Q, _>(root, results, |element| {
        matching::matches_selector_list(selector_list, &element, matching_context)
    });
}

/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
pub fn query_selector<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    use invalidation::element::invalidator::TreeStyleInvalidator;

    let quirks_mode = root.owner_doc().quirks_mode();
    let fast_result = query_selector_fast::<E, Q>(
        root,
        selector_list,
        results,
        quirks_mode,
    );

    if fast_result.is_ok() {
        return;
    }

    // Slow path: Use the invalidation machinery if we're a root, and tree
    // traversal otherwise.
    //
    // See the comment in collect_invalidations to see why only if we're a root.
    let mut nth_index_cache = NthIndexCache::default();
    let mut matching_context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        Some(&mut nth_index_cache),
        quirks_mode,
    );

    let root_element = root.as_element();
    matching_context.scope_element = root_element.map(|e| e.opaque());

    // The invalidation mechanism is only useful in presence of combinators.
    //
    // We could do that check properly here, though checking the length of the
    // selectors is a good heuristic.
    let invalidation_may_be_useful =
        selector_list.0.iter().any(|s| s.len() > 1);

    if root_element.is_some() || !invalidation_may_be_useful {
        query_selector_slow::<E, Q>(
            root,
            selector_list,
            results,
            &mut matching_context,
        );
    } else {
        let mut processor = QuerySelectorProcessor::<E, Q> {
            results,
            matching_context,
            selector_list,
        };

        for node in root.dom_children() {
            if let Some(e) = node.as_element() {
                TreeStyleInvalidator::new(
                    e,
                    /* stack_limit_checker = */ None,
                    &mut processor,
                ).invalidate();
            }
        }
    }
}
<commit_msg>style: Add a fast path for querySelector/All with a single id selector using the doc ID table.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Generic implementations of some DOM APIs so they can be shared between Servo
//! and Gecko.

use context::QuirksMode;
use dom::{TDocument, TElement, TNode};
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
use selectors::{Element, NthIndexCache, SelectorList};
use selectors::attr::CaseSensitivity;
use selectors::matching::{self, MatchingContext, MatchingMode};
use selectors::parser::{Component, LocalName};
use smallvec::SmallVec;
use std::borrow::Borrow;

/// <https://dom.spec.whatwg.org/#dom-element-matches>
pub fn element_matches<E>(
    element: &E,
    selector_list: &SelectorList<E::Impl>,
    quirks_mode: QuirksMode,
) -> bool
where
    E: Element,
{
    let mut context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        None,
        quirks_mode,
    );
    context.scope_element = Some(element.opaque());
    matching::matches_selector_list(selector_list, element, &mut context)
}

/// <https://dom.spec.whatwg.org/#dom-element-closest>
pub fn element_closest<E>(
    element: E,
    selector_list: &SelectorList<E::Impl>,
    quirks_mode: QuirksMode,
) -> Option<E>
where
    E: Element,
{
    let mut nth_index_cache = NthIndexCache::default();

    let mut context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        Some(&mut nth_index_cache),
        quirks_mode,
    );
    context.scope_element = Some(element.opaque());

    let mut current = Some(element);
    while let Some(element) = current.take() {
        if matching::matches_selector_list(selector_list, &element, &mut context) {
            return Some(element);
        }
        current = element.parent_element();
    }

    return None;
}

/// A selector query abstraction, in order to be generic over QuerySelector and
/// QuerySelectorAll.
pub trait SelectorQuery<E: TElement> {
    /// The output of the query.
    type Output;

    /// Whether the query should stop after the first element has been matched.
    fn should_stop_after_first_match() -> bool;

    /// Append an element matching after the first query.
    fn append_element(output: &mut Self::Output, element: E);

    /// Returns true if the output is empty.
    fn is_empty(output: &Self::Output) -> bool;
}

/// The result of a querySelectorAll call.
pub type QuerySelectorAllResult<E> = SmallVec<[E; 128]>;

/// A query for all the elements in a subtree.
pub struct QueryAll;

impl<E: TElement> SelectorQuery<E> for QueryAll {
    type Output = QuerySelectorAllResult<E>;

    fn should_stop_after_first_match() -> bool { false }

    fn append_element(output: &mut Self::Output, element: E) {
        output.push(element);
    }

    fn is_empty(output: &Self::Output) -> bool {
        output.is_empty()
    }
}

/// A query for the first in-tree match of all the elements in a subtree.
pub struct QueryFirst;

impl<E: TElement> SelectorQuery<E> for QueryFirst {
    type Output = Option<E>;

    fn should_stop_after_first_match() -> bool { true }

    fn append_element(output: &mut Self::Output, element: E) {
        if output.is_none() {
            *output = Some(element)
        }
    }

    fn is_empty(output: &Self::Output) -> bool {
        output.is_none()
    }
}

struct QuerySelectorProcessor<'a, E, Q>
where
    E: TElement + 'a,
    Q: SelectorQuery<E>,
    Q::Output: 'a,
{
    results: &'a mut Q::Output,
    matching_context: MatchingContext<'a, E::Impl>,
    selector_list: &'a SelectorList<E::Impl>,
}

impl<'a, E, Q> InvalidationProcessor<'a, E> for QuerySelectorProcessor<'a, E, Q>
where
    E: TElement + 'a,
    Q: SelectorQuery<E>,
    Q::Output: 'a,
{
    fn light_tree_only(&self) -> bool { true }

    fn collect_invalidations(
        &mut self,
        element: E,
        self_invalidations: &mut InvalidationVector<'a>,
        descendant_invalidations: &mut InvalidationVector<'a>,
        _sibling_invalidations: &mut InvalidationVector<'a>,
    ) -> bool {
        // TODO(emilio): If the element is not a root element, and
        // selector_list has any descendant combinator, we need to do extra work
        // in order to handle properly things like:
        //
        //

        //

        //

        //

        //

        //
        // b.querySelector('#a div'); // Should return "c".
        //
        // For now, assert it's a root element.
        debug_assert!(element.parent_element().is_none());

        let target_vector =
            if self.matching_context.scope_element.is_some() {
                descendant_invalidations
            } else {
                self_invalidations
            };

        for selector in self.selector_list.0.iter() {
            target_vector.push(Invalidation::new(selector, 0))
        }

        false
    }

    fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
        &mut self.matching_context
    }

    fn should_process_descendants(&mut self, _: E) -> bool {
        if Q::should_stop_after_first_match() {
            return Q::is_empty(&self.results)
        }

        true
    }

    fn invalidated_self(&mut self, e: E) {
        Q::append_element(self.results, e);
    }

    fn recursion_limit_exceeded(&mut self, _e: E) {}
    fn invalidated_descendants(&mut self, _e: E, _child: E) {}
}

fn collect_all_elements<E, Q, F>(
    root: E::ConcreteNode,
    results: &mut Q::Output,
    mut filter: F,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
    F: FnMut(E) -> bool,
{
    for node in root.dom_descendants() {
        let element = match node.as_element() {
            Some(e) => e,
            None => continue,
        };

        if !filter(element) {
            continue;
        }

        Q::append_element(results, element);
        if Q::should_stop_after_first_match() {
            return;
        }
    }
}

/// Returns whether a given element is descendant of a given `root` node.
///
/// NOTE(emilio): if root == element, this returns false.
fn element_is_descendant_of<E>(element: E, root: E::ConcreteNode) -> bool
where
    E: TElement,
{
    let mut current = element.as_node().parent_node();
    while let Some(n) = current.take() {
        if n == root {
            return true;
        }

        current = n.parent_node();
    }
    false
}

/// Fast paths for querySelector with a single simple selector.
fn query_selector_single_query<E, Q>(
    root: E::ConcreteNode,
    component: &Component<E::Impl>,
    results: &mut Q::Output,
    quirks_mode: QuirksMode,
) -> Result<(), ()>
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    match *component {
        Component::ExplicitUniversalType => {
            collect_all_elements::<E, Q, _>(root, results, |_| true)
        }
        Component::ID(ref id) => {
            let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();

            if case_sensitivity == CaseSensitivity::CaseSensitive &&
               root.is_in_document()
            {
                let doc = root.owner_doc();
                if let Ok(elements) = doc.elements_with_id(id) {
                    if root == doc.as_node() {
                        for element in elements {
                            Q::append_element(results, *element);
                            if Q::should_stop_after_first_match() {
                                break;
                            }
                        }
                    } else {
                        for element in elements {
                            if !element_is_descendant_of(*element, root) {
                                continue;
                            }

                            Q::append_element(results, *element);
                            if Q::should_stop_after_first_match() {
                                break;
                            }
                        }
                    }
                    return Ok(())
                }
            }

            collect_all_elements::<E, Q, _>(root, results, |element| {
                element.has_id(id, case_sensitivity)
            })
        }
        Component::Class(ref class) => {
            let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
            collect_all_elements::<E, Q, _>(root, results, |element| {
                element.has_class(class, case_sensitivity)
            })
        }
        Component::LocalName(LocalName { ref name, ref lower_name }) => {
            collect_all_elements::<E, Q, _>(root, results, |element| {
                if element.is_html_element_in_html_document() {
                    element.get_local_name() == lower_name.borrow()
                } else {
                    element.get_local_name() == name.borrow()
                }
            })
        }
        // TODO(emilio): More fast paths?
        _ => {
            return Err(())
        }
    }

    Ok(())
}

/// Fast paths for a given selector query.
///
/// FIXME(emilio, nbp): This may very well be a good candidate for code to be
/// replaced by HolyJit :)
fn query_selector_fast<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    quirks_mode: QuirksMode,
) -> Result<(), ()>
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    // We need to return elements in document order, and reordering them
    // afterwards is kinda silly.
    if selector_list.0.len() > 1 {
        return Err(());
    }

    let selector = &selector_list.0[0];

    // Let's just care about the easy cases for now.
    if selector.len() == 1 {
        return query_selector_single_query::<E, Q>(
            root,
            selector.iter().next().unwrap(),
            results,
            quirks_mode,
        );
    }

    // FIXME(emilio): Implement better optimizations for compound selectors and
    // such.
    Err(())
}

// Slow path for a given selector query.
fn query_selector_slow<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
    matching_context: &mut MatchingContext<E::Impl>,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    collect_all_elements::<E, Q, _>(root, results, |element| {
        matching::matches_selector_list(selector_list, &element, matching_context)
    });
}

/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
pub fn query_selector<E, Q>(
    root: E::ConcreteNode,
    selector_list: &SelectorList<E::Impl>,
    results: &mut Q::Output,
)
where
    E: TElement,
    Q: SelectorQuery<E>,
{
    use invalidation::element::invalidator::TreeStyleInvalidator;

    let quirks_mode = root.owner_doc().quirks_mode();
    let fast_result = query_selector_fast::<E, Q>(
        root,
        selector_list,
        results,
        quirks_mode,
    );

    if fast_result.is_ok() {
        return;
    }

    // Slow path: Use the invalidation machinery if we're a root, and tree
    // traversal otherwise.
    //
    // See the comment in collect_invalidations to see why only if we're a root.
    let mut nth_index_cache = NthIndexCache::default();
    let mut matching_context = MatchingContext::new(
        MatchingMode::Normal,
        None,
        Some(&mut nth_index_cache),
        quirks_mode,
    );

    let root_element = root.as_element();
    matching_context.scope_element = root_element.map(|e| e.opaque());

    // The invalidation mechanism is only useful in presence of combinators.
    //
    // We could do that check properly here, though checking the length of the
    // selectors is a good heuristic.
    let invalidation_may_be_useful =
        selector_list.0.iter().any(|s| s.len() > 1);

    if root_element.is_some() || !invalidation_may_be_useful {
        query_selector_slow::<E, Q>(
            root,
            selector_list,
            results,
            &mut matching_context,
        );
    } else {
        let mut processor = QuerySelectorProcessor::<E, Q> {
            results,
            matching_context,
            selector_list,
        };

        for node in root.dom_children() {
            if let Some(e) = node.as_element() {
                TreeStyleInvalidator::new(
                    e,
                    /* stack_limit_checker = */ None,
                    &mut processor,
                ).invalidate();
            }
        }
    }
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]
extern crate graphene;
#[cfg(test)]
#[macro_use]
extern crate quickcheck;

use graphene::implementations::adjacency_list::*;
use graphene::graph::*;

//Helper functions
fn create_adjListGraph(vertices: Vec<usize>) -> Option<AdjListGraph<usize>>{
	let v_count  = vertices.len();

	//Create all edges
	let mut edges = Vec::new();
	for i in 0..v_count{
		edges.push((i, vertices[i]%v_count));
	}

	//Create graph
	AdjListGraph::new(vertices, edges)
}

//Property functions
fn create_adjListGraph_has_correct_vertex_count(vertices: Vec<usize>) -> bool{
	let v_count = vertices.len();

	match create_adjListGraph(vertices){
		Some(g) => {
			g.vertex_count() == v_count
		}
		None => false,
	}
}

//Test runners
quickcheck!{
	fn prop_create_adjListGraph_has_correct_vertex_count(vertices: Vec<usize>) -> bool{
		create_adjListGraph_has_correct_vertex_count(vertices)
	}
}<commit_msg>Added tests<commit_after>#![allow(non_snake_case)]
extern crate graphene;
#[cfg(test)]
#[macro_use]
extern crate quickcheck;

use graphene::implementations::adjacency_list::*;
use graphene::graph::*;

//Helper functions
fn create_adjListGraph(vertices: Vec<usize>) -> Option<AdjListGraph<usize>>{
	let v_count  = vertices.len();

	//Create all edges
	let mut edges = Vec::new();
	for i in 0..v_count{
		edges.push((i, vertices[i]%v_count));
	}

	//Create graph
	AdjListGraph::new(vertices, edges)
}

//Property functions
fn created_adjListGraph_has_correct_vertex_count(vertices: Vec<usize>) -> bool{
	let v_count = vertices.len();

	match create_adjListGraph(vertices){
		Some(g) => {
			g.vertex_count() == v_count
		}
		None => false,
	}
}

fn create_adjListGraph_has_correct_edge_count(vertices: Vec<usize>) -> bool{
	let v_count = vertices.len();

	match create_adjListGraph(vertices){
		Some(g) => {
			g.edge_count() == v_count
		}
		None => false,
	}
}

//Test runners
quickcheck!{
	fn prop_created_adjListGraph_has_correct_vertex_count(vertices: Vec<usize>) -> bool{
		create_adjListGraph_has_correct_vertex_count(vertices)
	}

	fn prop_created_adjListGraph_has_correct_edge_count(vertices: Vec<usize>) -> bool{
		created_adjListGraph_has_correct_vertex_count(vertices)
	}
}<|endoftext|>


<commit_before>//! Data structures and implementations for union-of-patterns.

use std::mem;
use std::cmp::Ordering;
use std::iter::FromIterator;

use itertools::Itertools;

use util::set::{self, IsSubsetOf};
use super::{Atom, Class, Element, Repetition, Sequence, flatten_vec};

// To hide the implementation details, we wrap the type alias in
// a private submodule.
mod union_impl {
    use std::slice;
    use super::super::Element;
    pub type Inner<T> = Vec<Element<T>>;
    pub type Iter<'a,T> = slice::Iter<'a,Element<T>>;
}

/// Union of patterns.
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct Union<T: Atom>(union_impl::Inner<T>);

impl<T: Atom> Union<T> {
    /// Create a new union from the given vector.
    pub fn new(v: Vec<Element<T>>) -> Self {
        if v.len() < 2 {
            panic!("Unions must have at least two members");
        }
        Union(v)
    }

    /// Fetch an iterator over the members of the union
    pub fn iter<'a>(&'a self) -> UnionIterator<'a,T> {
        UnionIterator(self.0.iter())
    }

    /// Get the number of members in the union
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Transforms each contained atom using the supplied function or closure
    /// to produce a new sequence.
    pub fn map_atoms<U, F>(self, f: F) -> Union<U>
        where F: Fn(T) -> U,
              U: Atom
    {
        self.0.into_iter().map(|elt| elt.map_atoms(&f)).collect()
    }

    fn into_inner(self) -> union_impl::Inner<T> {
        self.0
    }

    /// Flatten the union and apply implementation-defined optimizations.
    pub fn reduce(&mut self) {
        for elt in self.0.iter_mut() {
            elt.reduce();
        }
        flatten_vec(&mut self.0,
                    |elt| match elt { &Element::Union(ref u) => Some(u.len()), _ => None },
                    |elt| match elt { Element::Union(u) => u.into_inner(), _ => unreachable!() });

        let mut reduced = self.0.clone().into_iter()
            .sorted_by(|a, b| { if a.is_subset_of(b) || b.is_subset_of(a) { Ordering::Equal }
                                else { a.cmp(b) } })
            .into_iter()
            .coalesce(|a, b| { if a.is_subset_of(&b) { Ok(b) }
                               else if b.is_subset_of(&a) { Ok(a) }
                               else { Err((a, b)) } })
            .collect();
        mem::swap(&mut self.0, &mut reduced);
    }
}

impl<T: Atom> set::Contains<T> for Union<T> {
    fn contains(&self, atom: T) -> bool {
        self.0.iter().any(|m| m.contains(atom))
    }
}

impl<T: Atom> FromIterator<Element<T>> for Union<T> {
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item=Element<T>>
    {
        Union::new(iter.into_iter().collect())
    }
}

impl<T: Atom> set::IsSubsetOf<Sequence<T>> for Union<T> {
    /// A union is a subset of a sequence S if it consists entirely of
    /// sequences whose elements are subsets of the corresponding element in S.
    fn is_subset_of(&self, seq: &Sequence<T>) -> bool {
        self.iter().all(|m| match m {
            &Element::Sequence(ref s) =>
                seq.len() == s.len() &&
                seq.iter().zip(s.iter()).all(|(seq_elt, s_elt)| s_elt.is_subset_of(seq_elt)),
            _ => false })
    }
}

macro_rules! is_subset_if_all_members_are_subsets {
    ($T: ident,$Other: ty, $name: ident) => {
        impl<$T: Atom> set::IsSubsetOf<$Other> for Union<$T> {
            /// A union is a subset of a $name if all members are subsets.
            fn is_subset_of(&self, $name: &$Other) -> bool {
                self.iter().all(|m| m.is_subset_of($name))
            }
        }
    };
}

is_subset_if_all_members_are_subsets!(T, Repetition<T>, repetition);
is_subset_if_all_members_are_subsets!(T, Class<T>, class);
is_subset_if_all_members_are_subsets!(T, Union<T>, union);

impl<T: Atom> set::IsSubsetOf<Element<T>> for Union<T> {
    fn is_subset_of(&self, elt: &Element<T>) -> bool {
        match elt {
            &Element::Tagged{ref element, ..} => self.is_subset_of(&**element),
            &Element::Class(ref c) => self.is_subset_of(c),
            &Element::Sequence(ref s) => self.is_subset_of(s),
            &Element::Repeat(ref r) => self.is_subset_of(r),
            &Element::Union(ref u) => self.is_subset_of(u),

            // A union is a subset of a wildcard if all members are
            // also subsets.
            &Element::Wildcard => self.iter().all(|m| m.is_subset_of(&Element::Wildcard)),

            // Unions always contain at least two unique members, thus they
            // cannot be subsets of single atoms.
            &Element::Atom(_) => false,
            &Element::Anchor(_) => false,
        }
    }
}

/// Iterator over the patterns within a union.
pub struct UnionIterator<'a,T: 'a + Atom>(union_impl::Iter<'a,T>);

impl<'a,T: 'a + Atom> Iterator for UnionIterator<'a,T> {
    type Item = &'a Element<T>;

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}
<commit_msg>pattern/union: switch `iter` method to use `impl Iterator<...>`<commit_after>//! Data structures and implementations for union-of-patterns.

use std::mem;
use std::cmp::Ordering;
use std::iter::FromIterator;

use itertools::Itertools;

use util::set::{self, IsSubsetOf};
use super::{Atom, Class, Element, Repetition, Sequence, flatten_vec};

// To hide the implementation details, we wrap the type alias in
// a private submodule.
mod union_impl {
    use std::slice;
    use super::super::Element;
    pub type Inner<T> = Vec<Element<T>>;
}

/// Union of patterns.
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub struct Union<T: Atom>(union_impl::Inner<T>);

impl<T: Atom> Union<T> {
    /// Create a new union from the given vector.
    pub fn new(v: Vec<Element<T>>) -> Self {
        if v.len() < 2 {
            panic!("Unions must have at least two members");
        }
        Union(v)
    }

    /// Fetch an iterator over the members of the union
    pub fn iter<'a>(&'a self) -> impl Iterator<Item=&'a Element<T>> {
        self.0.iter()
    }

    /// Get the number of members in the union
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Transforms each contained atom using the supplied function or closure
    /// to produce a new sequence.
    pub fn map_atoms<U, F>(self, f: F) -> Union<U>
        where F: Fn(T) -> U,
              U: Atom
    {
        self.0.into_iter().map(|elt| elt.map_atoms(&f)).collect()
    }

    fn into_inner(self) -> union_impl::Inner<T> {
        self.0
    }

    /// Flatten the union and apply implementation-defined optimizations.
    pub fn reduce(&mut self) {
        for elt in self.0.iter_mut() {
            elt.reduce();
        }
        flatten_vec(&mut self.0,
                    |elt| match elt { &Element::Union(ref u) => Some(u.len()), _ => None },
                    |elt| match elt { Element::Union(u) => u.into_inner(), _ => unreachable!() });

        let mut reduced = self.0.clone().into_iter()
            .sorted_by(|a, b| { if a.is_subset_of(b) || b.is_subset_of(a) { Ordering::Equal }
                                else { a.cmp(b) } })
            .into_iter()
            .coalesce(|a, b| { if a.is_subset_of(&b) { Ok(b) }
                               else if b.is_subset_of(&a) { Ok(a) }
                               else { Err((a, b)) } })
            .collect();
        mem::swap(&mut self.0, &mut reduced);
    }
}

impl<T: Atom> set::Contains<T> for Union<T> {
    fn contains(&self, atom: T) -> bool {
        self.0.iter().any(|m| m.contains(atom))
    }
}

impl<T: Atom> FromIterator<Element<T>> for Union<T> {
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item=Element<T>>
    {
        Union::new(iter.into_iter().collect())
    }
}

impl<T: Atom> set::IsSubsetOf<Sequence<T>> for Union<T> {
    /// A union is a subset of a sequence S if it consists entirely of
    /// sequences whose elements are subsets of the corresponding element in S.
    fn is_subset_of(&self, seq: &Sequence<T>) -> bool {
        self.iter().all(|m| match m {
            &Element::Sequence(ref s) =>
                seq.len() == s.len() &&
                seq.iter().zip(s.iter()).all(|(seq_elt, s_elt)| s_elt.is_subset_of(seq_elt)),
            _ => false })
    }
}

macro_rules! is_subset_if_all_members_are_subsets {
    ($T: ident,$Other: ty, $name: ident) => {
        impl<$T: Atom> set::IsSubsetOf<$Other> for Union<$T> {
            /// A union is a subset of a $name if all members are subsets.
            fn is_subset_of(&self, $name: &$Other) -> bool {
                self.iter().all(|m| m.is_subset_of($name))
            }
        }
    };
}

is_subset_if_all_members_are_subsets!(T, Repetition<T>, repetition);
is_subset_if_all_members_are_subsets!(T, Class<T>, class);
is_subset_if_all_members_are_subsets!(T, Union<T>, union);

impl<T: Atom> set::IsSubsetOf<Element<T>> for Union<T> {
    fn is_subset_of(&self, elt: &Element<T>) -> bool {
        match elt {
            &Element::Tagged{ref element, ..} => self.is_subset_of(&**element),
            &Element::Class(ref c) => self.is_subset_of(c),
            &Element::Sequence(ref s) => self.is_subset_of(s),
            &Element::Repeat(ref r) => self.is_subset_of(r),
            &Element::Union(ref u) => self.is_subset_of(u),

            // A union is a subset of a wildcard if all members are
            // also subsets.
            &Element::Wildcard => self.iter().all(|m| m.is_subset_of(&Element::Wildcard)),

            // Unions always contain at least two unique members, thus they
            // cannot be subsets of single atoms.
            &Element::Atom(_) => false,
            &Element::Anchor(_) => false,
        }
    }
}
<|endoftext|>


<commit_before>/*!

A render buffer is similar to a texture, but is optimized for usage as a draw target.

Contrary to a texture, you can't sample nor modify the content of a render buffer.
You should prefer render buffers over textures when you know that you don't need to read or modify
the data of the render buffer.

*/
use std::sync::Arc;
use std::sync::mpsc::channel;
use std::mem;

use framebuffer::{ColorAttachment, ToColorAttachment};
use framebuffer::{DepthAttachment, ToDepthAttachment};
use framebuffer::{StencilAttachment, ToStencilAttachment};
use framebuffer::{DepthStencilAttachment, ToDepthStencilAttachment};
use texture::{UncompressedFloatFormat, DepthFormat, StencilFormat, DepthStencilFormat};

use {gl, context};
use {GlObject, DisplayImpl, ToGlEnum};
use version::Api;

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `RenderBuffer`.
pub struct RenderBuffer {
    buffer: RenderBufferImpl,
}

impl RenderBuffer {
    /// Builds a new render buffer.
    pub fn new(display: &::Display, format: UncompressedFloatFormat, width: u32, height: u32)
               -> RenderBuffer
    {
        RenderBuffer {
            buffer: RenderBufferImpl::new(display, format.to_glenum(), width, height)
        }
    }

    /// Returns the dimensions of the render buffer.
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.buffer.width, self.buffer.height)
    }
}

impl ToColorAttachment for RenderBuffer {
    fn to_color_attachment(&self) -> ColorAttachment {
        ColorAttachment::RenderBuffer(self)
    }
}

impl GlObject for RenderBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `DepthRenderBuffer` directly.
pub struct DepthRenderBuffer {
    buffer: RenderBufferImpl,
}

impl DepthRenderBuffer {
    /// Builds a new render buffer.
    pub fn new(display: &::Display, format: DepthFormat, width: u32, height: u32)
               -> DepthRenderBuffer
    {
        DepthRenderBuffer {
            buffer: RenderBufferImpl::new(display, format.to_glenum(), width, height)
        }
    }

    /// Returns the dimensions of the render buffer.
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.buffer.width, self.buffer.height)
    }
}

impl ToDepthAttachment for DepthRenderBuffer {
    fn to_depth_attachment(&self) -> DepthAttachment {
        DepthAttachment::RenderBuffer(self)
    }
}

impl GlObject for DepthRenderBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `StencilRenderBuffer` directly.
pub struct StencilRenderBuffer {
    buffer: RenderBufferImpl,
}

impl StencilRenderBuffer {
    /// Builds a new render buffer.
    pub fn new(display: &::Display, format: StencilFormat, width: u32, height: u32)
               -> StencilRenderBuffer
    {
        StencilRenderBuffer {
            buffer: RenderBufferImpl::new(display, format.to_glenum(), width, height)
        }
    }

    /// Returns the dimensions of the render buffer.
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.buffer.width, self.buffer.height)
    }
}

impl ToStencilAttachment for StencilRenderBuffer {
    fn to_stencil_attachment(&self) -> StencilAttachment {
        StencilAttachment::RenderBuffer(self)
    }
}

impl GlObject for StencilRenderBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `DepthStencilRenderBuffer` directly.
pub struct DepthStencilRenderBuffer {
    buffer: RenderBufferImpl,
}

impl DepthStencilRenderBuffer {
    /// Builds a new render buffer.
    pub fn new(display: &::Display, format: DepthStencilFormat, width: u32, height: u32)
               -> DepthStencilRenderBuffer
    {
        DepthStencilRenderBuffer {
            buffer: RenderBufferImpl::new(display, format.to_glenum(), width, height)
        }
    }

    /// Returns the dimensions of the render buffer.
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.buffer.width, self.buffer.height)
    }
}

impl ToDepthStencilAttachment for DepthStencilRenderBuffer {
    fn to_depth_stencil_attachment(&self) -> DepthStencilAttachment {
        DepthStencilAttachment::RenderBuffer(self)
    }
}

impl GlObject for DepthStencilRenderBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// The implementation
struct RenderBufferImpl {
    display: Arc<DisplayImpl>,
    id: gl::types::GLuint,
    width: u32,
    height: u32,
}

impl RenderBufferImpl {
    /// Builds a new render buffer.
    fn new(display: &::Display, format: gl::types::GLenum, width: u32, height: u32)
           -> RenderBufferImpl
    {
        let (tx, rx) = channel();

        // TODO: check that dimensions don't exceed GL_MAX_RENDERBUFFER_SIZE

        display.context.context.exec(move |ctxt| {
            unsafe {
                let mut id = mem::uninitialized();

                if ctxt.version >= &context::GlVersion(Api::Gl, 4, 5) ||
                    ctxt.extensions.gl_arb_direct_state_access
                {
                    ctxt.gl.CreateRenderbuffers(1, &mut id);
                    ctxt.gl.NamedRenderbufferStorage(id, format, width as gl::types::GLsizei,
                                                     height as gl::types::GLsizei);

                } else if ctxt.version >= &context::GlVersion(Api::Gl, 3, 0) {
                    ctxt.gl.GenRenderbuffers(1, &mut id);
                    ctxt.gl.BindRenderbuffer(gl::RENDERBUFFER, id);
                    ctxt.state.renderbuffer = id;
                    ctxt.gl.RenderbufferStorage(gl::RENDERBUFFER, format,
                                                width as gl::types::GLsizei,
                                                height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_ext_framebuffer_object {
                    ctxt.gl.GenRenderbuffersEXT(1, &mut id);
                    ctxt.gl.BindRenderbufferEXT(gl::RENDERBUFFER_EXT, id);
                    ctxt.state.renderbuffer = id;
                    ctxt.gl.RenderbufferStorageEXT(gl::RENDERBUFFER_EXT, format,
                                                   width as gl::types::GLsizei,
                                                   height as gl::types::GLsizei);

                } else {
                    unreachable!();
                }

                tx.send(id).unwrap();
            }
        });

        RenderBufferImpl {
            display: display.context.clone(),
            id: rx.recv().unwrap(),
            width: width,
            height: height,
        }
    }
}

impl Drop for RenderBufferImpl {
    fn drop(&mut self) {
        // removing FBOs which contain this buffer
        self.display.framebuffer_objects.as_ref().unwrap()
                    .purge_renderbuffer(self.id, &self.display.context);

        // destroying
        let id = self.id.clone();
        self.display.context.exec(move |ctxt| {
            unsafe {

                if ctxt.version >= &context::GlVersion(Api::Gl, 3, 0) {
                    if ctxt.state.renderbuffer == id {
                        ctxt.gl.BindRenderbuffer(gl::RENDERBUFFER, 0);
                        ctxt.state.renderbuffer = 0;
                    }
                    ctxt.gl.DeleteRenderbuffers(1, [ id ].as_ptr());

                } else if ctxt.extensions.gl_ext_framebuffer_object {
                    if ctxt.state.renderbuffer == id {
                        ctxt.gl.BindRenderbufferEXT(gl::RENDERBUFFER_EXT, 0);
                        ctxt.state.renderbuffer = 0;
                    }
                    ctxt.gl.DeleteRenderbuffersEXT(1, [ id ].as_ptr());

                } else {
                    unreachable!();
                }
            }
        });
    }
}

impl GlObject for RenderBufferImpl {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.id
    }
}
<commit_msg>Fix OpenGL ES usage for render_buffer.rs<commit_after>/*!

A render buffer is similar to a texture, but is optimized for usage as a draw target.

Contrary to a texture, you can't sample nor modify the content of a render buffer.
You should prefer render buffers over textures when you know that you don't need to read or modify
the data of the render buffer.

*/
use std::sync::Arc;
use std::sync::mpsc::channel;
use std::mem;

use framebuffer::{ColorAttachment, ToColorAttachment};
use framebuffer::{DepthAttachment, ToDepthAttachment};
use framebuffer::{StencilAttachment, ToStencilAttachment};
use framebuffer::{DepthStencilAttachment, ToDepthStencilAttachment};
use texture::{UncompressedFloatFormat, DepthFormat, StencilFormat, DepthStencilFormat};

use {gl, context};
use {GlObject, DisplayImpl, ToGlEnum};
use version::Api;

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `RenderBuffer`.
pub struct RenderBuffer {
    buffer: RenderBufferImpl,
}

impl RenderBuffer {
    /// Builds a new render buffer.
    pub fn new(display: &::Display, format: UncompressedFloatFormat, width: u32, height: u32)
               -> RenderBuffer
    {
        RenderBuffer {
            buffer: RenderBufferImpl::new(display, format.to_glenum(), width, height)
        }
    }

    /// Returns the dimensions of the render buffer.
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.buffer.width, self.buffer.height)
    }
}

impl ToColorAttachment for RenderBuffer {
    fn to_color_attachment(&self) -> ColorAttachment {
        ColorAttachment::RenderBuffer(self)
    }
}

impl GlObject for RenderBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `DepthRenderBuffer` directly.
pub struct DepthRenderBuffer {
    buffer: RenderBufferImpl,
}

impl DepthRenderBuffer {
    /// Builds a new render buffer.
    pub fn new(display: &::Display, format: DepthFormat, width: u32, height: u32)
               -> DepthRenderBuffer
    {
        DepthRenderBuffer {
            buffer: RenderBufferImpl::new(display, format.to_glenum(), width, height)
        }
    }

    /// Returns the dimensions of the render buffer.
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.buffer.width, self.buffer.height)
    }
}

impl ToDepthAttachment for DepthRenderBuffer {
    fn to_depth_attachment(&self) -> DepthAttachment {
        DepthAttachment::RenderBuffer(self)
    }
}

impl GlObject for DepthRenderBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `StencilRenderBuffer` directly.
pub struct StencilRenderBuffer {
    buffer: RenderBufferImpl,
}

impl StencilRenderBuffer {
    /// Builds a new render buffer.
    pub fn new(display: &::Display, format: StencilFormat, width: u32, height: u32)
               -> StencilRenderBuffer
    {
        StencilRenderBuffer {
            buffer: RenderBufferImpl::new(display, format.to_glenum(), width, height)
        }
    }

    /// Returns the dimensions of the render buffer.
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.buffer.width, self.buffer.height)
    }
}

impl ToStencilAttachment for StencilRenderBuffer {
    fn to_stencil_attachment(&self) -> StencilAttachment {
        StencilAttachment::RenderBuffer(self)
    }
}

impl GlObject for StencilRenderBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// A render buffer is similar to a texture, but is optimized for usage as a draw target.
///
/// Contrary to a texture, you can't sample or modify the content of the `DepthStencilRenderBuffer` directly.
pub struct DepthStencilRenderBuffer {
    buffer: RenderBufferImpl,
}

impl DepthStencilRenderBuffer {
    /// Builds a new render buffer.
    pub fn new(display: &::Display, format: DepthStencilFormat, width: u32, height: u32)
               -> DepthStencilRenderBuffer
    {
        DepthStencilRenderBuffer {
            buffer: RenderBufferImpl::new(display, format.to_glenum(), width, height)
        }
    }

    /// Returns the dimensions of the render buffer.
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.buffer.width, self.buffer.height)
    }
}

impl ToDepthStencilAttachment for DepthStencilRenderBuffer {
    fn to_depth_stencil_attachment(&self) -> DepthStencilAttachment {
        DepthStencilAttachment::RenderBuffer(self)
    }
}

impl GlObject for DepthStencilRenderBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

/// The implementation
struct RenderBufferImpl {
    display: Arc<DisplayImpl>,
    id: gl::types::GLuint,
    width: u32,
    height: u32,
}

impl RenderBufferImpl {
    /// Builds a new render buffer.
    fn new(display: &::Display, format: gl::types::GLenum, width: u32, height: u32)
           -> RenderBufferImpl
    {
        let (tx, rx) = channel();

        // TODO: check that dimensions don't exceed GL_MAX_RENDERBUFFER_SIZE

        display.context.context.exec(move |ctxt| {
            unsafe {
                let mut id = mem::uninitialized();

                if ctxt.version >= &context::GlVersion(Api::Gl, 4, 5) ||
                    ctxt.extensions.gl_arb_direct_state_access
                {
                    ctxt.gl.CreateRenderbuffers(1, &mut id);
                    ctxt.gl.NamedRenderbufferStorage(id, format, width as gl::types::GLsizei,
                                                     height as gl::types::GLsizei);

                } else if ctxt.version >= &context::GlVersion(Api::Gl, 3, 0) ||
                          ctxt.version >= &context::GlVersion(Api::GlEs, 2, 0)
                {
                    ctxt.gl.GenRenderbuffers(1, &mut id);
                    ctxt.gl.BindRenderbuffer(gl::RENDERBUFFER, id);
                    ctxt.state.renderbuffer = id;
                    // FIXME: gles2 only supports very few formats
                    ctxt.gl.RenderbufferStorage(gl::RENDERBUFFER, format,
                                                width as gl::types::GLsizei,
                                                height as gl::types::GLsizei);

                } else if ctxt.extensions.gl_ext_framebuffer_object {
                    ctxt.gl.GenRenderbuffersEXT(1, &mut id);
                    ctxt.gl.BindRenderbufferEXT(gl::RENDERBUFFER_EXT, id);
                    ctxt.state.renderbuffer = id;
                    ctxt.gl.RenderbufferStorageEXT(gl::RENDERBUFFER_EXT, format,
                                                   width as gl::types::GLsizei,
                                                   height as gl::types::GLsizei);

                } else {
                    unreachable!();
                }

                tx.send(id).unwrap();
            }
        });

        RenderBufferImpl {
            display: display.context.clone(),
            id: rx.recv().unwrap(),
            width: width,
            height: height,
        }
    }
}

impl Drop for RenderBufferImpl {
    fn drop(&mut self) {
        // removing FBOs which contain this buffer
        self.display.framebuffer_objects.as_ref().unwrap()
                    .purge_renderbuffer(self.id, &self.display.context);

        // destroying
        let id = self.id.clone();
        self.display.context.exec(move |ctxt| {
            unsafe {
                if ctxt.version >= &context::GlVersion(Api::Gl, 3, 0) ||
                   ctxt.version >= &context::GlVersion(Api::GlEs, 2, 0)
                {
                    if ctxt.state.renderbuffer == id {
                        ctxt.gl.BindRenderbuffer(gl::RENDERBUFFER, 0);
                        ctxt.state.renderbuffer = 0;
                    }
                    ctxt.gl.DeleteRenderbuffers(1, [ id ].as_ptr());

                } else if ctxt.extensions.gl_ext_framebuffer_object {
                    if ctxt.state.renderbuffer == id {
                        ctxt.gl.BindRenderbufferEXT(gl::RENDERBUFFER_EXT, 0);
                        ctxt.state.renderbuffer = 0;
                    }
                    ctxt.gl.DeleteRenderbuffersEXT(1, [ id ].as_ptr());

                } else {
                    unreachable!();
                }
            }
        });
    }
}

impl GlObject for RenderBufferImpl {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.id
    }
}
<|endoftext|>


<commit_before>use winapi;
use secur32;
use std::io;
use std::mem;
use std::ptr;

use Inner;

lazy_static! {
    static ref UNISP_NAME: Vec<u8> = winapi::UNISP_NAME.bytes().chain(Some(0)).collect();
}

#[derive(Copy, Debug, Clone, PartialEq, Eq)]
pub enum Direction {
    Inbound,
    Outbound,
}

/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum Algorithm {
    /// Advanced Encryption Standard (AES).
    Aes = winapi::CALG_AES,
    /// 128 bit AES.
    Aes128 = winapi::CALG_AES_128,
    /// 192 bit AES.
    Aes192 = winapi::CALG_AES_192,
    /// 256 bit AES.
    Aes256 = winapi::CALG_AES_256,
    /// Temporary algorithm identifier for handles of Diffie-Hellman–agreed keys.
    AgreedkeyAny = winapi::CALG_AGREEDKEY_ANY,
    /// An algorithm to create a 40-bit DES key that has parity bits and zeroed key bits to make
    /// its key length 64 bits.
    CylinkMek = winapi::CALG_CYLINK_MEK,
    /// DES encryption algorithm.
    Des = winapi::CALG_DES,
    /// DESX encryption algorithm.
    Desx = winapi::CALG_DESX,
    /// Diffie-Hellman ephemeral key exchange algorithm.
    DhEphem = winapi::CALG_DH_EPHEM,
    /// Diffie-Hellman store and forward key exchange algorithm.
    DhSf = winapi::CALG_DH_SF,
    /// DSA public key signature algorithm.
    DssSign = winapi::CALG_DSS_SIGN,
    /// Elliptic curve Diffie-Hellman key exchange algorithm.
    Ecdh = winapi::CALG_ECDH,
    // https://github.com/retep998/winapi-rs/issues/287
    // /// Ephemeral elliptic curve Diffie-Hellman key exchange algorithm.
    // EcdhEphem = winapi::CALG_ECDH_EPHEM,
    /// Elliptic curve digital signature algorithm.
    Ecdsa = winapi::CALG_ECDSA,
    /// One way function hashing algorithm.
    HashReplaceOwf = winapi::CALG_HASH_REPLACE_OWF,
    /// Hughes MD5 hashing algorithm.
    HughesMd5 = winapi::CALG_HUGHES_MD5,
    /// HMAC keyed hash algorithm.
    Hmac = winapi::CALG_HMAC,
    /// MAC keyed hash algorithm.
    Mac = winapi::CALG_MAC,
    /// MD2 hashing algorithm.
    Md2 = winapi::CALG_MD2,
    /// MD4 hashing algorithm.
    Md4 = winapi::CALG_MD4,
    /// MD5 hashing algorithm.
    Md5 = winapi::CALG_MD5,
    /// No signature algorithm..
    NoSign = winapi::CALG_NO_SIGN,
    /// RC2 block encryption algorithm.
    Rc2 = winapi::CALG_RC2,
    /// RC4 stream encryption algorithm.
    Rc4 = winapi::CALG_RC4,
    /// RC5 block encryption algorithm.
    Rc5 = winapi::CALG_RC5,
    /// RSA public key exchange algorithm.
    RsaKeyx = winapi::CALG_RSA_KEYX,
    /// RSA public key signature algorithm.
    RsaSign = winapi::CALG_RSA_SIGN,
    /// SHA hashing algorithm.
    Sha1 = winapi::CALG_SHA1,
    /// 256 bit SHA hashing algorithm.
    Sha256 = winapi::CALG_SHA_256,
    /// 384 bit SHA hashing algorithm.
    Sha384 = winapi::CALG_SHA_384,
    /// 512 bit SHA hashing algorithm.
    Sha512 = winapi::CALG_SHA_512,
    /// Triple DES encryption algorithm.
    TripleDes = winapi::CALG_3DES,
    /// Two-key triple DES encryption with effective key length equal to 112 bits.
    TripleDes112 = winapi::CALG_3DES_112,
    #[doc(hidden)]
    __ForExtensibility,
}

#[derive(Debug, Copy, Clone)]
pub enum Protocol {
    /// Secure Sockets Layer 3.0
    Ssl3,
    /// Transport Layer Security 1.0
    Tls10,
    /// Transport Layer Security 1.1
    Tls11,
    /// Transport Layer Security 1.2
    Tls12,
    #[doc(hidden)]
    __ForExtensibility,
}

impl Protocol {
    fn dword(self, direction: Direction) -> winapi::DWORD {
        match (self, direction) {
            (Protocol::Ssl3, Direction::Inbound) => winapi::SP_PROT_SSL3_SERVER,
            (Protocol::Tls10, Direction::Inbound) => winapi::SP_PROT_TLS1_0_SERVER,
            (Protocol::Tls11, Direction::Inbound) => winapi::SP_PROT_TLS1_1_SERVER,
            (Protocol::Tls12, Direction::Inbound) => winapi::SP_PROT_TLS1_2_SERVER,
            (Protocol::Ssl3, Direction::Outbound) => winapi::SP_PROT_SSL3_CLIENT,
            (Protocol::Tls10, Direction::Outbound) => winapi::SP_PROT_TLS1_0_CLIENT,
            (Protocol::Tls11, Direction::Outbound) => winapi::SP_PROT_TLS1_1_CLIENT,
            (Protocol::Tls12, Direction::Outbound) => winapi::SP_PROT_TLS1_2_CLIENT,
            (Protocol::__ForExtensibility, _) => unreachable!(),
        }
    }
}

pub struct Builder {
    supported_algorithms: Option<Vec<Algorithm>>,
    enabled_protocols: Option<Vec<Protocol>>,
}

impl Builder {
    /// Sets the algorithms supported for sessions created from this builder.
    pub fn supported_algorithms(mut self,
                                supported_algorithms: &[Algorithm])
                                -> Builder {
        self.supported_algorithms = Some(supported_algorithms.to_owned());
        self
    }

    /// Sets the protocols enabled for sessions created from this builder.
    pub fn enabled_protocols(mut self, enabled_protocols: &[Protocol]) -> Builder {
        self.enabled_protocols = Some(enabled_protocols.to_owned());
        self
    }

    pub fn acquire(&self, direction: Direction) -> io::Result<SchannelCred> {
        unsafe {
            let mut handle = mem::uninitialized();
            let mut cred_data: winapi::SCHANNEL_CRED = mem::zeroed();
            cred_data.dwVersion = winapi::SCHANNEL_CRED_VERSION;
            cred_data.dwFlags = winapi::SCH_USE_STRONG_CRYPTO;
            if let Some(ref supported_algorithms) = self.supported_algorithms {
                cred_data.cSupportedAlgs = supported_algorithms.len() as winapi::DWORD;
                cred_data.palgSupportedAlgs = supported_algorithms.as_ptr() as *mut _;
            }
            if let Some(ref enabled_protocols) = self.enabled_protocols {
                cred_data.grbitEnabledProtocols = enabled_protocols.iter()
                                                                   .map(|p| p.dword(direction))
                                                                   .fold(0, |acc, p| acc | p);
            }

            let direction = match direction {
                Direction::Inbound => winapi::SECPKG_CRED_INBOUND,
                Direction::Outbound => winapi::SECPKG_CRED_OUTBOUND,
            };

            match secur32::AcquireCredentialsHandleA(ptr::null_mut(),
                                                     UNISP_NAME.as_ptr() as *const _ as *mut _,
                                                     direction,
                                                     ptr::null_mut(),
                                                     &mut cred_data as *mut _ as *mut _,
                                                     None,
                                                     ptr::null_mut(),
                                                     &mut handle,
                                                     ptr::null_mut()) {
                winapi::SEC_E_OK => Ok(SchannelCred(handle)),
                err => Err(io::Error::from_raw_os_error(err as i32)),
            }
        }
    }
}

pub struct SchannelCred(winapi::CredHandle);

impl Drop for SchannelCred {
    fn drop(&mut self) {
        unsafe {
            secur32::FreeCredentialsHandle(&mut self.0);
        }
    }
}

impl Inner<winapi::CredHandle> for SchannelCred {
    unsafe fn from_inner(inner: winapi::CredHandle) -> SchannelCred {
        SchannelCred(inner)
    }

    fn as_inner(&self) -> winapi::CredHandle {
        self.0
    }

    fn get_mut(&mut self) -> &mut winapi::CredHandle {
        &mut self.0
    }
}

impl SchannelCred {
    pub fn builder() -> Builder {
        Builder {
            supported_algorithms: None,
            enabled_protocols: None,
        }
    }
}<commit_msg>Add checks for __ForExtensibility variants<commit_after>use winapi;
use secur32;
use std::io;
use std::mem;
use std::ptr;

use Inner;

lazy_static! {
    static ref UNISP_NAME: Vec<u8> = winapi::UNISP_NAME.bytes().chain(Some(0)).collect();
}

#[derive(Copy, Debug, Clone, PartialEq, Eq)]
pub enum Direction {
    Inbound,
    Outbound,
}

/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum Algorithm {
    /// Advanced Encryption Standard (AES).
    Aes = winapi::CALG_AES,
    /// 128 bit AES.
    Aes128 = winapi::CALG_AES_128,
    /// 192 bit AES.
    Aes192 = winapi::CALG_AES_192,
    /// 256 bit AES.
    Aes256 = winapi::CALG_AES_256,
    /// Temporary algorithm identifier for handles of Diffie-Hellman–agreed keys.
    AgreedkeyAny = winapi::CALG_AGREEDKEY_ANY,
    /// An algorithm to create a 40-bit DES key that has parity bits and zeroed key bits to make
    /// its key length 64 bits.
    CylinkMek = winapi::CALG_CYLINK_MEK,
    /// DES encryption algorithm.
    Des = winapi::CALG_DES,
    /// DESX encryption algorithm.
    Desx = winapi::CALG_DESX,
    /// Diffie-Hellman ephemeral key exchange algorithm.
    DhEphem = winapi::CALG_DH_EPHEM,
    /// Diffie-Hellman store and forward key exchange algorithm.
    DhSf = winapi::CALG_DH_SF,
    /// DSA public key signature algorithm.
    DssSign = winapi::CALG_DSS_SIGN,
    /// Elliptic curve Diffie-Hellman key exchange algorithm.
    Ecdh = winapi::CALG_ECDH,
    // https://github.com/retep998/winapi-rs/issues/287
    // /// Ephemeral elliptic curve Diffie-Hellman key exchange algorithm.
    // EcdhEphem = winapi::CALG_ECDH_EPHEM,
    /// Elliptic curve digital signature algorithm.
    Ecdsa = winapi::CALG_ECDSA,
    /// One way function hashing algorithm.
    HashReplaceOwf = winapi::CALG_HASH_REPLACE_OWF,
    /// Hughes MD5 hashing algorithm.
    HughesMd5 = winapi::CALG_HUGHES_MD5,
    /// HMAC keyed hash algorithm.
    Hmac = winapi::CALG_HMAC,
    /// MAC keyed hash algorithm.
    Mac = winapi::CALG_MAC,
    /// MD2 hashing algorithm.
    Md2 = winapi::CALG_MD2,
    /// MD4 hashing algorithm.
    Md4 = winapi::CALG_MD4,
    /// MD5 hashing algorithm.
    Md5 = winapi::CALG_MD5,
    /// No signature algorithm..
    NoSign = winapi::CALG_NO_SIGN,
    /// RC2 block encryption algorithm.
    Rc2 = winapi::CALG_RC2,
    /// RC4 stream encryption algorithm.
    Rc4 = winapi::CALG_RC4,
    /// RC5 block encryption algorithm.
    Rc5 = winapi::CALG_RC5,
    /// RSA public key exchange algorithm.
    RsaKeyx = winapi::CALG_RSA_KEYX,
    /// RSA public key signature algorithm.
    RsaSign = winapi::CALG_RSA_SIGN,
    /// SHA hashing algorithm.
    Sha1 = winapi::CALG_SHA1,
    /// 256 bit SHA hashing algorithm.
    Sha256 = winapi::CALG_SHA_256,
    /// 384 bit SHA hashing algorithm.
    Sha384 = winapi::CALG_SHA_384,
    /// 512 bit SHA hashing algorithm.
    Sha512 = winapi::CALG_SHA_512,
    /// Triple DES encryption algorithm.
    TripleDes = winapi::CALG_3DES,
    /// Two-key triple DES encryption with effective key length equal to 112 bits.
    TripleDes112 = winapi::CALG_3DES_112,
    #[doc(hidden)]
    __ForExtensibility,
}

#[derive(Debug, Copy, Clone)]
pub enum Protocol {
    /// Secure Sockets Layer 3.0
    Ssl3,
    /// Transport Layer Security 1.0
    Tls10,
    /// Transport Layer Security 1.1
    Tls11,
    /// Transport Layer Security 1.2
    Tls12,
    #[doc(hidden)]
    __ForExtensibility,
}

impl Protocol {
    fn dword(self, direction: Direction) -> winapi::DWORD {
        match (self, direction) {
            (Protocol::Ssl3, Direction::Inbound) => winapi::SP_PROT_SSL3_SERVER,
            (Protocol::Tls10, Direction::Inbound) => winapi::SP_PROT_TLS1_0_SERVER,
            (Protocol::Tls11, Direction::Inbound) => winapi::SP_PROT_TLS1_1_SERVER,
            (Protocol::Tls12, Direction::Inbound) => winapi::SP_PROT_TLS1_2_SERVER,
            (Protocol::Ssl3, Direction::Outbound) => winapi::SP_PROT_SSL3_CLIENT,
            (Protocol::Tls10, Direction::Outbound) => winapi::SP_PROT_TLS1_0_CLIENT,
            (Protocol::Tls11, Direction::Outbound) => winapi::SP_PROT_TLS1_1_CLIENT,
            (Protocol::Tls12, Direction::Outbound) => winapi::SP_PROT_TLS1_2_CLIENT,
            (Protocol::__ForExtensibility, _) => unreachable!(),
        }
    }
}

pub struct Builder {
    supported_algorithms: Option<Vec<Algorithm>>,
    enabled_protocols: Option<Vec<Protocol>>,
}

impl Builder {
    /// Sets the algorithms supported for sessions created from this builder.
    pub fn supported_algorithms(mut self,
                                supported_algorithms: &[Algorithm])
                                -> Builder {
        assert!(supported_algorithms.iter()
                                    .all(|a| {
                                        match *a {
                                            Algorithm::__ForExtensibility => false,
                                            _ => true
                                        }
                                    }));
        self.supported_algorithms = Some(supported_algorithms.to_owned());
        self
    }

    /// Sets the protocols enabled for sessions created from this builder.
    pub fn enabled_protocols(mut self, enabled_protocols: &[Protocol]) -> Builder {
        assert!(enabled_protocols.iter()
                                 .all(|a| {
                                    match *a {
                                        Protocol::__ForExtensibility => false,
                                        _ => true
                                    }
                                 }));
        self.enabled_protocols = Some(enabled_protocols.to_owned());
        self
    }

    pub fn acquire(&self, direction: Direction) -> io::Result<SchannelCred> {
        unsafe {
            let mut handle = mem::uninitialized();
            let mut cred_data: winapi::SCHANNEL_CRED = mem::zeroed();
            cred_data.dwVersion = winapi::SCHANNEL_CRED_VERSION;
            cred_data.dwFlags = winapi::SCH_USE_STRONG_CRYPTO;
            if let Some(ref supported_algorithms) = self.supported_algorithms {
                cred_data.cSupportedAlgs = supported_algorithms.len() as winapi::DWORD;
                cred_data.palgSupportedAlgs = supported_algorithms.as_ptr() as *mut _;
            }
            if let Some(ref enabled_protocols) = self.enabled_protocols {
                cred_data.grbitEnabledProtocols = enabled_protocols.iter()
                                                                   .map(|p| p.dword(direction))
                                                                   .fold(0, |acc, p| acc | p);
            }

            let direction = match direction {
                Direction::Inbound => winapi::SECPKG_CRED_INBOUND,
                Direction::Outbound => winapi::SECPKG_CRED_OUTBOUND,
            };

            match secur32::AcquireCredentialsHandleA(ptr::null_mut(),
                                                     UNISP_NAME.as_ptr() as *const _ as *mut _,
                                                     direction,
                                                     ptr::null_mut(),
                                                     &mut cred_data as *mut _ as *mut _,
                                                     None,
                                                     ptr::null_mut(),
                                                     &mut handle,
                                                     ptr::null_mut()) {
                winapi::SEC_E_OK => Ok(SchannelCred(handle)),
                err => Err(io::Error::from_raw_os_error(err as i32)),
            }
        }
    }
}

pub struct SchannelCred(winapi::CredHandle);

impl Drop for SchannelCred {
    fn drop(&mut self) {
        unsafe {
            secur32::FreeCredentialsHandle(&mut self.0);
        }
    }
}

impl Inner<winapi::CredHandle> for SchannelCred {
    unsafe fn from_inner(inner: winapi::CredHandle) -> SchannelCred {
        SchannelCred(inner)
    }

    fn as_inner(&self) -> winapi::CredHandle {
        self.0
    }

    fn get_mut(&mut self) -> &mut winapi::CredHandle {
        &mut self.0
    }
}

impl SchannelCred {
    pub fn builder() -> Builder {
        Builder {
            supported_algorithms: None,
            enabled_protocols: None,
        }
    }
}<|endoftext|>