<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::state_replication::StateComputer;
use anyhow::{Error, Result};
use consensus_types::block::Block;
use executor_types::{BlockExecutor, StateComputeResult};
use libra_crypto::HashValue;
use libra_logger::prelude::*;
use libra_metrics::monitor;
use libra_types::{ledger_info::LedgerInfoWithSignatures, transaction::Transaction};
use state_synchronizer::StateSyncClient;
use std::{
    boxed::Box,
    sync::{Arc, Mutex},
};

/// Basic communication with the Execution module;
/// implements StateComputer traits.
pub struct ExecutionProxy {
    execution_correctness_client: Mutex<Box<dyn BlockExecutor + Send + Sync>>,
    synchronizer: Arc<StateSyncClient>,
}

impl ExecutionProxy {
    pub fn new(
        execution_correctness_client: Box<dyn BlockExecutor + Send + Sync>,
        synchronizer: Arc<StateSyncClient>,
    ) -> Self {
        Self {
            execution_correctness_client: Mutex::new(execution_correctness_client),
            synchronizer,
        }
    }

    fn transactions_from_block(block: &Block) -> Vec<Transaction> {
        let mut transactions = vec![Transaction::BlockMetadata(block.into())];
        transactions.extend(
            block
                .payload()
                .unwrap_or(&vec![])
                .iter()
                .map(|txn| Transaction::UserTransaction(txn.clone())),
        );
        transactions
    }
}

#[async_trait::async_trait]
impl StateComputer for ExecutionProxy {
    fn compute(
        &self,
        // The block to be executed.
        block: &Block,
        // The parent block id.
        parent_block_id: HashValue,
    ) -> Result<StateComputeResult> {
        debug!(
            "Executing block {:x}. Parent: {:x}.",
            block.id(),
            block.parent_id(),
        );

        // TODO: figure out error handling for the prologue txn
        monitor!(
            "execute_block",
            self.execution_correctness_client
                .lock()
                .unwrap()
                .execute_block(
                    (block.id(), Self::transactions_from_block(block)),
                    parent_block_id,
                )
                .map_err(Error::from)
        )
    }

    /// Send a successful commit. A future is fulfilled when the state is finalized.
    async fn commit(
        &self,
        block_ids: Vec<HashValue>,
        finality_proof: LedgerInfoWithSignatures,
    ) -> Result<()> {
        let (committed_txns, reconfig_events) = monitor!(
            "commit_block",
            self.execution_correctness_client
                .lock()
                .unwrap()
                .commit_blocks(block_ids, finality_proof)?
        );
        if let Err(e) = self
            .synchronizer
            .commit(committed_txns, reconfig_events)
            .await
        {
            error!("failed to notify state synchronizer: {:?}", e);
        }
        Ok(())
    }

    /// Synchronize to a commit that not present locally.
    async fn sync_to(&self, target: LedgerInfoWithSignatures) -> Result<()> {
        // Here to start to do state synchronization where ChunkExecutor inside will
        // process chunks and commit to Storage. However, after block execution and
        // commitments, the the sync state of ChunkExecutor may be not up to date so
        // it is required to reset the cache of ChunkExecutor in StateSynchronizer
        // when requested to sync.
        let res = monitor!("sync_to", self.synchronizer.sync_to(target).await);
        // Similarily, after the state synchronization, we have to reset the cache
        // of BlockExecutor to guarantee the latest committed state is up to date.
        self.execution_correctness_client.lock().unwrap().reset()?;
        res
    }
}
<commit_msg>[consensus] add counter for state sync notification<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::state_replication::StateComputer;
use anyhow::{Error, Result};
use consensus_types::block::Block;
use executor_types::{BlockExecutor, StateComputeResult};
use libra_crypto::HashValue;
use libra_logger::prelude::*;
use libra_metrics::monitor;
use libra_types::{ledger_info::LedgerInfoWithSignatures, transaction::Transaction};
use state_synchronizer::StateSyncClient;
use std::{
    boxed::Box,
    sync::{Arc, Mutex},
};

/// Basic communication with the Execution module;
/// implements StateComputer traits.
pub struct ExecutionProxy {
    execution_correctness_client: Mutex<Box<dyn BlockExecutor + Send + Sync>>,
    synchronizer: Arc<StateSyncClient>,
}

impl ExecutionProxy {
    pub fn new(
        execution_correctness_client: Box<dyn BlockExecutor + Send + Sync>,
        synchronizer: Arc<StateSyncClient>,
    ) -> Self {
        Self {
            execution_correctness_client: Mutex::new(execution_correctness_client),
            synchronizer,
        }
    }

    fn transactions_from_block(block: &Block) -> Vec<Transaction> {
        let mut transactions = vec![Transaction::BlockMetadata(block.into())];
        transactions.extend(
            block
                .payload()
                .unwrap_or(&vec![])
                .iter()
                .map(|txn| Transaction::UserTransaction(txn.clone())),
        );
        transactions
    }
}

#[async_trait::async_trait]
impl StateComputer for ExecutionProxy {
    fn compute(
        &self,
        // The block to be executed.
        block: &Block,
        // The parent block id.
        parent_block_id: HashValue,
    ) -> Result<StateComputeResult> {
        debug!(
            "Executing block {:x}. Parent: {:x}.",
            block.id(),
            block.parent_id(),
        );

        // TODO: figure out error handling for the prologue txn
        monitor!(
            "execute_block",
            self.execution_correctness_client
                .lock()
                .unwrap()
                .execute_block(
                    (block.id(), Self::transactions_from_block(block)),
                    parent_block_id,
                )
                .map_err(Error::from)
        )
    }

    /// Send a successful commit. A future is fulfilled when the state is finalized.
    async fn commit(
        &self,
        block_ids: Vec<HashValue>,
        finality_proof: LedgerInfoWithSignatures,
    ) -> Result<()> {
        let (committed_txns, reconfig_events) = monitor!(
            "commit_block",
            self.execution_correctness_client
                .lock()
                .unwrap()
                .commit_blocks(block_ids, finality_proof)?
        );
        if let Err(e) = monitor!(
            "notify_state_sync",
            self.synchronizer
                .commit(committed_txns, reconfig_events)
                .await
        ) {
            error!("failed to notify state synchronizer: {:?}", e);
        }
        Ok(())
    }

    /// Synchronize to a commit that not present locally.
    async fn sync_to(&self, target: LedgerInfoWithSignatures) -> Result<()> {
        // Here to start to do state synchronization where ChunkExecutor inside will
        // process chunks and commit to Storage. However, after block execution and
        // commitments, the the sync state of ChunkExecutor may be not up to date so
        // it is required to reset the cache of ChunkExecutor in StateSynchronizer
        // when requested to sync.
        let res = monitor!("sync_to", self.synchronizer.sync_to(target).await);
        // Similarily, after the state synchronization, we have to reset the cache
        // of BlockExecutor to guarantee the latest committed state is up to date.
        self.execution_correctness_client.lock().unwrap().reset()?;
        res
    }
}
<|endoftext|>


<commit_before>use std::ffi::{CString, self};
use std::mem;
use std::str;

use objc::{encode, Encode, Id};

use {INSCopying, INSObject};

pub trait INSValue : INSObject {
    type Value: Copy + Encode;

    fn value(&self) -> Self::Value {
        assert!(self.encoding() == encode::<Self::Value>());
        unsafe {
            let value = mem::uninitialized::<Self::Value>();
            let _: () = msg_send![self, getValue:&value];
            value
        }
    }

    fn encoding(&self) -> &str {
        unsafe {
            let result: *const i8 = msg_send![self, objCType];
            let bytes = ffi::c_str_to_bytes(&result);
            let s = str::from_utf8(bytes).unwrap();
            mem::transmute(s)
        }
    }

    fn from_value(value: &Self::Value) -> Id<Self> {
        let cls = <Self as INSObject>::class();
        let encoding = CString::from_slice(encode::<Self::Value>().as_bytes());
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, initWithBytes:value
                                                     objCType:encoding.as_ptr()];
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSValue<T>);

impl<T: Copy + Encode> INSValue for NSValue<T> {
    type Value = T;
}

impl<T> INSCopying for NSValue<T> {
    type Output = NSValue<T>;
}

#[cfg(test)]
mod tests {
    use objc::{encode, Id};
    use {INSValue, NSValue};

    #[test]
    fn test_value() {
        let val: Id<NSValue<uint>> = INSValue::from_value(&13);
        assert!(val.value() == 13);
        assert!(val.encoding() == encode::<uint>());
    }
}
<commit_msg>Made INSValue's from_value take by value.<commit_after>use std::ffi::{CString, self};
use std::mem;
use std::str;

use objc::{encode, Encode, Id};

use {INSCopying, INSObject};

pub trait INSValue : INSObject {
    type Value: Copy + Encode;

    fn value(&self) -> Self::Value {
        assert!(self.encoding() == encode::<Self::Value>());
        unsafe {
            let value = mem::uninitialized::<Self::Value>();
            let _: () = msg_send![self, getValue:&value];
            value
        }
    }

    fn encoding(&self) -> &str {
        unsafe {
            let result: *const i8 = msg_send![self, objCType];
            let bytes = ffi::c_str_to_bytes(&result);
            let s = str::from_utf8(bytes).unwrap();
            mem::transmute(s)
        }
    }

    fn from_value(value: Self::Value) -> Id<Self> {
        let cls = <Self as INSObject>::class();
        let encoding = CString::from_slice(encode::<Self::Value>().as_bytes());
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, initWithBytes:&value
                                                     objCType:encoding.as_ptr()];
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSValue<T>);

impl<T: Copy + Encode> INSValue for NSValue<T> {
    type Value = T;
}

impl<T> INSCopying for NSValue<T> {
    type Output = NSValue<T>;
}

#[cfg(test)]
mod tests {
    use objc::{encode, Id};
    use {INSValue, NSValue};

    #[test]
    fn test_value() {
        let val: Id<NSValue<u32>> = INSValue::from_value(13);
        assert!(val.value() == 13);
        assert!(val.encoding() == encode::<u32>());
    }
}
<|endoftext|>


<commit_before>use std::ascii;
use std::fs::File;
use std::io::{self, BufRead};
use std::path::{Path, PathBuf};

use csv;
use fst::{IntoStreamer, Streamer};
use fst::raw::Output;

use Error;

pub fn escape_input(b: u8) -> String {
    String::from_utf8(ascii::escape_default(b).collect::<Vec<_>>()).unwrap()
}

pub fn get_buf_reader<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<io::BufReader<Box<io::Read + Send + Sync + 'static>>> {
    Ok(io::BufReader::new(try!(get_reader(path))))
}

pub fn get_buf_writer<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<io::BufWriter<Box<io::Write + Send + Sync + 'static>>> {
    Ok(io::BufWriter::new(try!(get_writer(path))))
}

pub fn get_reader<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<Box<io::Read + Send + Sync + 'static>> {
    Ok(match to_stdio(path) {
        None => Box::new(io::stdin()),
        Some(path) => Box::new(try!(File::open(path))),
    })
}

pub fn get_writer<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<Box<io::Write + Send + Sync + 'static>> {
    Ok(match to_stdio(path) {
        None => Box::new(io::stdout()),
        Some(path) => Box::new(try!(File::create(path))),
    })
}

fn to_stdio<T: AsRef<Path>>(path: Option<T>) -> Option<PathBuf> {
    match path {
        None => None,
        Some(s) => {
            if s.as_ref().to_string_lossy() == "-" {
                None
            } else {
                Some(s.as_ref().to_path_buf())
            }
        }
    }
}

pub fn print_stream<'f, W, I, S>(
    mut wtr: W,
    outputs: bool,
    stream: I,
) -> Result<(), Error>
where W: io::Write,
      I: for<'a> IntoStreamer<'a, Into=S, Item=(&'a [u8], Output)>,
      S: 'f + for<'a> Streamer<'a, Item=(&'a [u8], Output)> {
    let mut stream = stream.into_stream();
    if outputs {
        let mut wtr = csv::Writer::from_writer(wtr);
        while let Some((k, v)) = stream.next() {
            let v = v.value().to_string();
            try!(wtr.write_record((&[k, v.as_bytes()]).iter()));
        }
        wtr.flush().map_err(From::from)
    } else {
        while let Some((k, _)) = stream.next() {
            try!(wtr.write_all(k));
            try!(wtr.write_all(b"\n"));
        }
        wtr.flush().map_err(From::from)
    }
}

pub struct ConcatLines {
    inputs: Vec<PathBuf>,
    cur: Option<Lines>,
}

type Lines = io::Lines<io::BufReader<Box<io::Read + Send + Sync + 'static>>>;

impl ConcatLines {
    pub fn new(mut inputs: Vec<PathBuf>) -> ConcatLines {
        inputs.reverse(); // treat it as a stack
        ConcatLines { inputs: inputs, cur: None }
    }
}

impl Iterator for ConcatLines {
    type Item = io::Result<String>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.cur.is_none() {
                match self.inputs.pop() {
                    None => return None,
                    Some(path) => {
                        let rdr = match get_buf_reader(Some(path)) {
                            Err(err) => return Some(Err(err)),
                            Ok(rdr) => rdr,
                        };
                        self.cur = Some(rdr.lines());
                    }
                }
            }
            match self.cur.as_mut().and_then(|lines| Iterator::next(lines)) {
                None => self.cur = None,
                Some(r) => return Some(r),
            }
        }
    }
}

pub struct ConcatCsv {
    inputs: Vec<PathBuf>,
    cur: Option<Rows>,
}

type Reader = Box<io::Read + Send + Sync + 'static>;
type Rows = csv::DeserializeRecordsIntoIter<Reader, (String, u64)>;

impl ConcatCsv {
    pub fn new(mut inputs: Vec<PathBuf>) -> ConcatCsv {
        inputs.reverse(); // treat it as a stack
        ConcatCsv { inputs: inputs, cur: None }
    }

    fn read_row(&mut self) -> Option<Result<(String, u64), Error>> {
        let mut rdr = match self.cur {
            None => return None,
            Some(ref mut rdr) => rdr,
        };
        match rdr.next() {
            Some(Ok((k, v))) => Some(Ok((k, v))),
            Some(Err(err)) => Some(Err(From::from(err))),
            None => None,
        }
    }
}

impl Iterator for ConcatCsv {
    type Item = Result<(String, u64), Error>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.cur.is_none() {
                match self.inputs.pop() {
                    None => return None,
                    Some(path) => {
                        let rdr = match get_reader(Some(path)) {
                            Err(err) => return Some(Err(From::from(err))),
                            Ok(rdr) => rdr,
                        };
                        let csvrdr = csv::Reader::from_reader(rdr);
                        self.cur = Some(csvrdr.into_deserialize());
                    }
                }
            }
            match self.read_row() {
                None => self.cur = None,
                Some(r) => return Some(r),
            }
        }
    }
}
<commit_msg>fst-bin: remove unnecessary `mut` binding<commit_after>use std::ascii;
use std::fs::File;
use std::io::{self, BufRead};
use std::path::{Path, PathBuf};

use csv;
use fst::{IntoStreamer, Streamer};
use fst::raw::Output;

use Error;

pub fn escape_input(b: u8) -> String {
    String::from_utf8(ascii::escape_default(b).collect::<Vec<_>>()).unwrap()
}

pub fn get_buf_reader<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<io::BufReader<Box<io::Read + Send + Sync + 'static>>> {
    Ok(io::BufReader::new(try!(get_reader(path))))
}

pub fn get_buf_writer<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<io::BufWriter<Box<io::Write + Send + Sync + 'static>>> {
    Ok(io::BufWriter::new(try!(get_writer(path))))
}

pub fn get_reader<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<Box<io::Read + Send + Sync + 'static>> {
    Ok(match to_stdio(path) {
        None => Box::new(io::stdin()),
        Some(path) => Box::new(try!(File::open(path))),
    })
}

pub fn get_writer<T: AsRef<Path>>(
    path: Option<T>,
) -> io::Result<Box<io::Write + Send + Sync + 'static>> {
    Ok(match to_stdio(path) {
        None => Box::new(io::stdout()),
        Some(path) => Box::new(try!(File::create(path))),
    })
}

fn to_stdio<T: AsRef<Path>>(path: Option<T>) -> Option<PathBuf> {
    match path {
        None => None,
        Some(s) => {
            if s.as_ref().to_string_lossy() == "-" {
                None
            } else {
                Some(s.as_ref().to_path_buf())
            }
        }
    }
}

pub fn print_stream<'f, W, I, S>(
    mut wtr: W,
    outputs: bool,
    stream: I,
) -> Result<(), Error>
where W: io::Write,
      I: for<'a> IntoStreamer<'a, Into=S, Item=(&'a [u8], Output)>,
      S: 'f + for<'a> Streamer<'a, Item=(&'a [u8], Output)> {
    let mut stream = stream.into_stream();
    if outputs {
        let mut wtr = csv::Writer::from_writer(wtr);
        while let Some((k, v)) = stream.next() {
            let v = v.value().to_string();
            try!(wtr.write_record((&[k, v.as_bytes()]).iter()));
        }
        wtr.flush().map_err(From::from)
    } else {
        while let Some((k, _)) = stream.next() {
            try!(wtr.write_all(k));
            try!(wtr.write_all(b"\n"));
        }
        wtr.flush().map_err(From::from)
    }
}

pub struct ConcatLines {
    inputs: Vec<PathBuf>,
    cur: Option<Lines>,
}

type Lines = io::Lines<io::BufReader<Box<io::Read + Send + Sync + 'static>>>;

impl ConcatLines {
    pub fn new(mut inputs: Vec<PathBuf>) -> ConcatLines {
        inputs.reverse(); // treat it as a stack
        ConcatLines { inputs: inputs, cur: None }
    }
}

impl Iterator for ConcatLines {
    type Item = io::Result<String>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.cur.is_none() {
                match self.inputs.pop() {
                    None => return None,
                    Some(path) => {
                        let rdr = match get_buf_reader(Some(path)) {
                            Err(err) => return Some(Err(err)),
                            Ok(rdr) => rdr,
                        };
                        self.cur = Some(rdr.lines());
                    }
                }
            }
            match self.cur.as_mut().and_then(|lines| Iterator::next(lines)) {
                None => self.cur = None,
                Some(r) => return Some(r),
            }
        }
    }
}

pub struct ConcatCsv {
    inputs: Vec<PathBuf>,
    cur: Option<Rows>,
}

type Reader = Box<io::Read + Send + Sync + 'static>;
type Rows = csv::DeserializeRecordsIntoIter<Reader, (String, u64)>;

impl ConcatCsv {
    pub fn new(mut inputs: Vec<PathBuf>) -> ConcatCsv {
        inputs.reverse(); // treat it as a stack
        ConcatCsv { inputs: inputs, cur: None }
    }

    fn read_row(&mut self) -> Option<Result<(String, u64), Error>> {
        let rdr = match self.cur {
            None => return None,
            Some(ref mut rdr) => rdr,
        };
        match rdr.next() {
            Some(Ok((k, v))) => Some(Ok((k, v))),
            Some(Err(err)) => Some(Err(From::from(err))),
            None => None,
        }
    }
}

impl Iterator for ConcatCsv {
    type Item = Result<(String, u64), Error>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.cur.is_none() {
                match self.inputs.pop() {
                    None => return None,
                    Some(path) => {
                        let rdr = match get_reader(Some(path)) {
                            Err(err) => return Some(Err(From::from(err))),
                            Ok(rdr) => rdr,
                        };
                        let csvrdr = csv::Reader::from_reader(rdr);
                        self.cur = Some(csvrdr.into_deserialize());
                    }
                }
            }
            match self.read_row() {
                None => self.cur = None,
                Some(r) => return Some(r),
            }
        }
    }
}
<|endoftext|>


<commit_before>const EXPECTED: &str = "\
cxxbridge $VERSION
David Tolnay <dtolnay@gmail.com>
https://github.com/dtolnay/cxx

USAGE:
    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
    cxxbridge --header                Emit \"rust/cxx.h\" header to stdout

ARGS:
    <input>
            Input Rust source file containing #[cxx::bridge].

OPTIONS:
        --cxx-impl-annotations <annotation>
            Optional annotation for implementations of C++ function wrappers
            that may be exposed to Rust. You may for example need to provide
            __declspec(dllexport) or __attribute__((visibility(\"default\")))
            if Rust code from one shared object or executable depends on
            these C++ functions in another.

    -h, --help
            Print help information.

        --header
            Emit header with declarations only. Optional if using `-o` with
            a path ending in `.h`.

    -i, --include <include>
            Any additional headers to #include. The cxxbridge tool does not
            parse or even require the given paths to exist; they simply go
            into the generated C++ code as #include lines.

    -o, --output <output>
            Path of file to write as output. Output goes to stdout if -o is
            not specified.

    -V, --version
            Print version information.
";

#[test]
fn test_help() {
    let mut app = super::app();
    let mut out = Vec::new();
    app.write_long_help(&mut out).unwrap();
    let help = String::from_utf8(out).unwrap();
    let version = option_env!("CARGO_PKG_VERSION").unwrap_or_default();
    let expected = EXPECTED.replace("$VERSION", version);
    assert_eq!(help, expected);
}

#[test]
fn test_cli() {
    let app = super::app();
    app.debug_assert();
}
<commit_msg>Add --cfg to cli help test<commit_after>const EXPECTED: &str = "\
cxxbridge $VERSION
David Tolnay <dtolnay@gmail.com>
https://github.com/dtolnay/cxx

USAGE:
    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
    cxxbridge --header                Emit \"rust/cxx.h\" header to stdout

ARGS:
    <input>
            Input Rust source file containing #[cxx::bridge].

OPTIONS:
        --cfg <name=\"value\" | name[=true] | name=false>
            Compilation configuration matching what will be used to build
            the Rust side of the bridge.

        --cxx-impl-annotations <annotation>
            Optional annotation for implementations of C++ function wrappers
            that may be exposed to Rust. You may for example need to provide
            __declspec(dllexport) or __attribute__((visibility(\"default\")))
            if Rust code from one shared object or executable depends on
            these C++ functions in another.

    -h, --help
            Print help information.

        --header
            Emit header with declarations only. Optional if using `-o` with
            a path ending in `.h`.

    -i, --include <include>
            Any additional headers to #include. The cxxbridge tool does not
            parse or even require the given paths to exist; they simply go
            into the generated C++ code as #include lines.

    -o, --output <output>
            Path of file to write as output. Output goes to stdout if -o is
            not specified.

    -V, --version
            Print version information.
";

#[test]
fn test_help() {
    let mut app = super::app();
    let mut out = Vec::new();
    app.write_long_help(&mut out).unwrap();
    let help = String::from_utf8(out).unwrap();
    let version = option_env!("CARGO_PKG_VERSION").unwrap_or_default();
    let expected = EXPECTED.replace("$VERSION", version);
    assert_eq!(help, expected);
}

#[test]
fn test_cli() {
    let app = super::app();
    app.debug_assert();
}
<|endoftext|>


<commit_before>extern crate gl;
extern crate glfw;
extern crate time;

use gl::types::*;
use glfw::{Context, OpenGlProfileHint, WindowHint, WindowMode};
use std::mem;
use std::ptr;

macro_rules! gl_str {
    ($string_literal:expr) => (concat!($string_literal, '\0').as_bytes().as_ptr() as *const GLchar)
}

const VERTEX_SHADER_SOURCE: &'static str = "
    #version 150

    in vec2 position;
    in vec3 color;

    out vec3 Color;

    void main() {
        Color = color;
        gl_Position = vec4(position, 0.0, 1.0);
    }
";

const FRAGMENT_SHADER_SOURCE: &'static str = "
    #version 150

    in vec3 Color;

    out vec4 out_color;

    void main() {
        out_color = vec4(Color, 1.0);
    }
";

#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(C, packed)]
struct Vertex {
    // Position.
    x: GLfloat, y: GLfloat,

    // Color.
    r: GLfloat, g: GLfloat, b: GLfloat,
}

static VERTICES: [Vertex; 4] = [
    Vertex { x: -0.5, y:  0.5, r: 1.0, g: 0.0, b: 0.0 }, // Top-left
    Vertex { x:  0.5, y:  0.5, r: 0.0, g: 1.0, b: 0.0 }, // Top-right
    Vertex { x:  0.5, y: -0.5, r: 0.0, g: 0.0, b: 1.0 }, // Bottom-right
    Vertex { x: -0.5, y: -0.5, r: 1.0, g: 1.0, b: 1.0 }, // Bottom-left
];

static ELEMENTS: [GLuint; 6] = [
    0, 1, 2, // Top-right triangle
    2, 3, 0, // Bottom-left triangle
];

unsafe fn compile_shader(shader_type: GLenum, source: &str) -> Result<GLuint, String> {
    let shader = gl::CreateShader(shader_type);
    let source_ptr = source.as_bytes().as_ptr() as *const GLchar;
    let source_len = source.len() as GLint;
    gl::ShaderSource(shader, 1, &source_ptr, &source_len);
    gl::CompileShader(shader);

    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    if status == gl::TRUE as GLint {
        Ok(shader)
    } else {
        let mut log_len = 0;
        gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut log_len);
        if log_len == 0 { return Err(String::new()) }

        let mut buf = Vec::with_capacity(log_len as usize);
        buf.set_len(log_len as usize - 1); // Subtract 1 to ignore the trailing null.
        gl::GetShaderInfoLog(shader, log_len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);

        Err(String::from_utf8_lossy(&buf).into_owned())
    }
}

fn main() {
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(WindowHint::ContextVersion(3, 2));
    glfw.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
    glfw.window_hint(WindowHint::OpenGlForwardCompat(true));
    glfw.window_hint(WindowHint::Resizable(false));

    let (mut window, events) = glfw.create_window(800, 600, "OpenGL", WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    // Listen for keyboard events on this window.
    window.set_key_polling(true);

    // Make this window's OpenGL context the current context. This must be done before calling
    // `gl::load_with`.
    window.make_current();

    // Load OpenGL function pointers.
    gl::load_with(|symbol| window.get_proc_address(symbol));

    let vertex_shader;
    let fragment_shader;
    let shader_program;
    let mut vao = 0;
    let mut vbo = 0;
    let mut ebo = 0;

    unsafe {
        // Create a vertex array object.
        gl::GenVertexArrays(1, &mut vao);
        gl::BindVertexArray(vao);

        // Create a vertex buffer object and copy the vertex data to it.
        gl::GenBuffers(1, &mut vbo);
        gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
        gl::BufferData(gl::ARRAY_BUFFER,
                       mem::size_of_val(&VERTICES) as GLsizeiptr,
                       VERTICES.as_ptr() as *const GLvoid,
                       gl::STATIC_DRAW);

        // Create an element buffer object and copy the element data to it.
        gl::GenBuffers(1, &mut ebo);
        gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
        gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
                       mem::size_of_val(&ELEMENTS) as GLsizeiptr,
                       ELEMENTS.as_ptr() as *const GLvoid,
                       gl::STATIC_DRAW);

        // Compile the vertex and fragment shaders.
        vertex_shader = compile_shader(gl::VERTEX_SHADER, VERTEX_SHADER_SOURCE).unwrap();
        fragment_shader = compile_shader(gl::FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE).unwrap();

        // Link the vertex and fragment shaders into a shader program.
        shader_program = gl::CreateProgram();
        gl::AttachShader(shader_program, vertex_shader);
        gl::AttachShader(shader_program, fragment_shader);
        gl::BindFragDataLocation(shader_program, 0, gl_str!("out_color"));
        gl::LinkProgram(shader_program);
        gl::UseProgram(shader_program);

        // Specify the layout of the vertex data.
        let position_attrib = gl::GetAttribLocation(shader_program, gl_str!("position"));
        gl::EnableVertexAttribArray(position_attrib as GLuint);
        gl::VertexAttribPointer(position_attrib as GLuint, 2, gl::FLOAT, gl::FALSE,
                                mem::size_of::<Vertex>() as GLint, ptr::null());

        let position_attrib = gl::GetAttribLocation(shader_program, gl_str!("color"));
        gl::EnableVertexAttribArray(position_attrib as GLuint);
        gl::VertexAttribPointer(position_attrib as GLuint, 3, gl::FLOAT, gl::FALSE,
                                mem::size_of::<Vertex>() as GLint,
                                (2 * mem::size_of::<GLfloat>()) as *const GLvoid);
    }

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }

        unsafe {
            // Clear the screen to black.
            gl::ClearColor(0.0, 0.0, 0.0, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);

            // Draw the triangles described by the elements array.
            gl::DrawElements(gl::TRIANGLES, ELEMENTS.len() as GLint, gl::UNSIGNED_INT,
                             ptr::null());
        }

        window.swap_buffers();
    }

    unsafe {
        gl::DeleteProgram(shader_program);
        gl::DeleteShader(fragment_shader);
        gl::DeleteShader(vertex_shader);
        gl::DeleteBuffers(1, &vbo);
        gl::DeleteVertexArrays(1, &vao);
    }
}

fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
    use glfw::{Action, Key, WindowEvent};

    match event {
        WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
            window.set_should_close(true);
        },
        _ => {},
    }
}
<commit_msg>Add simple checkerboard texture blended with colors.<commit_after>extern crate gl;
extern crate glfw;
extern crate time;

use gl::types::*;
use glfw::{Context, OpenGlProfileHint, WindowHint, WindowMode};
use std::mem;
use std::ptr;

macro_rules! gl_str {
    ($string_literal:expr) => (concat!($string_literal, '\0').as_bytes().as_ptr() as *const GLchar)
}

const VERTEX_SHADER_SOURCE: &'static str = "
    #version 150

    in vec2 position;
    in vec3 color;
    in vec2 texcoord;

    out vec3 Color;
    out vec2 Texcoord;

    void main() {
        Color = color;
        Texcoord = texcoord;
        gl_Position = vec4(position, 0.0, 1.0);
    }
";

const FRAGMENT_SHADER_SOURCE: &'static str = "
    #version 150

    in vec3 Color;
    in vec2 Texcoord;

    out vec4 out_color;

    uniform sampler2D tex;

    void main() {
        out_color = texture(tex, Texcoord) * vec4(Color, 1.0);
    }
";

#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(C, packed)]
struct Vertex {
    // Position.
    x: GLfloat, y: GLfloat,

    // Color.
    r: GLfloat, g: GLfloat, b: GLfloat,

    // Texture.
    s: GLfloat, t: GLfloat,
}

static VERTICES: [Vertex; 4] = [
    Vertex { x: -0.5, y:  0.5, r: 1.0, g: 0.0, b: 0.0, s: 0.0, t: 0.0 }, // Top-left
    Vertex { x:  0.5, y:  0.5, r: 0.0, g: 1.0, b: 0.0, s: 1.0, t: 0.0 }, // Top-right
    Vertex { x:  0.5, y: -0.5, r: 0.0, g: 0.0, b: 1.0, s: 1.0, t: 1.0 }, // Bottom-right
    Vertex { x: -0.5, y: -0.5, r: 1.0, g: 1.0, b: 1.0, s: 0.0, t: 1.0 }, // Bottom-left
];

static ELEMENTS: [GLuint; 6] = [
    0, 1, 2, // Top-right triangle
    2, 3, 0, // Bottom-left triangle
];

unsafe fn compile_shader(shader_type: GLenum, source: &str) -> Result<GLuint, String> {
    let shader = gl::CreateShader(shader_type);
    let source_ptr = source.as_bytes().as_ptr() as *const GLchar;
    let source_len = source.len() as GLint;
    gl::ShaderSource(shader, 1, &source_ptr, &source_len);
    gl::CompileShader(shader);

    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    if status == gl::TRUE as GLint {
        Ok(shader)
    } else {
        let mut log_len = 0;
        gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut log_len);
        if log_len == 0 { return Err(String::new()) }

        let mut buf = Vec::with_capacity(log_len as usize);
        buf.set_len(log_len as usize - 1); // Subtract 1 to ignore the trailing null.
        gl::GetShaderInfoLog(shader, log_len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);

        Err(String::from_utf8_lossy(&buf).into_owned())
    }
}

fn main() {
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(WindowHint::ContextVersion(3, 2));
    glfw.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
    glfw.window_hint(WindowHint::OpenGlForwardCompat(true));
    glfw.window_hint(WindowHint::Resizable(false));

    let (mut window, events) = glfw.create_window(800, 600, "OpenGL", WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    // Listen for keyboard events on this window.
    window.set_key_polling(true);

    // Make this window's OpenGL context the current context. This must be done before calling
    // `gl::load_with`.
    window.make_current();

    // Load OpenGL function pointers.
    gl::load_with(|symbol| window.get_proc_address(symbol));

    let vertex_shader;
    let fragment_shader;
    let shader_program;
    let mut vao = 0;
    let mut vbo = 0;
    let mut ebo = 0;
    let mut tex = 0;

    unsafe {
        // Create a vertex array object.
        gl::GenVertexArrays(1, &mut vao);
        gl::BindVertexArray(vao);

        // Create a vertex buffer object and copy the vertex data to it.
        gl::GenBuffers(1, &mut vbo);
        gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
        gl::BufferData(gl::ARRAY_BUFFER,
                       mem::size_of_val(&VERTICES) as GLsizeiptr,
                       VERTICES.as_ptr() as *const GLvoid,
                       gl::STATIC_DRAW);

        // Create an element buffer object and copy the element data to it.
        gl::GenBuffers(1, &mut ebo);
        gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
        gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
                       mem::size_of_val(&ELEMENTS) as GLsizeiptr,
                       ELEMENTS.as_ptr() as *const GLvoid,
                       gl::STATIC_DRAW);

        // Create a texture.
        gl::GenTextures(1, &mut tex);
        gl::BindTexture(gl::TEXTURE_2D, tex);
        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as GLint);
        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as GLint);
        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER,
                          gl::NEAREST as GLint);
        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER,
                          gl::NEAREST as GLint);

        // Black/white checkerboard.
        static PIXELS: [f32; 12] = [
            0.0, 0.0, 0.0,  1.0, 1.0, 1.0,
            1.0, 1.0, 1.0,  0.0, 0.0, 0.0,
        ];

        gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGB as GLint, 2, 2, 0, gl::RGB, gl::FLOAT,
                       PIXELS.as_ptr() as *const GLvoid);

        // Compile the vertex and fragment shaders.
        vertex_shader = compile_shader(gl::VERTEX_SHADER, VERTEX_SHADER_SOURCE).unwrap();
        fragment_shader = compile_shader(gl::FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE).unwrap();

        // Link the vertex and fragment shaders into a shader program.
        shader_program = gl::CreateProgram();
        gl::AttachShader(shader_program, vertex_shader);
        gl::AttachShader(shader_program, fragment_shader);
        gl::BindFragDataLocation(shader_program, 0, gl_str!("out_color"));
        gl::LinkProgram(shader_program);
        gl::UseProgram(shader_program);

        // Specify the layout of the vertex data.
        let position_attrib = gl::GetAttribLocation(shader_program, gl_str!("position"));
        gl::EnableVertexAttribArray(position_attrib as GLuint);
        gl::VertexAttribPointer(position_attrib as GLuint, 2, gl::FLOAT, gl::FALSE,
                                mem::size_of::<Vertex>() as GLint, ptr::null());

        let position_attrib = gl::GetAttribLocation(shader_program, gl_str!("color"));
        gl::EnableVertexAttribArray(position_attrib as GLuint);
        gl::VertexAttribPointer(position_attrib as GLuint, 3, gl::FLOAT, gl::FALSE,
                                mem::size_of::<Vertex>() as GLint,
                                (2 * mem::size_of::<GLfloat>()) as *const GLvoid);

        let position_attrib = gl::GetAttribLocation(shader_program, gl_str!("texcoord"));
        gl::EnableVertexAttribArray(position_attrib as GLuint);
        gl::VertexAttribPointer(position_attrib as GLuint, 2, gl::FLOAT, gl::FALSE,
                                mem::size_of::<Vertex>() as GLint,
                                (5 * mem::size_of::<GLfloat>()) as *const GLvoid);
    }

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }

        unsafe {
            // Clear the screen to black.
            gl::ClearColor(0.0, 0.0, 0.0, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);

            // Draw the triangles described by the elements array.
            gl::DrawElements(gl::TRIANGLES, ELEMENTS.len() as GLint, gl::UNSIGNED_INT,
                             ptr::null());
        }

        window.swap_buffers();
    }

    unsafe {
        gl::DeleteProgram(shader_program);
        gl::DeleteShader(fragment_shader);
        gl::DeleteShader(vertex_shader);
        gl::DeleteBuffers(1, &vbo);
        gl::DeleteVertexArrays(1, &vao);
    }
}

fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
    use glfw::{Action, Key, WindowEvent};

    match event {
        WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
            window.set_should_close(true);
        },
        _ => {},
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::collections::BTreeSet;
use std::str::FromStr;
use std::fmt;
use twiddle::Twiddle;
use enum_primitive::FromPrimitive;

use board::Board;
use board::Square;
use piece::Piece;
use piece::Player;
use piece;
use point::Point;

//TODO: Copy? (s needs to be removed first)
#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
pub struct Board5 {
    grid: [ [u16; 5]; 5],
    continuations: [u16; 7],
    s: Square, // This is just a stupid hack for compilation - 4/23/16

}

impl fmt::Display for Board5 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Not Implemented")
    }
}

fn top_piece_bits(spot: u16) -> u8 {
    spot.bits(15..13) as u8
}

impl Board for Board5 {
    fn new(board_size: usize) -> Board5 {
        assert!(board_size == 5);
        Board5 {
            grid: [[0; 5]; 5],
            continuations: [0; 7],
            s: Square::new(),
        }
    }

    fn at(&self, point: &Point) -> Result<&Square, &str> {
        Err("Not implemented")
    }

    fn at_mut(&mut self, point: &Point) -> Result<&mut Square, &str> {
        Err("Not implemented")
    }

    fn at_reset(&mut self, point: &Point) -> Result<Square, &str> {
        Err("Not implemented")
    }

    fn size(&self) -> usize {
        5
    }

    fn squares(&self) -> Vec<&Square> {
        vec![&self.s]
    }

    /// Checks to see if all spaces have at least one piece
    fn full(&self) -> bool {
        for row in self.grid.iter() {
            for square in row.iter() {
                if square.bits(15..13) == 0 {
                    return false
                }
            }
        }
        true
    }

    fn place_piece(&mut self, point: &Point, piece: Piece) -> Result<(), String> {
        if top_piece_bits(self.grid[point.x][point.y]) == 0 {
            self.grid[point.x][point.y] = (piece as u16) << 13;
            Ok(())
        } else {
            return Err("Cannot place stone on top of existing stone.".into());
        }
    }

    fn add_piece(&mut self, point: &Point, piece: Piece) -> Result<(), String> {
        let spot = self.grid[point.x][point.y];
        let top_bits = top_piece_bits(spot);
        if top_bits == 0 {
            self.grid[point.x][point.y] = (piece as u16) << 13;
            return Ok(());
        }
        let mut top = Piece::from_u8(top_bits).unwrap();
        try!(piece.move_onto(&mut top));

        if spot.bits(1..0) == 0 {
            let mut temp = spot.bits(11..2) >> 2;
            if top.owner() == Player::One {
                temp = temp | 0x400;
            } else {
                temp = temp | 0x800;
            }
            self.grid[point.x][point.y] = temp | ((piece as u16) << 13);
            Ok(())
        } else {
            // Need to figure out continuations
            Err("Not implemented".into())
        }
    }

    fn used_up(&self, piece: &Piece) -> bool {
        false
    }

    fn follow(&self,
              starts: &mut VecDeque<Point>,
              player: Player)
              -> BTreeSet<Point> {
        BTreeSet::new()
    }
}

impl FromStr for Board5 {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Board5::new(5))
    }
}
<commit_msg>Add logic to handle continuations in add_piece<commit_after>use std::collections::VecDeque;
use std::collections::BTreeSet;
use std::str::FromStr;
use std::fmt;
use twiddle::Twiddle;
use enum_primitive::FromPrimitive;

use board::Board;
use board::Square;
use piece::Piece;
use piece::Player;
use piece;
use point::Point;

//TODO: Copy? (s needs to be removed first)
#[derive(Clone, Debug, RustcDecodable, RustcEncodable)]
pub struct Board5 {
    grid: [ [u16; 5]; 5],
    continuations: [u16; 7],
    s: Square, // This is just a stupid hack for compilation - 4/23/16

}

impl fmt::Display for Board5 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Not Implemented")
    }
}

fn top_piece_bits(spot: u16) -> u8 {
    spot.bits(15..13) as u8
}

impl Board for Board5 {
    fn new(board_size: usize) -> Board5 {
        assert!(board_size == 5);
        Board5 {
            grid: [[0; 5]; 5],
            continuations: [0; 7],
            s: Square::new(),
        }
    }

    fn at(&self, point: &Point) -> Result<&Square, &str> {
        Err("Not implemented")
    }

    fn at_mut(&mut self, point: &Point) -> Result<&mut Square, &str> {
        Err("Not implemented")
    }

    fn at_reset(&mut self, point: &Point) -> Result<Square, &str> {
        Err("Not implemented")
    }

    fn size(&self) -> usize {
        5
    }

    fn squares(&self) -> Vec<&Square> {
        vec![&self.s]
    }

    /// Checks to see if all spaces have at least one piece
    fn full(&self) -> bool {
        for row in self.grid.iter() {
            for square in row.iter() {
                if square.bits(15..13) == 0 {
                    return false
                }
            }
        }
        true
    }

    fn place_piece(&mut self, point: &Point, piece: Piece) -> Result<(), String> {
        if top_piece_bits(self.grid[point.x][point.y]) == 0 {
            self.grid[point.x][point.y] = (piece as u16) << 13;
            Ok(())
        } else {
            return Err("Cannot place stone on top of existing stone.".into());
        }
    }

    fn add_piece(&mut self, point: &Point, piece: Piece) -> Result<(), String> {
        let spot = self.grid[point.x][point.y];
        let top_bits = top_piece_bits(spot);
        if top_bits == 0 {
            self.grid[point.x][point.y] = (piece as u16) << 13;
            return Ok(());
        }
        let mut top = Piece::from_u8(top_bits).unwrap();
        try!(piece.move_onto(&mut top));

        let mut lowest = spot.bits(1..0);
        let mut temp = spot.bits(11..2) >> 2;
        if top.owner() == Player::One {
            temp = temp | 0x400;
        } else {
            temp = temp | 0x800;
        }
        self.grid[point.x][point.y] = temp | ((piece as u16) << 13);
        if lowest == 0 {
            Ok(())
        } else {
            // Need to add the bumped piece to an existing continuation
            let my_spot = 0 as u16;
            for i in 0..7 {
                let cont = self.continuations[i];
                if cont.bits(15..11) == (point.x * 5 + point.y) as u16 {
                    let mut temp: u16 = cont & 0xF800; // Keep location
                    temp |= cont.bits(9..2); // Shift everything thats there
                    temp |= lowest << 9; // Add in the bumped piece
                    self.continuations[i] = temp;

                    lowest = cont & 3; // We may have to do this again...
                    if lowest == 0 {
                        return Ok(());
                    }
                }
            }

            // If we haven't returned yet, we need to start a new continuation
            for i in 0..7 {
                let cont = self.continuations[i];
                if cont.bits(15..11) == 0 {
                    // It's unclaimed - let's claim it by setting the location
                    let mut temp: u16 = ((point.x * 5 + point.y) as u16) << 11;
                    temp |= lowest << 9; // Add in the bumped piece
                    self.continuations[i] = temp;
                    return Ok(());
                }
            }

            // Need to figure out continuations
            Err("No available continuations. Did you play too many pieces?".into())
        }
    }

    fn used_up(&self, piece: &Piece) -> bool {
        false
    }

    fn follow(&self,
              starts: &mut VecDeque<Point>,
              player: Player)
              -> BTreeSet<Point> {
        BTreeSet::new()
    }
}

impl FromStr for Board5 {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Board5::new(5))
    }
}
<|endoftext|>


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

use gl;
use gl::types::{GLenum,GLsizeiptr,GLvoid};

use std::mem::size_of;

use super::tracker::Bind;
use super::context::{Context,ContextEditingSupport,RegistrationHandle};
use super::vertexarray::VertexArray;
use super::tracker::TrackerId;

#[derive(Clone,Copy,Debug)]
pub enum BufferType {
    VertexBuffer,
    IndexBuffer,
    UniformBuffer
}

fn type_to_target(buffer_type: BufferType) -> GLenum {
    match buffer_type {
        BufferType::VertexBuffer => gl::ARRAY_BUFFER,
        BufferType::IndexBuffer => gl::ELEMENT_ARRAY_BUFFER,
        BufferType::UniformBuffer => gl::UNIFORM_BUFFER
    }
}

pub struct BufferObject {
    pub id: u32,
    tracker_id: TrackerId,
    registration: RegistrationHandle
}

pub fn new_buffer(tracker_id: TrackerId, registration: RegistrationHandle) -> BufferObject {
    BufferObject::new(tracker_id, registration)
}

impl BufferObject {
    fn new(tracker_id: TrackerId, registration: RegistrationHandle) -> BufferObject {
        let mut id: u32 = 0;
        unsafe {
            gl::GenBuffers(1, &mut id);
            check_error!();
        }
        BufferObject {
            id: id,
            tracker_id: tracker_id,
            registration: registration
        }
    }

    pub fn data<D>(&self, buffer_type: BufferType, data: &[D]) {
        let data_size = (size_of::<D>() * data.len()) as GLsizeiptr;
        unsafe {
            gl::BufferData(type_to_target(buffer_type), data_size, data.as_ptr() as *const GLvoid, gl::STATIC_DRAW);
            check_error!();
        }
    }

    pub fn sub_data<D>(&self, buffer_type: BufferType, data: &[D], byte_offset: usize) {
        let data_size = (size_of::<D>() * data.len()) as GLsizeiptr;
        unsafe {
            gl::BufferSubData(type_to_target(buffer_type), data_size, byte_offset as GLsizeiptr, data.as_ptr() as *const GLvoid);
            check_error!();
        }
    }

    pub fn bind(&self, buffer_type: BufferType) {
        unsafe {
            gl::BindBuffer(type_to_target(buffer_type), self.id);
            check_error!();
        }
    }
}

impl Drop for BufferObject {
    fn drop(&mut self) {
        if self.registration.context_alive() {
            unsafe {
                gl::DeleteBuffers(1, &self.id);
                check_error!();
            }
        }
    }
}

/* impl PartialEq for BufferObject {
    fn eq(&self, other: &BufferObject) -> bool {
        self.id == other.id
    }
} */

pub struct BufferBinder {
    buffer_type: BufferType
}

impl BufferBinder {
    pub fn new(buffer_type: BufferType) -> BufferBinder {
        BufferBinder { buffer_type: buffer_type }
    }
}

impl Bind<BufferObject> for BufferBinder {
    fn bind(&self, buffer: &BufferObject) {
        buffer.bind(self.buffer_type);
    }

    fn get_id(&self, buffer: &BufferObject) -> TrackerId {
        buffer.tracker_id
    }
}

pub fn new_vertex_buffer_editor<'a>(context: &'a mut Context, buffer: &'a BufferObject) -> BufferEditor<'a> {
    context.bind_vbo_for_editing(buffer);
    BufferEditor { context: context, buffer: buffer, buffer_type: BufferType::VertexBuffer }
}

pub fn new_index_buffer_editor<'a>(context: &'a mut Context, vertex_array: &'a VertexArray, buffer: &'a BufferObject) -> BufferEditor<'a> {
    context.bind_vao_for_editing(vertex_array);
    BufferEditor { context: context, buffer: buffer, buffer_type: BufferType::IndexBuffer }
}

pub fn new_uniform_buffer_editor<'a>(context: &'a mut Context, buffer: &'a BufferObject) -> BufferEditor<'a> {
    context.bind_ubo_for_editing(buffer);
    BufferEditor { context: context, buffer: buffer, buffer_type: BufferType::UniformBuffer }
}

pub struct BufferEditor<'a> {
    #[allow(dead_code)]
    context: &'a mut Context,
    buffer: &'a BufferObject,
    buffer_type: BufferType
}

impl<'a> BufferEditor<'a> {
    pub fn data<D>(&mut self, buffer_type: BufferType, data: &[D]) {
        self.buffer.data(buffer_type, data);
    }

    pub fn sub_data<D>(&mut self, buffer_type: BufferType, data: &[D], byte_offset: usize) {
        self.buffer.sub_data(buffer_type, data, byte_offset);
    }
}
<commit_msg>Remove unncessary parameters from editor methods.<commit_after>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use gl;
use gl::types::{GLenum,GLsizeiptr,GLvoid};

use std::mem::size_of;

use super::tracker::Bind;
use super::context::{Context,ContextEditingSupport,RegistrationHandle};
use super::vertexarray::VertexArray;
use super::tracker::TrackerId;

#[derive(Clone,Copy,Debug)]
pub enum BufferType {
    VertexBuffer,
    IndexBuffer,
    UniformBuffer
}

fn type_to_target(buffer_type: BufferType) -> GLenum {
    match buffer_type {
        BufferType::VertexBuffer => gl::ARRAY_BUFFER,
        BufferType::IndexBuffer => gl::ELEMENT_ARRAY_BUFFER,
        BufferType::UniformBuffer => gl::UNIFORM_BUFFER
    }
}

pub struct BufferObject {
    pub id: u32,
    tracker_id: TrackerId,
    registration: RegistrationHandle
}

pub fn new_buffer(tracker_id: TrackerId, registration: RegistrationHandle) -> BufferObject {
    BufferObject::new(tracker_id, registration)
}

impl BufferObject {
    fn new(tracker_id: TrackerId, registration: RegistrationHandle) -> BufferObject {
        let mut id: u32 = 0;
        unsafe {
            gl::GenBuffers(1, &mut id);
            check_error!();
        }
        BufferObject {
            id: id,
            tracker_id: tracker_id,
            registration: registration
        }
    }

    pub fn data<D>(&self, buffer_type: BufferType, data: &[D]) {
        let data_size = (size_of::<D>() * data.len()) as GLsizeiptr;
        unsafe {
            gl::BufferData(type_to_target(buffer_type), data_size, data.as_ptr() as *const GLvoid, gl::STATIC_DRAW);
            check_error!();
        }
    }

    pub fn sub_data<D>(&self, buffer_type: BufferType, data: &[D], byte_offset: usize) {
        let data_size = (size_of::<D>() * data.len()) as GLsizeiptr;
        unsafe {
            gl::BufferSubData(type_to_target(buffer_type), data_size, byte_offset as GLsizeiptr, data.as_ptr() as *const GLvoid);
            check_error!();
        }
    }

    pub fn bind(&self, buffer_type: BufferType) {
        unsafe {
            gl::BindBuffer(type_to_target(buffer_type), self.id);
            check_error!();
        }
    }
}

impl Drop for BufferObject {
    fn drop(&mut self) {
        if self.registration.context_alive() {
            unsafe {
                gl::DeleteBuffers(1, &self.id);
                check_error!();
            }
        }
    }
}

/* impl PartialEq for BufferObject {
    fn eq(&self, other: &BufferObject) -> bool {
        self.id == other.id
    }
} */

pub struct BufferBinder {
    buffer_type: BufferType
}

impl BufferBinder {
    pub fn new(buffer_type: BufferType) -> BufferBinder {
        BufferBinder { buffer_type: buffer_type }
    }
}

impl Bind<BufferObject> for BufferBinder {
    fn bind(&self, buffer: &BufferObject) {
        buffer.bind(self.buffer_type);
    }

    fn get_id(&self, buffer: &BufferObject) -> TrackerId {
        buffer.tracker_id
    }
}

pub fn new_vertex_buffer_editor<'a>(context: &'a mut Context, buffer: &'a BufferObject) -> BufferEditor<'a> {
    context.bind_vbo_for_editing(buffer);
    BufferEditor { context: context, buffer: buffer, buffer_type: BufferType::VertexBuffer }
}

pub fn new_index_buffer_editor<'a>(context: &'a mut Context, vertex_array: &'a VertexArray, buffer: &'a BufferObject) -> BufferEditor<'a> {
    context.bind_vao_for_editing(vertex_array);
    BufferEditor { context: context, buffer: buffer, buffer_type: BufferType::IndexBuffer }
}

pub fn new_uniform_buffer_editor<'a>(context: &'a mut Context, buffer: &'a BufferObject) -> BufferEditor<'a> {
    context.bind_ubo_for_editing(buffer);
    BufferEditor { context: context, buffer: buffer, buffer_type: BufferType::UniformBuffer }
}

pub struct BufferEditor<'a> {
    #[allow(dead_code)]
    context: &'a mut Context,
    buffer: &'a BufferObject,
    buffer_type: BufferType
}

impl<'a> BufferEditor<'a> {
    pub fn data<D>(&mut self, data: &[D]) {
        self.buffer.data(self.buffer_type, data);
    }

    pub fn sub_data<D>(&mut self, data: &[D], byte_offset: usize) {
        self.buffer.sub_data(self.buffer_type, data, byte_offset);
    }
}
<|endoftext|>


<commit_before>extern crate calx_window;
extern crate calx_cache;
extern crate calx_draw;

use calx_cache::{AtlasBuilder, Atlas, AtlasItem};
use calx_window::{WindowBuilder, Window, Event, Key};
use calx_draw::Buffer;

struct Context {
    pub window: Window,
    pub buffer: Buffer,
    pub tiles: Vec<AtlasItem>,
}

impl Context {
    pub fn new() -> Context {
        let window = WindowBuilder::new().set_title("Calx demo").build();
        let mut atlas_builder = AtlasBuilder::new();
        atlas_builder.push_solid();
        let Atlas {
            image: img,
            items: tiles,
        } = atlas_builder.build();

        let buffer = Buffer::new(&window.display, img);
        Context {
            window: window,
            buffer: buffer,
            tiles: tiles,
        }
    }
}

fn main() {
    let mut ctx = Context::new();

    'top: loop {
        for e in ctx.window.events().into_iter() {
            match e {
                Event::Quit => break 'top,
                Event::KeyPress(Key::Escape) => break 'top,
                _ => (),
            }
        }

        ctx.window.end_frame();
    }
}
<commit_msg>WIP font in demo<commit_after>extern crate image;
extern crate calx_window;
extern crate calx_cache;
extern crate calx_draw;

use calx_cache::{AtlasBuilder, Atlas, AtlasItem, tilesheet_bounds, subimage};
use calx_window::{WindowBuilder, Window, Event, Key};
use calx_draw::Buffer;

struct Context {
    pub window: Window,
    pub buffer: Buffer,
    pub tiles: Vec<AtlasItem>,
}

impl Context {
    pub fn new() -> Context {
        let window = WindowBuilder::new().set_title("Calx demo").build();
        let mut atlas_builder = AtlasBuilder::new();

        // Solid color as the default element.
        assert!(atlas_builder.push_solid() == Default::default());

        let mut sheet = image::load_from_memory(include_bytes!("../assets/font.png")).unwrap();
        let bounds = tilesheet_bounds(&sheet);

        let Atlas {
            image: img,
            items: tiles,
        } = atlas_builder.build();

        let buffer = Buffer::new(&window.display, img);
        Context {
            window: window,
            buffer: buffer,
            tiles: tiles,
        }
    }
}

fn main() {
    let mut ctx = Context::new();

    'top: loop {
        for e in ctx.window.events().into_iter() {
            match e {
                Event::Quit => break 'top,
                Event::KeyPress(Key::Escape) => break 'top,
                _ => (),
            }
        }

        ctx.window.end_frame();
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
extern crate capnp_futures;
extern crate futures;
extern crate tokio_core;
extern crate mio_uds;

pub mod addressbook_capnp {
  include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs"));
}

#[cfg(test)]
mod tests {
    use addressbook_capnp::{address_book, person};

    fn populate_address_book(address_book: address_book::Builder) {
        let mut people = address_book.init_people(2);
        {
            let mut alice = people.reborrow().get(0);
            alice.set_id(123);
            alice.set_name("Alice");
            alice.set_email("alice@example.com");
            {
                let mut alice_phones = alice.reborrow().init_phones(1);
                alice_phones.reborrow().get(0).set_number("555-1212");
                alice_phones.reborrow().get(0).set_type(person::phone_number::Type::Mobile);
            }
            alice.get_employment().set_school("MIT");
        }

        {
            let mut bob = people.get(1);
            bob.set_id(456);
            bob.set_name("Bob");
            bob.set_email("bob@example.com");
            {
                let mut bob_phones = bob.reborrow().init_phones(2);
                bob_phones.reborrow().get(0).set_number("555-4567");
                bob_phones.reborrow().get(0).set_type(person::phone_number::Type::Home);
                bob_phones.reborrow().get(1).set_number("555-7654");
                bob_phones.reborrow().get(1).set_type(person::phone_number::Type::Work);
            }
            bob.get_employment().set_unemployed(());
        }
    }

    fn read_address_book(address_book: address_book::Reader) {
        let people = address_book.get_people().unwrap();
        assert_eq!(people.len(), 2);
        let alice = people.get(0);
        assert_eq!(alice.get_id(), 123);
        assert_eq!(alice.get_name().unwrap(), "Alice");
        assert_eq!(alice.get_email().unwrap(), "alice@example.com");

        let bob = people.get(1);
        assert_eq!(bob.get_id(), 456);
        assert_eq!(bob.get_name().unwrap(), "Bob");
    }

    #[test]
    fn foo() {
        use tokio_core::reactor;
        use mio_uds::UnixStream;
        use capnp;
        use capnp_futures;
        use futures::future::Future;
        use futures::stream::Stream;

        use std::cell::Cell;
        use std::rc::Rc;

        let mut l = reactor::Core::new().unwrap();
        let handle = l.handle();
        let (s1, s2) = UnixStream::pair().unwrap();
        let s1 = reactor::PollEvented::new(s1, &handle).unwrap();
        let s2 = reactor::PollEvented::new(s2, &handle).unwrap();

        let (mut sender, write_queue) = capnp_futures::write_queue(s1);

        let read_stream = capnp_futures::ReadStream::new(s2, Default::default());

        let messages_read = Rc::new(Cell::new(0u32));
        let messages_read1 = messages_read.clone();

        let done_reading = read_stream.for_each(|m| {
            let address_book = m.get_root::<address_book::Reader>().unwrap();
            read_address_book(address_book);
            messages_read.set(messages_read.get() + 1);
            Ok(())
        });

        let io = done_reading.join(write_queue.map(|_| ()));

        let mut m = capnp::message::Builder::new_default();
        populate_address_book(m.init_root());
        handle.spawn(sender.send(m).map_err(|_| panic!("cancelled")).map(|_| { println!("SENT"); ()}));
        drop(sender);

        l.run(io).expect("running");

        assert_eq!(messages_read1.get(), 1);
    }
/*
    fn fill_and_send_message(mut message: message::Builder<message::HeapAllocator>) {
        {
            let mut address_book = message.init_root::<address_book::Builder>();
            populate_address_book(address_book.borrow());
            read_address_book(address_book.borrow_as_reader());
        }

        gj::EventLoop::top_level(move |wait_scope| -> Result<(), ::std::io::Error> {
            let mut event_port = try!(::gjio::EventPort::new());
            let network = event_port.get_network();
            let (stream0, stream1) = try!(network.new_socket_pair());

            let promise0 = serialize::write_message(stream0, message).map(|_| Ok(()));
            let promise1 =
                serialize::read_message(stream1, message::ReaderOptions::new()).then(|(_, message_reader)| {
                    let address_book = message_reader.get_root::<address_book::Reader>().unwrap();
                    read_address_book(address_book);
                    gj::Promise::ok(())
                });

            gj::Promise::all(vec![promise0, promise1].into_iter()).wait(wait_scope, &mut event_port).unwrap();
            Ok(())
        }).unwrap();

    }

    #[test]
    fn single_segment() {
        fill_and_send_message(message::Builder::new_default());
    }

    #[test]
    fn multi_segment() {
        let builder_options = message::HeapAllocator::new()
            .first_segment_words(1).allocation_strategy(::capnp::message::AllocationStrategy::FixedSize);
        fill_and_send_message(message::Builder::new(builder_options));
    }
*/
}
<commit_msg>uncomment and update some capnp-futures tests<commit_after>// Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate capnp;
extern crate capnp_futures;
extern crate futures;
extern crate tokio_core;
extern crate mio_uds;

pub mod addressbook_capnp {
  include!(concat!(env!("OUT_DIR"), "/addressbook_capnp.rs"));
}

#[cfg(test)]
mod tests {
    use addressbook_capnp::{address_book, person};

    fn populate_address_book(address_book: address_book::Builder) {
        let mut people = address_book.init_people(2);
        {
            let mut alice = people.reborrow().get(0);
            alice.set_id(123);
            alice.set_name("Alice");
            alice.set_email("alice@example.com");
            {
                let mut alice_phones = alice.reborrow().init_phones(1);
                alice_phones.reborrow().get(0).set_number("555-1212");
                alice_phones.reborrow().get(0).set_type(person::phone_number::Type::Mobile);
            }
            alice.get_employment().set_school("MIT");
        }

        {
            let mut bob = people.get(1);
            bob.set_id(456);
            bob.set_name("Bob");
            bob.set_email("bob@example.com");
            {
                let mut bob_phones = bob.reborrow().init_phones(2);
                bob_phones.reborrow().get(0).set_number("555-4567");
                bob_phones.reborrow().get(0).set_type(person::phone_number::Type::Home);
                bob_phones.reborrow().get(1).set_number("555-7654");
                bob_phones.reborrow().get(1).set_type(person::phone_number::Type::Work);
            }
            bob.get_employment().set_unemployed(());
        }
    }

    fn read_address_book(address_book: address_book::Reader) {
        let people = address_book.get_people().unwrap();
        assert_eq!(people.len(), 2);
        let alice = people.get(0);
        assert_eq!(alice.get_id(), 123);
        assert_eq!(alice.get_name().unwrap(), "Alice");
        assert_eq!(alice.get_email().unwrap(), "alice@example.com");

        let bob = people.get(1);
        assert_eq!(bob.get_id(), 456);
        assert_eq!(bob.get_name().unwrap(), "Bob");
    }

    #[test]
    fn write_stream_and_read_queue() {
        use tokio_core::reactor;
        use mio_uds::UnixStream;
        use capnp;
        use capnp_futures;
        use futures::future::Future;
        use futures::stream::Stream;

        use std::cell::Cell;
        use std::rc::Rc;

        let mut l = reactor::Core::new().unwrap();
        let handle = l.handle();
        let (s1, s2) = UnixStream::pair().unwrap();
        let s1 = reactor::PollEvented::new(s1, &handle).unwrap();
        let s2 = reactor::PollEvented::new(s2, &handle).unwrap();

        let (mut sender, write_queue) = capnp_futures::write_queue(s1);

        let read_stream = capnp_futures::ReadStream::new(s2, Default::default());

        let messages_read = Rc::new(Cell::new(0u32));
        let messages_read1 = messages_read.clone();

        let done_reading = read_stream.for_each(|m| {
            let address_book = m.get_root::<address_book::Reader>().unwrap();
            read_address_book(address_book);
            messages_read.set(messages_read.get() + 1);
            Ok(())
        });

        let io = done_reading.join(write_queue.map(|_| ()));

        let mut m = capnp::message::Builder::new_default();
        populate_address_book(m.init_root());
        handle.spawn(sender.send(m).map_err(|_| panic!("cancelled")).map(|_| { println!("SENT"); ()}));
        drop(sender);

        l.run(io).expect("running");

        assert_eq!(messages_read1.get(), 1);
    }

    fn fill_and_send_message(mut message: capnp::message::Builder<capnp::message::HeapAllocator>) {
        use tokio_core::reactor;
        use mio_uds::UnixStream;
        use capnp_futures::serialize;
        use futures::Future;

        {
            let mut address_book = message.init_root::<address_book::Builder>();
            populate_address_book(address_book.reborrow());
            read_address_book(address_book.reborrow_as_reader());
        }

        let mut l = reactor::Core::new().unwrap();
        let handle = l.handle();
        let (s0, s1) = UnixStream::pair().unwrap();
        let stream0 = reactor::PollEvented::new(s0, &handle).unwrap();
        let stream1 = reactor::PollEvented::new(s1, &handle).unwrap();

        let promise0 = serialize::write_message(stream0, message).map(|_| Ok::<(), capnp::Error>(()));
        let promise1 =
            serialize::read_message(stream1, capnp::message::ReaderOptions::new()).and_then(|(_, maybe_message_reader)| {
                match maybe_message_reader {
                    None => panic!("did not get message"),
                    Some(m) => {
                        let address_book = m.get_root::<address_book::Reader>().unwrap();
                        read_address_book(address_book);
                        Ok::<(),capnp::Error>(())
                    }
                }
            });

        handle.spawn(promise0.map_err(|e| panic!("failed to write. {:?}", e)).map(|_| ()));
        l.run(promise1).expect("running");
    }

    #[test]
    fn single_segment() {
        fill_and_send_message(capnp::message::Builder::new_default());
    }

    #[test]
    fn multi_segment() {
        let builder_options = capnp::message::HeapAllocator::new()
            .first_segment_words(1).allocation_strategy(capnp::message::AllocationStrategy::FixedSize);
        fill_and_send_message(capnp::message::Builder::new(builder_options));
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate dialoguer;
extern crate serde;
extern crate serde_json;
extern crate snapshot;
extern crate walkdir;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::process::{Command, Stdio};

use clap::{Arg, SubCommand};
use dialoguer::Checkboxes;
use snapshot::SnapFileContents;
use walkdir::WalkDir;

fn main() {
    let input = app_from_crate!()
        .subcommand(
            SubCommand::with_name("update")
                .about("Update snapshots.")
                .arg(Arg::with_name("all").short("a").long("all").help(
                    "Unconditionally update all snapshots, including unrecorded ones.",
                )),
        )
        .get_matches();

    let cwd = ::std::env::current_dir().expect("can't access working directory!");

    // throw away errors
    let existing: Vec<SnapFileContents> = WalkDir::new(cwd)
        .into_iter()
        .map(|r| r.expect("unable to traverse project directory"))
        .filter(|e| e.path().extension() == Some(OsStr::new("snap")))
        .map(|p| BufReader::new(File::open(p.path()).expect("unable to open snapshot file")))
        .map(|r| serde_json::from_reader(r).expect("unable to parse snapshot file"))
        .collect::<Vec<_>>();

    let update_matches = input.subcommand_matches("update");

    if update_matches.is_none() {
        panic!("unsupported command!");
    }

    let mut test_function_names = Vec::new();
    for snap_file in existing {
        for fun in snap_file.keys() {
            test_function_names.push(fun.clone());
        }
    }

    let mut failed_tests = Vec::new();

    println!("Checking for out of date snapshot tests...\n");
    for test_fn in test_function_names {
        let mut test_fn_chunks = test_fn.splitn(2, "::");

        // skip the crate name
        test_fn_chunks
            .next()
            .expect("looks like an empty test function name");

        let real_test_fn = test_fn_chunks
            .next()
            .expect("seemingly malformed test name");

        let first_run_status = Command::new("cargo")
            .arg("test")
            .arg(&real_test_fn)
// uncomment these once we can get just the error message back from cargo/rust
//            .stdout(Stdio::null())
//            .stderr(Stdio::null())
            .status()
            .expect("unable to execute cargo");

        if !first_run_status.success() {
            failed_tests.push(real_test_fn.to_owned());
        }
    }

    if failed_tests.is_empty() {
        println!("\nNo snapshot tests require an update!");
        ::std::process::exit(0);
    } else {
        println!("\nPlease select which snapshot tests should be updated:");
        println!("  (press <Space> to select, <Enter> to submit)\n");

        let mut menu = Checkboxes::new();
        for failed in &failed_tests {
            menu.item(failed);
        }
        let all_to_update = menu.interact().expect("error accepting user selections");

        for fn_idx in all_to_update {
            let fn_to_update = &failed_tests[fn_idx];
            println!("Updating {}...", &fn_to_update);

            // TODO actually run the tests
        }

        println!("\nAll updates processed!");
    }

    // TODO figure out how to handle un-recorded tests
}
<commit_msg>Update snapshots interactively.<commit_after>#[macro_use]
extern crate clap;
extern crate dialoguer;
extern crate serde;
extern crate serde_json;
extern crate snapshot;
extern crate walkdir;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::process::{Command, Stdio};

use clap::{Arg, SubCommand};
use dialoguer::{Checkboxes, Select};
use snapshot::SnapFileContents;
use walkdir::WalkDir;

fn main() {
    let input = app_from_crate!()
        .subcommand(
            SubCommand::with_name("update")
                .about("Update snapshots.")
                .arg(Arg::with_name("all").short("a").long("all").help(
                    "Unconditionally update all snapshots, including unrecorded ones.",
                )),
        )
        .get_matches();

    let cwd = ::std::env::current_dir().expect("can't access working directory!");

    // throw away errors
    let existing: Vec<SnapFileContents> = WalkDir::new(cwd)
        .into_iter()
        .map(|r| r.expect("unable to traverse project directory"))
        .filter(|e| e.path().extension() == Some(OsStr::new("snap")))
        .map(|p| BufReader::new(File::open(p.path()).expect("unable to open snapshot file")))
        .map(|r| serde_json::from_reader(r).expect("unable to parse snapshot file"))
        .collect::<Vec<_>>();

    let update_matches = input.subcommand_matches("update");

    if update_matches.is_none() {
        panic!("unsupported command!");
    }

    let mut test_function_names = Vec::new();
    for snap_file in existing {
        for fun in snap_file.keys() {
            test_function_names.push(fun.clone());
        }
    }

    let mut failed_tests = Vec::new();

    println!("Checking for out of date snapshot tests...\n");
    for test_fn in test_function_names {
        let mut test_fn_chunks = test_fn.splitn(2, "::");

        // skip the crate name
        test_fn_chunks
            .next()
            .expect("looks like an empty test function name");

        let real_test_fn = test_fn_chunks
            .next()
            .expect("seemingly malformed test name");

        let first_run_status = Command::new("cargo")
            .arg("test")
            .arg(&real_test_fn)
// uncomment these once we can get just the error message back from cargo/rust
//            .stdout(Stdio::null())
//            .stderr(Stdio::null())
            .status()
            .expect("unable to execute cargo");

        if !first_run_status.success() {
            failed_tests.push(real_test_fn.to_owned());
        }
    }

    if failed_tests.is_empty() {
        println!("\nNo snapshot tests require an update!");
        ::std::process::exit(0);
    } else {
        println!("\nPlease select which snapshot tests should be updated:");
        println!("  (press <Space> to select, <Enter> to submit)\n");

        let mut menu = Checkboxes::new();
        for failed in &failed_tests {
            menu.item(failed);
        }
        let all_to_update = menu.interact().expect("error accepting user selections");

        for fn_idx in all_to_update {
            let fn_to_update = &failed_tests[fn_idx];
            println!("Updating {}...", &fn_to_update);

            let mut run_test = true;
            while run_test {
                let run_status = Command::new("cargo")
                    .arg("test")
                    .arg(fn_to_update)
                    .env("UPDATE_SNAPSHOTS", "1")
                    .status()
                    .expect("unable to execute cargo");

                if run_status.success() {
                    run_test = false;
                } else {
                    println!("\nUpdating {} failed! What would you like to do?",
                             fn_to_update);

                    let options = ["Retry", "Skip", "Abort"];

                    let selection = Select::new()
                        .items(&options)
                        .interact()
                        .expect("unable to retrieve user input");

                    if options[selection] == "Retry" {
                        continue;
                    } else if options[selection] == "Skip" {
                        break;
                    } else if options[selection] == "Abort" {
                        ::std::process::exit(1);
                    } else {
                        panic!("invalid menu selection")
                    }
                }
            }
        }

        println!("\nAll updates processed!");
    }

    // TODO figure out how to handle un-recorded tests
}
<|endoftext|>


<commit_before>use std::rand;
use std::rand::Rng;

fn main() {
	println("Secret Santa");

	let names = ~["Angus", "Greg", "Lewis", "Mike", "Isabel", "Rob", "Shannon", "Allan"];

	let pairings = secret_santa(&names);

	print_pairings(&pairings);
}

fn secret_santa<'r>(names: &~[&'r str]) -> ~[(&'r str,&'r str)] {
	let mut rng = rand::rng();
	let mut unshuffled_names = names.clone();
	let mut shuffled_names = rng.shuffle(names.clone());

	println!("Picking pairings from: {:?}", unshuffled_names);

	let mut pairs = ~[];

	while shuffled_names.len() > 0 {
		let chosen = unshuffled_names.pop();
		let partner = shuffled_names.pop();

		if( chosen == partner ) {
			unshuffled_names.push(chosen);
			shuffled_names.push(partner);

			if(shuffled_names.len() == 1) {
				break;
			}
			rng.shuffle_mut(shuffled_names);
			loop;
		}

		pairs.push((chosen,partner));
	}

	if(shuffled_names.len() == 1) {
		println("Restarting - no good solution.");
		secret_santa(names);
	}

	return pairs.clone();
}

fn print_pairings(pairings: &~[(&str, &str)]) {
	for &pair in pairings.iter() {
			println!("{:?} --- is buying for ---> {:?}", pair.first(), pair.second());
	}
}<commit_msg>Update secret-santa.rs<commit_after>use std::rand;
use std::rand::Rng;

fn main() {
	println("Secret Santa");

	let names = ~["Angus", "Greg", "Lewis", "Mike", "Isabel", "Rob", "Shannon", "Allan"];

	let pairings = secret_santa(&names);

	print_pairings(&pairings);
}

fn secret_santa<'r>(names: &~[&'r str]) -> ~[(&'r str,&'r str)] {
	let mut rng = rand::rng();
	let mut unshuffled_names = names.clone();
	let mut shuffled_names = rng.shuffle(names.clone());

	println!("Picking pairings from: {:?}", unshuffled_names);

	let mut pairs = ~[];

	while shuffled_names.len() > 0 {
		let chosen = unshuffled_names.pop();
		let partner = shuffled_names.pop();

		if( chosen == partner ) {
			unshuffled_names.push(chosen);
			shuffled_names.push(partner);

			if(shuffled_names.len() == 1) {
				break;
			}
			rng.shuffle_mut(shuffled_names);
			loop;
		}

		pairs.push((chosen,partner));
	}

	if(shuffled_names.len() == 1) {
		println("Restarting - no good solution.");
		return secret_santa(names);
	}

	return pairs.clone();
}

fn print_pairings(pairings: &~[(&str, &str)]) {
	for &pair in pairings.iter() {
			println!("{:?} --- is buying for ---> {:?}", pair.first(), pair.second());
	}
}
<|endoftext|>