<commit_before>/*
 * Copyright 2017-2018 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 */

use std::io;
use std::net::SocketAddr;

use futures::{Future, Stream};

use tokio_tcp::TcpStream;

use tokio_io::{AsyncRead, codec::Framed};

use resp;

pub type RespConnection = Framed<TcpStream, resp::RespCodec>;

/// Connect to a Redis server and return paired Sink and Stream for reading and writing
/// asynchronously.
pub fn connect(addr: &SocketAddr) -> Box<Future<Item = RespConnection, Error = io::Error> + Send> {
    Box::new(TcpStream::connect(addr).map(move |socket| socket.framed(resp::RespCodec)))
}
<commit_msg>Documentation<commit_after>/*
 * Copyright 2017-2018 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 */

use std::io;
use std::net::SocketAddr;

use futures::{Future, Stream};

use tokio_tcp::TcpStream;

use tokio_io::{AsyncRead, codec::Framed};

use resp;

pub type RespConnection = Framed<TcpStream, resp::RespCodec>;

/// Connect to a Redis server and return a Future that resolves to a
/// `RespConnection` for reading and writing asynchronously.
///
/// Each `RespConnection` implements both `Sink` and `Stream` and read and
/// writes `RESP` objects.
///
/// This is a low-level interface to enable the creation of higher-level
/// functionality.
///
/// The sink and stream sides behave independently of each other, it is the
/// responsibility of the calling application to determine what results are
/// paired to a particular command.
///
/// But since most Redis usages involve issue commands that result in one
/// single result, this library also implements `paired_connect`.
pub fn connect(addr: &SocketAddr) -> Box<Future<Item = RespConnection, Error = io::Error> + Send> {
    Box::new(TcpStream::connect(addr).map(move |socket| socket.framed(resp::RespCodec)))
}
<|endoftext|>


<commit_before>use crate::codegen;
use crate::ir::function::Abi;
use proc_macro2::Ident;

/// Used to build the output tokens for dynamic bindings.
#[derive(Default)]
pub struct DynamicItems {
    /// Tracks whether or not we contain any required symbols.
    /// If so, the signature of the generated `from_library` function
    /// will be altered to return a `Result<Self, ::libloading::Error>`
    has_required: bool,

    /// Tracks the tokens that will appears inside the library struct -- e.g.:
    /// ```ignore
    /// struct Lib {
    ///    __library: ::libloading::Library,
    ///    pub x: Result<unsafe extern ..., ::libloading::Error>, // <- tracks these
    ///    ...
    /// }
    /// ```
    struct_members: Vec<proc_macro2::TokenStream>,

    /// Tracks the tokens that will appear inside the library struct's implementation, e.g.:
    ///
    /// ```ignore
    /// impl Lib {
    ///     ...
    ///     pub unsafe fn foo(&self, ...) { // <- tracks these
    ///         ...
    ///     }
    /// }
    /// ```
    struct_implementation: Vec<proc_macro2::TokenStream>,

    /// Tracks the initialization of the fields inside the `::new` constructor of the library
    /// struct, e.g.:
    /// ```ignore
    /// impl Lib {
    ///
    ///     pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
    ///     where
    ///         P: AsRef<::std::ffi::OsStr>,
    ///     {
    ///         ...
    ///         let foo = __library.get(...) ...; // <- tracks these
    ///         ...
    ///     }
    ///
    ///     ...
    /// }
    /// ```
    constructor_inits: Vec<proc_macro2::TokenStream>,

    /// Tracks the information that is passed to the library struct at the end of the `::new`
    /// constructor, e.g.:
    /// ```ignore
    /// impl LibFoo {
    ///     pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
    ///     where
    ///         P: AsRef<::std::ffi::OsStr>,
    ///     {
    ///         ...
    ///         Ok(LibFoo {
    ///             __library: __library,
    ///             foo,
    ///             bar, // <- tracks these
    ///             ...
    ///         })
    ///     }
    /// }
    /// ```
    init_fields: Vec<proc_macro2::TokenStream>,
}

impl DynamicItems {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn get_tokens(&self, lib_ident: Ident) -> proc_macro2::TokenStream {
        let struct_members = &self.struct_members;
        let constructor_inits = &self.constructor_inits;
        let init_fields = &self.init_fields;
        let struct_implementation = &self.struct_implementation;

        // FIXME: Is there a better way to lay this out? Conditional in the quote
        // macro?
        // If we have any required symbols, we must alter the signature of `from_library`
        // so that it can return a failure code.
        quote! {
            extern crate libloading;

            pub struct #lib_ident {
                __library: ::libloading::Library,
                #(#struct_members)*
            }

            impl #lib_ident {
                pub unsafe fn new<P>(
                    path: P
                ) -> Result<Self, ::libloading::Error>
                where P: AsRef<::std::ffi::OsStr> {
                    let library = ::libloading::Library::new(path)?;
                    Self::from_library(library)
                }

                pub unsafe fn from_library<L>(
                    library: L
                ) -> Result<Self, ::libloading::Error>
                where L: Into<::libloading::Library> {
                    let __library = library.into();
                    #( #constructor_inits )*
                    Ok(#lib_ident {
                        __library,
                        #( #init_fields ),*
                    })
                }

                #( #struct_implementation )*
            }
        }
    }

    pub fn push(
        &mut self,
        ident: Ident,
        abi: Abi,
        is_variadic: bool,
        is_required: bool,
        args: Vec<proc_macro2::TokenStream>,
        args_identifiers: Vec<proc_macro2::TokenStream>,
        ret: proc_macro2::TokenStream,
        ret_ty: proc_macro2::TokenStream,
    ) {
        if !is_variadic {
            assert_eq!(args.len(), args_identifiers.len());
        }

        self.has_required |= is_required;

        self.struct_members.push(
            if is_required {
                quote! {
                    pub #ident: unsafe extern #abi fn ( #( #args),* ) #ret,
                }
            } else {
                quote! {
                    pub #ident: Result<unsafe extern #abi fn ( #( #args ),* ) #ret, ::libloading::Error>,
                }
            }
        );

        // We can't implement variadic functions from C easily, so we allow to
        // access the function pointer so that the user can call it just fine.
        if !is_variadic {
            self.struct_implementation.push(
                if is_required {
                    quote! {
                        pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty {
                            self.#ident(#( #args_identifiers ),*)
                        }
                    }
                } else {
                    quote! {
                        pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty {
                            let sym = self.#ident.as_ref().expect("Expected function, got error.");
                            (sym)(#( #args_identifiers ),*)
                        }
                    }
                }
            );
        }

        let ident_str = codegen::helpers::ast_ty::cstr_expr(ident.to_string());
        self.constructor_inits.push(if is_required {
            quote! {
                let #ident = __library.get(#ident_str).map(|sym| *sym)?;
            }
        } else {
            quote! {
                let #ident = __library.get(#ident_str).map(|sym| *sym);
            }
        });

        self.init_fields.push(quote! {
            #ident
        });
    }
}
<commit_msg>Remove `DynamicItems::has_required`<commit_after>use crate::codegen;
use crate::ir::function::Abi;
use proc_macro2::Ident;

/// Used to build the output tokens for dynamic bindings.
#[derive(Default)]
pub struct DynamicItems {
    /// Tracks the tokens that will appears inside the library struct -- e.g.:
    /// ```ignore
    /// struct Lib {
    ///    __library: ::libloading::Library,
    ///    pub x: Result<unsafe extern ..., ::libloading::Error>, // <- tracks these
    ///    ...
    /// }
    /// ```
    struct_members: Vec<proc_macro2::TokenStream>,

    /// Tracks the tokens that will appear inside the library struct's implementation, e.g.:
    ///
    /// ```ignore
    /// impl Lib {
    ///     ...
    ///     pub unsafe fn foo(&self, ...) { // <- tracks these
    ///         ...
    ///     }
    /// }
    /// ```
    struct_implementation: Vec<proc_macro2::TokenStream>,

    /// Tracks the initialization of the fields inside the `::new` constructor of the library
    /// struct, e.g.:
    /// ```ignore
    /// impl Lib {
    ///
    ///     pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
    ///     where
    ///         P: AsRef<::std::ffi::OsStr>,
    ///     {
    ///         ...
    ///         let foo = __library.get(...) ...; // <- tracks these
    ///         ...
    ///     }
    ///
    ///     ...
    /// }
    /// ```
    constructor_inits: Vec<proc_macro2::TokenStream>,

    /// Tracks the information that is passed to the library struct at the end of the `::new`
    /// constructor, e.g.:
    /// ```ignore
    /// impl LibFoo {
    ///     pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
    ///     where
    ///         P: AsRef<::std::ffi::OsStr>,
    ///     {
    ///         ...
    ///         Ok(LibFoo {
    ///             __library: __library,
    ///             foo,
    ///             bar, // <- tracks these
    ///             ...
    ///         })
    ///     }
    /// }
    /// ```
    init_fields: Vec<proc_macro2::TokenStream>,
}

impl DynamicItems {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn get_tokens(&self, lib_ident: Ident) -> proc_macro2::TokenStream {
        let struct_members = &self.struct_members;
        let constructor_inits = &self.constructor_inits;
        let init_fields = &self.init_fields;
        let struct_implementation = &self.struct_implementation;

        // FIXME: Is there a better way to lay this out? Conditional in the quote
        // macro?
        // If we have any required symbols, we must alter the signature of `from_library`
        // so that it can return a failure code.
        quote! {
            extern crate libloading;

            pub struct #lib_ident {
                __library: ::libloading::Library,
                #(#struct_members)*
            }

            impl #lib_ident {
                pub unsafe fn new<P>(
                    path: P
                ) -> Result<Self, ::libloading::Error>
                where P: AsRef<::std::ffi::OsStr> {
                    let library = ::libloading::Library::new(path)?;
                    Self::from_library(library)
                }

                pub unsafe fn from_library<L>(
                    library: L
                ) -> Result<Self, ::libloading::Error>
                where L: Into<::libloading::Library> {
                    let __library = library.into();
                    #( #constructor_inits )*
                    Ok(#lib_ident {
                        __library,
                        #( #init_fields ),*
                    })
                }

                #( #struct_implementation )*
            }
        }
    }

    pub fn push(
        &mut self,
        ident: Ident,
        abi: Abi,
        is_variadic: bool,
        is_required: bool,
        args: Vec<proc_macro2::TokenStream>,
        args_identifiers: Vec<proc_macro2::TokenStream>,
        ret: proc_macro2::TokenStream,
        ret_ty: proc_macro2::TokenStream,
    ) {
        if !is_variadic {
            assert_eq!(args.len(), args_identifiers.len());
        }

        self.struct_members.push(
            if is_required {
                quote! {
                    pub #ident: unsafe extern #abi fn ( #( #args),* ) #ret,
                }
            } else {
                quote! {
                    pub #ident: Result<unsafe extern #abi fn ( #( #args ),* ) #ret, ::libloading::Error>,
                }
            }
        );

        // We can't implement variadic functions from C easily, so we allow to
        // access the function pointer so that the user can call it just fine.
        if !is_variadic {
            self.struct_implementation.push(
                if is_required {
                    quote! {
                        pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty {
                            self.#ident(#( #args_identifiers ),*)
                        }
                    }
                } else {
                    quote! {
                        pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty {
                            let sym = self.#ident.as_ref().expect("Expected function, got error.");
                            (sym)(#( #args_identifiers ),*)
                        }
                    }
                }
            );
        }

        let ident_str = codegen::helpers::ast_ty::cstr_expr(ident.to_string());
        self.constructor_inits.push(if is_required {
            quote! {
                let #ident = __library.get(#ident_str).map(|sym| *sym)?;
            }
        } else {
            quote! {
                let #ident = __library.get(#ident_str).map(|sym| *sym);
            }
        });

        self.init_fields.push(quote! {
            #ident
        });
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate termbox_simple;

use termbox_simple::*;

use std::thread::sleep;
use std::time::Duration;

struct Termbox {}

impl Termbox {
    fn new() -> Termbox {
        unsafe { tb_init(); }
        Termbox {}
    }
}

impl Drop for Termbox {
    fn drop(&mut self) {
        unsafe { tb_shutdown(); }
        println!("Dropped");
    }
}

fn main() {
    let termbox = Termbox::new();

    // Set up the descriptors for select()
    let mut fd_set : libc::fd_set = unsafe { std::mem::zeroed() };

    unsafe { libc::FD_SET(libc::STDIN_FILENO, &mut fd_set); }

    loop {
        let mut fd_set_ = fd_set.clone();
        let ret =
            unsafe {
                libc::select(1,
                             &mut fd_set_,           // read fds
                             std::ptr::null_mut(),   // write fds
                             std::ptr::null_mut(),   // error fds
                             std::ptr::null_mut())   // timeval
            };

        if ret == -1 {
            unsafe { tb_resize(); }
        } else if unsafe { libc::FD_ISSET(0, &mut fd_set_) } {
            let mut buf : Vec<u8> = vec![];
            if read_input_events(&mut buf) {
                let string = format!("{:?}", buf);
                unsafe { tb_clear(); }
                if buf == vec![27] { break; }
                for (char_idx, char) in string.chars().enumerate() {
                    unsafe { tb_change_cell(char_idx as libc::c_int,
                                            0, char as u32, TB_WHITE, TB_DEFAULT); }
                }
                unsafe { tb_present(); }
            }
        }
    }
}

/// Read stdin contents if it's ready for reading. Returns true when it was able
/// to read. Buffer is not modified when return value is 0.
fn read_input_events(buf : &mut Vec<u8>) -> bool {
    let mut bytes_available : i32 = 0; // this really needs to be a 32-bit value
    let ioctl_ret = unsafe { libc::ioctl(libc::STDIN_FILENO, libc::FIONREAD, &mut bytes_available) };
    // println!("ioctl_ret: {}", ioctl_ret);
    // println!("bytes_available: {}", bytes_available);
    if ioctl_ret < 0 || bytes_available == 0 {
        false
    } else {
        buf.clear();
        buf.reserve(bytes_available as usize);

        let buf_ptr : *mut libc::c_void = buf.as_ptr() as *mut libc::c_void;
        let bytes_read = unsafe { libc::read(libc::STDIN_FILENO, buf_ptr, bytes_available as usize) };
        debug_assert!(bytes_read == bytes_available as isize);

        unsafe { buf.set_len(bytes_read as usize); }
        true
    }
}
<commit_msg>Fix termbox_simple example program<commit_after>extern crate libc;
extern crate termbox_simple;

use termbox_simple::*;

fn main() {
    let mut termbox = Termbox::init().unwrap();

    // Set up the descriptors for select()
    let mut fd_set : libc::fd_set = unsafe { std::mem::zeroed() };

    unsafe { libc::FD_SET(libc::STDIN_FILENO, &mut fd_set); }

    loop {
        let mut fd_set_ = fd_set.clone();
        let ret =
            unsafe {
                libc::select(1,
                             &mut fd_set_,           // read fds
                             std::ptr::null_mut(),   // write fds
                             std::ptr::null_mut(),   // error fds
                             std::ptr::null_mut())   // timeval
            };

        if ret == -1 {
            termbox.resize();
        } else if unsafe { libc::FD_ISSET(0, &mut fd_set_) } {
            let mut buf : Vec<u8> = vec![];
            if read_input_events(&mut buf) {
                let string = format!("{:?}", buf);
                termbox.clear();
                if buf == vec![27] { break; }
                for (char_idx, char) in string.chars().enumerate() {
                    termbox.change_cell(char_idx as libc::c_int, 0, char, TB_WHITE, TB_DEFAULT);
                }
                termbox.present();
            }
        }
    }
}

/// Read stdin contents if it's ready for reading. Returns true when it was able
/// to read. Buffer is not modified when return value is 0.
fn read_input_events(buf : &mut Vec<u8>) -> bool {
    let mut bytes_available : i32 = 0; // this really needs to be a 32-bit value
    let ioctl_ret = unsafe { libc::ioctl(libc::STDIN_FILENO, libc::FIONREAD, &mut bytes_available) };
    // println!("ioctl_ret: {}", ioctl_ret);
    // println!("bytes_available: {}", bytes_available);
    if ioctl_ret < 0 || bytes_available == 0 {
        false
    } else {
        buf.clear();
        buf.reserve(bytes_available as usize);

        let buf_ptr : *mut libc::c_void = buf.as_ptr() as *mut libc::c_void;
        let bytes_read = unsafe { libc::read(libc::STDIN_FILENO, buf_ptr, bytes_available as usize) };
        debug_assert!(bytes_read == bytes_available as isize);

        unsafe { buf.set_len(bytes_read as usize); }
        true
    }
}
<|endoftext|>


<commit_before>extern crate orbclient;

use orbclient::Color;

use std::env;
use std::io::{Read, Write};
use std::process::{Command, Stdio};
use std::sync::{Arc, Mutex};
use std::thread;

use window::{ConsoleEvent, ConsoleWindow};

mod window;

fn main() {
    let mut window = ConsoleWindow::new(-1, -1, 576, 400, "Terminal");

    let shell = env::args().nth(1).unwrap_or("sh".to_string());
    match Command::new(&shell)
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
    {
        Ok(process) => {
            let output_mutex = Arc::new(Mutex::new(Vec::new()));

            {
                let mut stdout = process.stdout.unwrap();
                let stdout_output_mutex = output_mutex.clone();
                thread::spawn(move || {
                    'stdout: loop {
                        let mut buf = [0; 4096];
                        match stdout.read(&mut buf) {
                            Ok(0) => break 'stdout,
                            Ok(count) => match stdout_output_mutex.lock() {
                                Ok(mut stdout_output) => stdout_output.extend_from_slice(&buf[..count]),
                                Err(_) => {
                                    println!("failed to lock stdout output mutex");
                                    break 'stdout;
                                }
                            },
                            Err(err) => {
                                println!("failed to read stdout: {}", err);
                                break 'stdout;
                            }
                        }
                    }
                });
            }

            {
                let mut stderr = process.stderr.unwrap();
                let stderr_output_mutex = output_mutex.clone();
                thread::spawn(move || {
                    'stderr: loop {
                        let mut buf = [0; 4096];
                        match stderr.read(&mut buf) {
                            Ok(0) => break 'stderr,
                            Ok(count) => match stderr_output_mutex.lock() {
                                Ok(mut stderr_output) => stderr_output.extend_from_slice(&buf[..count]),
                                Err(_) => {
                                    println!("failed to lock stderr output mutex");
                                    break 'stderr;
                                }
                            },
                            Err(err) => {
                                println!("failed to read stderr: {}", err);
                                break 'stderr;
                            }
                        }
                    }
                });
            }

            let mut stdin = process.stdin.unwrap();
            'events: loop {
                match output_mutex.lock() {
                    Ok(mut output) => {
                        let mut string = String::new();
                        for byte in output.drain(..) {
                            string.push(byte as char);
                        }
                        window.print(&string, Color::rgb(255, 255, 255));
                    },
                    Err(_) => {
                        println!("failed to lock print output mutex");
                        break 'events;
                    }
                }

                for console_event in window.read() {
                    match console_event {
                        ConsoleEvent::Line(mut line) => {
                            line.push('\n');
                            match stdin.write(&line.as_bytes()) {
                                Ok(_) => (),
                                Err(err) => {
                                    println!("failed to write stdin: {}", err);
                                    break 'events;
                                }
                            }
                        },
                        ConsoleEvent::Quit => break 'events
                    }
                }

                thread::sleep_ms(30);
            }
        },
        Err(err) => println!("failed to execute '{}': {}\n", shell, err)
    }
}
<commit_msg>Do not break on 0<commit_after>extern crate orbclient;

use orbclient::Color;

use std::env;
use std::io::{self, Read, Write};
use std::process::{Command, Stdio};
use std::sync::{Arc, Mutex};
use std::thread;

use window::{ConsoleEvent, ConsoleWindow};

mod window;

fn main() {
    let shell = env::args().nth(1).unwrap_or("sh".to_string());
    match Command::new(&shell)
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
    {
        Ok(process) => {
            let output_mutex = Arc::new(Mutex::new(Vec::new()));

            {
                let mut stdout = process.stdout.unwrap();
                let stdout_output_mutex = output_mutex.clone();
                thread::spawn(move || {
                    'stdout: loop {
                        let mut buf = [0; 4096];
                        match stdout.read(&mut buf) {
                            //Ok(0) => break 'stdout,
                            Ok(count) => {
                                match stdout_output_mutex.lock() {
                                    Ok(mut stdout_output) => stdout_output.extend_from_slice(&buf[..count]),
                                    Err(_) => {
                                        println!("failed to lock stdout output mutex");
                                        break 'stdout;
                                    }
                                }
                            },
                            Err(err) => {
                                println!("failed to read stdout: {}", err);
                                break 'stdout;
                            }
                        }
                    }
                });
            }

            {
                let mut stderr = process.stderr.unwrap();
                let stderr_output_mutex = output_mutex.clone();
                thread::spawn(move || {
                    'stderr: loop {
                        let mut buf = [0; 4096];
                        match stderr.read(&mut buf) {
                            //Ok(0) => break 'stderr,
                            Ok(count) => {
                                match stderr_output_mutex.lock() {
                                    Ok(mut stderr_output) => stderr_output.extend_from_slice(&buf[..count]),
                                    Err(_) => {
                                        println!("failed to lock stderr output mutex");
                                        break 'stderr;
                                    }
                                }
                            },
                            Err(err) => {
                                println!("failed to read stderr: {}", err);
                                break 'stderr;
                            }
                        }
                    }
                });
            }

            let mut stdin = process.stdin.unwrap();
            let mut window = ConsoleWindow::new(-1, -1, 576, 400, "Terminal");
            'events: loop {
                match output_mutex.lock() {
                    Ok(mut output) => {
                        let mut string = String::new();
                        for byte in output.drain(..) {
                            string.push(byte as char);
                        }
                        window.print(&string, Color::rgb(255, 255, 255));
                    },
                    Err(_) => {
                        println!("failed to lock print output mutex");
                        break 'events;
                    }
                }

                for console_event in window.read() {
                    match console_event {
                        ConsoleEvent::Line(mut line) => {
                            line.push('\n');
                            match stdin.write(&line.as_bytes()) {
                                Ok(_) => (),
                                Err(err) => {
                                    println!("failed to write stdin: {}", err);
                                    break 'events;
                                }
                            }
                        },
                        ConsoleEvent::Quit => break 'events
                    }
                }

                thread::sleep_ms(30);
            }
        },
        Err(err) => println!("failed to execute '{}': {}\n", shell, err)
    }
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

//! Generic char output trait.

use core::option::{Some, None};
use core::str::{Str, StrSlice};
use core::slice::{Vector, ImmutableVector};
use core::container::Container;
use core::iter::Iterator;

use core::mem::zeroed;

use lib::strconv;

/// CharIO provides interface for outputting characters.
///
/// This trait implements the common functions to output strings and numbers,
/// requiring only one method: `putc`.
pub trait CharIO {
  /// Outputs a character.
  fn putc(&self, value: char);

  /// Outputs a string.
  fn puts(&self, s: &str) {
    let chars : &[u8] = s.as_slice().as_bytes();
    let mut i = 0;
    while i < s.len() {
      let c : char = chars[i] as char;
      self.putc(c);
      i += 1;
    }
  }

  /// Outputs an integer with given base.
  fn putint(&self, i: u32, base: u32) {
    let mut buf : [u8, ..32] = unsafe { zeroed() };
    let bsl : &mut [u8] = buf;
    strconv::itoa(i, bsl, base);

    for &i in bsl.iter() {
      if i == 0 {
        break;
      }
      self.putc(i as char);
    }
  }

  /// Outputs an integer.
  fn puti(&self, i: u32) {
    self.putint(i, 10);
  }

  /// Outputs an integer as a hex string.
  fn puth(&self, i: u32) {
    self.putint(i, 16);
  }
}
<commit_msg>Rename Container to Collection. Fixes #64.<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

//! Generic char output trait.

use core::option::{Some, None};
use core::str::{Str, StrSlice};
use core::slice::{Vector, ImmutableVector};
use core::collections::Collection;
use core::iter::Iterator;

use core::mem::zeroed;

use lib::strconv;

/// CharIO provides interface for outputting characters.
///
/// This trait implements the common functions to output strings and numbers,
/// requiring only one method: `putc`.
pub trait CharIO {
  /// Outputs a character.
  fn putc(&self, value: char);

  /// Outputs a string.
  fn puts(&self, s: &str) {
    let chars : &[u8] = s.as_slice().as_bytes();
    let mut i = 0;
    while i < s.len() {
      let c : char = chars[i] as char;
      self.putc(c);
      i += 1;
    }
  }

  /// Outputs an integer with given base.
  fn putint(&self, i: u32, base: u32) {
    let mut buf : [u8, ..32] = unsafe { zeroed() };
    let bsl : &mut [u8] = buf;
    strconv::itoa(i, bsl, base);

    for &i in bsl.iter() {
      if i == 0 {
        break;
      }
      self.putc(i as char);
    }
  }

  /// Outputs an integer.
  fn puti(&self, i: u32) {
    self.putint(i, 10);
  }

  /// Outputs an integer as a hex string.
  fn puth(&self, i: u32) {
    self.putint(i, 16);
  }
}
<|endoftext|>


<commit_before>use anyhow::Result;
extern crate chrono;
extern crate clap;
extern crate log;

fn run(sig_path: &str, output_path: &str) -> Result<()> {
    let buf = std::fs::read(sig_path)?;
    let buf = lancelot_flirt::sig::unpack_sig(&buf)?;

    std::fs::write(output_path, &buf)?;

    Ok(())
}

fn main() {
    better_panic::install();

    // while the macro form of clap is more readable,
    // it doesn't seem to allow us to use dynamically-generated values,
    // such as the defaults pulled from env vars, etc.
    let matches = clap::App::new("sig2pat")
        .author("Willi Ballenthin <willi.ballenthin@gmail.com>")
        .about("translate a FLIRT .sig file into a .pat file")
        .arg(
            clap::Arg::with_name("verbose")
                .short("v")
                .long("verbose")
                .multiple(true)
                .help("log verbose messages"),
        )
        .arg(
            clap::Arg::with_name("sig")
                .required(true)
                .index(1)
                .help("path to .sig file"),
        )
        .arg(
            clap::Arg::with_name("output")
                .required(true)
                .index(2)
                .help("path to output file"),
        )
        .get_matches();

    let log_level = match matches.occurrences_of("verbose") {
        0 => log::LevelFilter::Info,
        1 => log::LevelFilter::Debug,
        2 => log::LevelFilter::Trace,
        _ => log::LevelFilter::Trace,
    };

    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{} [{:5}] {} {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.level(),
                if log_level == log::LevelFilter::Trace {
                    record.target()
                } else {
                    ""
                },
                message
            ))
        })
        .level(log_level)
        .chain(std::io::stderr())
        .apply()
        .expect("failed to configure logging");

    if let Err(e) = run(matches.value_of("sig").unwrap(), matches.value_of("output").unwrap()) {
        println!("error: {:}", e);
    }
}
<commit_msg>flirt: decompress sig: fix doc<commit_after>use anyhow::Result;
extern crate chrono;
extern crate clap;
extern crate log;

fn run(sig_path: &str, output_path: &str) -> Result<()> {
    let buf = std::fs::read(sig_path)?;
    let buf = lancelot_flirt::sig::unpack_sig(&buf)?;

    std::fs::write(output_path, &buf)?;

    Ok(())
}

fn main() {
    better_panic::install();

    // while the macro form of clap is more readable,
    // it doesn't seem to allow us to use dynamically-generated values,
    // such as the defaults pulled from env vars, etc.
    let matches = clap::App::new("sig2pat")
        .author("Willi Ballenthin <willi.ballenthin@gmail.com>")
        .about("decompress a FLIRT .sig file with compression into one without compression")
        .arg(
            clap::Arg::with_name("verbose")
                .short("v")
                .long("verbose")
                .multiple(true)
                .help("log verbose messages"),
        )
        .arg(
            clap::Arg::with_name("sig")
                .required(true)
                .index(1)
                .help("path to .sig file"),
        )
        .arg(
            clap::Arg::with_name("output")
                .required(true)
                .index(2)
                .help("path to output file"),
        )
        .get_matches();

    let log_level = match matches.occurrences_of("verbose") {
        0 => log::LevelFilter::Info,
        1 => log::LevelFilter::Debug,
        2 => log::LevelFilter::Trace,
        _ => log::LevelFilter::Trace,
    };

    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{} [{:5}] {} {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.level(),
                if log_level == log::LevelFilter::Trace {
                    record.target()
                } else {
                    ""
                },
                message
            ))
        })
        .level(log_level)
        .chain(std::io::stderr())
        .apply()
        .expect("failed to configure logging");

    if let Err(e) = run(matches.value_of("sig").unwrap(), matches.value_of("output").unwrap()) {
        println!("error: {:}", e);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::path;
use std::fs;

use mio::{ TryRead, TryWrite, Evented };
use mio::unix;

use super::{ Transport, Connection, Listener };

pub struct Ipc;

impl Transport for Ipc {

	fn connect(&self, addr: &str) -> io::Result<Box<Connection>> {
		self.connect(path::Path::new(addr))
	}

	fn bind(&self, addr: &str) -> io::Result<Box<Listener>> {
		self.bind(path::Path::new(addr))
	}

}

impl Ipc {

	fn connect(&self, addr: &path::Path) -> Result<Box<Connection>, io::Error> {
		let ipc_stream = try!(unix::UnixStream::connect(&addr));
		let connection = IpcConnection { stream: ipc_stream };

		Ok(Box::new(connection))
	}

	fn bind(&self, path: &path::Path) -> Result<Box<Listener>, io::Error> {
		let _ = fs::remove_file(path);
		let ipc_listener = try!(unix::UnixListener::bind(path));
		let listener = IpcListener { listener: ipc_listener };

		Ok(Box::new(listener))
	}

}

struct IpcConnection {
	stream: unix::UnixStream
}

impl Connection for IpcConnection {
	fn try_read(&mut self, buf: &mut [u8]) -> Result<Option<usize>, io::Error> {
		self.stream.try_read(buf)
	}

	fn try_write(&mut self, buf: &[u8]) -> Result<Option<usize>, io::Error> {
		self.stream.try_write(buf)
	}

	fn as_evented(&self) -> &Evented {
		&self.stream
	}
}

struct IpcListener {
    listener: unix::UnixListener
}

impl Listener for IpcListener {

	fn as_evented(&self) -> &Evented {
		&self.listener
	}

	fn accept(&mut self) -> io::Result<Vec<Box<Connection>>> {
		let mut conns: Vec<Box<Connection>> = Vec::new();

		loop {
			match try!(self.listener.accept()) {
				Some(s) => conns.push(Box::new(IpcConnection { stream: s })),
				None    => break
			}
		}

		Ok(conns)
	}
}
<commit_msg>Adds IPC support on unix platforms<commit_after>use std::io;
use std::path;
use std::fs;

use mio::{ TryRead, TryWrite, Evented };
use mio::unix;

use super::{ Transport, Connection, Listener };

pub struct Ipc;

impl Transport for Ipc {

	fn connect(&self, addr: &str) -> io::Result<Box<Connection>> {
		self.connect(path::Path::new(addr))
	}

	fn bind(&self, addr: &str) -> io::Result<Box<Listener>> {
		self.bind(path::Path::new(addr))
	}

}

impl Ipc {

	fn connect(&self, addr: &path::Path) -> Result<Box<Connection>, io::Error> {
		let ipc_stream = try!(unix::UnixStream::connect(&addr));
		let connection = IpcConnection { stream: ipc_stream };

		Ok(Box::new(connection))
	}

	fn bind(&self, path: &path::Path) -> Result<Box<Listener>, io::Error> {
		if fs::metadata(path).is_ok() {
			let _ = fs::remove_file(path);
		}

		let ipc_listener = try!(unix::UnixListener::bind(path));
		let listener = IpcListener { listener: ipc_listener };

		Ok(Box::new(listener))
	}

}

struct IpcConnection {
	stream: unix::UnixStream
}

impl Connection for IpcConnection {
	fn try_read(&mut self, buf: &mut [u8]) -> Result<Option<usize>, io::Error> {
		self.stream.try_read(buf)
	}

	fn try_write(&mut self, buf: &[u8]) -> Result<Option<usize>, io::Error> {
		self.stream.try_write(buf)
	}

	fn as_evented(&self) -> &Evented {
		&self.stream
	}
}

struct IpcListener {
    listener: unix::UnixListener
}

impl Listener for IpcListener {

	fn as_evented(&self) -> &Evented {
		&self.listener
	}

	fn accept(&mut self) -> io::Result<Vec<Box<Connection>>> {
		let mut conns: Vec<Box<Connection>> = Vec::new();

		loop {
			match try!(self.listener.accept()) {
				Some(s) => conns.push(Box::new(IpcConnection { stream: s })),
				None    => break
			}
		}

		Ok(conns)
	}
}
<|endoftext|>


<commit_before>//! Describe font type

///  cairo_font_type_t is used to describe the type of a given font face or scaled font. The font types are also known as "font backends" within cairo.
///
/// The type of a font face is determined by the function used to create it, which will generally be of the form cairo_type_font_face_create(). The font face type can be queried with cairo_font_face_get_type()
///
/// The various cairo_font_face_t functions can be used with a font face of any type.
///
/// The type of a scaled font is determined by the type of the font face passed to cairo_scaled_font_create(). The scaled font type can be queried with cairo_scaled_font_get_type()
///
/// The various cairo_scaled_font_t functions can be used with scaled fonts of any type, but some font backends also provide type-specific functions that must only be called with a scaled font of the appropriate type. These functions have names that begin with cairo_type_scaled_font() such as cairo_ft_scaled_font_lock_face().
///
/// The behavior of calling a type-specific function with a scaled font of the wrong type is undefined.
///
/// New entries may be added in future versions.
///
/// Since 1.2
#[repr(i32)]
pub enum FontType {
  /// The font was created using cairo's toy font api (Since: 1.2)
  Toy = 0,
  /// The font is of type FreeType (Since: 1.2)
  FT = 1,
  /// The font is of type Win32 (Since: 1.2)
  Win32 = 2,
  /// The font is of type Quartz (Since: 1.6, in 1.2 and 1.4 it was named CAIRO_FONT_TYPE_ATSUI)
  Quartz = 3,
  /// The font was create using cairo's user font api (Since: 1.8)
  User = 4
}

<commit_msg>Replaced Cairo '_t' types with Rust-Cairo types<commit_after>//! Describe font type

/// font::font_type::FontType is used to describe the type of a given font face or scaled font. The font types are also known as "font backends" within cairo.
///
/// The type of a font face is determined by the function used to create it, which will generally be of the form cairo_type_font_face_create(). The font face type can be queried with cairo_font_face_get_type()
///
/// The various cairo_font_face_t functions can be used with a font face of any type.
///
/// The type of a scaled font is determined by the type of the font face passed to cairo_scaled_font_create(). The scaled font type can be queried with cairo_scaled_font_get_type()
///
/// The various cairo_scaled_font_t functions can be used with scaled fonts of any type, but some font backends also provide type-specific functions that must only be called with a scaled font of the appropriate type. These functions have names that begin with cairo_type_scaled_font() such as cairo_ft_scaled_font_lock_face().
///
/// The behavior of calling a type-specific function with a scaled font of the wrong type is undefined.
///
/// New entries may be added in future versions.
///
/// Since 1.2
#[repr(i32)]
pub enum FontType {
  /// The font was created using cairo's toy font api (Since: 1.2)
  Toy = 0,
  /// The font is of type FreeType (Since: 1.2)
  FT = 1,
  /// The font is of type Win32 (Since: 1.2)
  Win32 = 2,
  /// The font is of type Quartz (Since: 1.6, in 1.2 and 1.4 it was named CAIRO_FONT_TYPE_ATSUI)
  Quartz = 3,
  /// The font was create using cairo's user font api (Since: 1.8)
  User = 4
}

<|endoftext|>


<commit_before>//! Handle http requests

use curl;
use error::GGRResult;
use error::GGRError;
use std::cell::RefCell;
use std::cell::RefMut;
use std::fmt;
use std::io::Read;
use std::io::Write;
use url;

/// helper function for Request without body content and with content
fn send_req<W: Write>(handle: &mut curl::easy::Easy,
                     out: &mut W,
                     body: Option<Vec<u8>>)
    -> GGRResult<(u32, Vec<String>)> {
        match body {
            Some(body) => {
                let mut body = &body[..];
                try!(handle.upload(true));
                try!(handle.in_filesize(body.len() as u64));
                handle_req(handle, out, &mut |buf| body.read(buf).unwrap_or(0))
            },
            None => {
                handle_req(handle, out, &mut |_| 0)
            }
        }
}

/// Does the real send
fn handle_req<W: Write>(handle: &mut curl::easy::Easy,
                       out: &mut W,
                       read: &mut FnMut(&mut [u8]) -> usize)
    -> GGRResult<(u32, Vec<String>)> {
        let mut headers = Vec::new();

        {
            let mut handle = handle.transfer();

            try!(handle.read_function(|buf| Ok(read(buf))));
            try!{handle.write_function(|data| {
                Ok(match out.write_all(data) {
                    Ok(_) => data.len(),
                    Err(_) => 0,
                })
            })};

            try!{handle.header_function(|data| {
                headers.push(String::from_utf8_lossy(data).into_owned());
                true
            })};

            try!(handle.perform());
        }

        Ok((try!{handle.response_code()}, headers))
}

pub enum CallMethod {
    Get,
}

/// Transform `CallMethod` type to String
impl fmt::Display for CallMethod {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CallMethod::Get => write!(f, "GET"),
        }
    }
}

/// Represents a HTTP request
///
/// For usage we fill the `CallRequest` with an header and a body. Later we call via `handler` the
/// gerrit server.
pub struct CallRequest<'a> {
    handle: RefMut<'a, curl::easy::Easy>,
    headers: curl::easy::List,
    body: Option<Vec<u8>>,
}

impl<'a> CallRequest<'a> {
    /// creates new instance of [`CallRequest`] with a curl-handler, the HTTP method and the url
    /// endpoint
    pub fn new(mut handle: RefMut<'a, curl::easy::Easy>,
               method: CallMethod,
               url: String)
        -> GGRResult<CallRequest<'a>> {
            let mut headers = curl::easy::List::new();
            // we only want compact json data
            let _ = headers.append("Accept: application/json");

            match method {
                CallMethod::Get => try!{handle.get(true)},
            };

            try!(handle.url(&url));

            Ok(CallRequest {
                handle: handle,
                headers: headers,
                body: None,
            })
    }

    /// helper function to handle a request, write the returned content to a `Write` capabel object
    /// and returns a `CallResponse`.
    fn send_into<W:Write>(mut self, out: &mut W) -> GGRResult<CallResponse> {
        try!(self.handle.http_headers(self.headers));

        let (status, headers) = try!(send_req(&mut self.handle, out, self.body));

        Ok(CallResponse {
            status: status,
            headers: headers,
            body: None,
        })
    }

    /// Does the send function.
    ///
    /// **NOTICE**: The first 4 characters are cutted from the returned content. We want only json
    /// data which has a prevention against XSSI attacks. More here:
    /// <https://gerrit-documentation.storage.googleapis.com/Documentation/2.12.3/rest-api.html#output>
    pub fn send(self) -> GGRResult<CallResponse> {
        let mut out: Vec<u8> = Vec::new();
        let mut rv = try!(self.send_into(&mut out));

        debug!("return-from-server: {:?}", rv);

        /* cut first 4 bytes from output stream */
        if out.starts_with(b")]}'") {
            out = out[4..].into();
        }

        rv.body = Some(out);
        Ok(rv)
    }
}

/// Representation of a Response
#[derive(Debug)]
pub struct CallResponse {
    /// http return status
    pub status: u32,
    /// header of http response
    pub headers: Vec<String>,
    /// the content
    pub body: Option<Vec<u8>>,
}

/// Abstraction of a HTTP call
pub struct Call {
    url: url::Url,
    handle: RefCell<curl::easy::Easy>,
}

impl Call {
    /// Creates a new http call with the base address of a gerrit server
    pub fn new(url: String) -> Call {
        Call {
            url: url::Url::parse(&url).unwrap(),
            handle: RefCell::new(curl::easy::Easy::new()),
        }
    }

    /// Creates a `CallRequest` object with a specific HTTP method and the complete url
    fn request(&self, method:CallMethod, url:String) -> GGRResult<CallRequest> {
        let mut handle = self.handle.borrow_mut();

        try!(handle.cookie_session(true));
        try!(handle.netrc(curl::easy::NetRc::Required));

        CallRequest::new(handle, method, url)
    }

    /// Does a `GET` Request and returns a CallResponse. Only path and querystring is needed. The
    /// base url was setup via [`Call::new()`] function.
    ///
    /// [`Call::new()`]: ./struct.Call.html#method.new
    pub fn get(&self, path: &str, querystring: &str) -> GGRResult<CallResponse> {
        let mut sendurl = self.url.clone();

        let mut path = format!("{}/a/{}", sendurl.path().to_string(), path);

        path = path.replace("//", "/");

        sendurl.set_path(&path);
        sendurl.set_query(Some(querystring));

        debug!("url-to-send: {:?}", sendurl);

        for am in vec!(
            curl::easy::Auth::new().digest(true),
            curl::easy::Auth::new().basic(true)
        ) {
            let mut call_request = try!(self.request(CallMethod::Get, sendurl.to_owned().into_string()));
            try!(call_request.handle.http_auth(am));

            let call_response = try!(call_request.send());
            if call_response.status == 401 {
                continue;
            }

            return Ok(call_response);
        }

        Err(GGRError::General("No Authentication algorithm found for your gerrit server. 'basic' and 'digest' tested".into()))
    }
}
<commit_msg>update curl sources to sentry-cli sources<commit_after>use std::io::{Read, Write};
use std::fmt;
use std::cell::{RefMut, RefCell};
use std::ascii::AsciiExt;

use serde::{Serialize, Deserialize};
use serde_json;
use curl;
use url;

use error::GGRResult;
use error::GGRError;

fn send_req<W: Write>(handle: &mut curl::easy::Easy,
                      out: &mut W,
                      body: Option<Vec<u8>>)
                      -> GGRResult<(u32, Vec<String>)> {
    match body {
        Some(body) => {
            let mut body = &body[..];
            handle.upload(true)?;
            handle.in_filesize(body.len() as u64)?;
            handle_req(handle, out, &mut |buf| body.read(buf).unwrap_or(0))
        }
        None => handle_req(handle, out, &mut |_| 0),
    }
}

fn handle_req<W: Write>(handle: &mut curl::easy::Easy,
                        out: &mut W,
                        read: &mut FnMut(&mut [u8]) -> usize)
                        -> GGRResult<(u32, Vec<String>)> {
    let mut headers = Vec::new();
    {
        let mut handle = handle.transfer();
        handle.read_function(|buf| Ok(read(buf)))?;
        handle.write_function(|data| {
                Ok(match out.write_all(data) {
                    Ok(_) => data.len(),
                    Err(_) => 0,
                })
            })?;
        handle.header_function(|data| {
                headers.push(String::from_utf8_lossy(data).into_owned());
                true
            })?;
        handle.perform()?;
    }

    Ok((handle.response_code()?, headers))
}

#[derive(PartialEq, Debug)]
enum CallMethod {
    Get,
    Post,
    Put,
    Delete,
}

impl fmt::Display for CallMethod {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CallMethod::Get => write!(f, "GET"),
            CallMethod::Post => write!(f, "POST"),
            CallMethod::Put => write!(f, "PUT"),
            CallMethod::Delete => write!(f, "DELETE"),
        }
    }
}

pub struct Call {
    shared_handle: RefCell<curl::easy::Easy>,
    base: url::Url,
}

impl Call {
    pub fn new(url: &url::Url) -> Call {
        Call {
            shared_handle: RefCell::new(curl::easy::Easy::new()),
            base: url.clone(),
        }
    }

    pub fn set_url_query(&mut self, q: Option<&str>) {
        self.base.set_query(q);
    }

    // Low Level Methods

    fn do_request(&self, method: &CallMethod, url: &str) -> GGRResult<CallRequest> {
        let mut handle = self.shared_handle.borrow_mut();
        try!(handle.cookie_session(true));
        try!(handle.netrc(curl::easy::NetRc::Required));

        CallRequest::new(handle, method, url)
    }

    fn request<S: Serialize>(&self, method: CallMethod, path: &str, body: Option<&S>) -> GGRResult<CallResponse> {
        let mut sendurl = self.base.clone();
        sendurl.set_path(path);
        debug!("url-to-send: {:?}", sendurl);

        for am in vec!(
            curl::easy::Auth::new().digest(true),
            curl::easy::Auth::new().basic(true),
        ) {
            let mut call_request = try!(self.do_request(&method, &sendurl.to_owned().into_string()));
            if let Some(body) = body {
                call_request.with_json_body(&body).ok();
            }

            try!(call_request.handle.http_auth(am));
            let call_response = try!(call_request.send());
            if call_response.status == 401 {
                continue;
            }
            return Ok(call_response);
        }
        Err(GGRError::General("No Authentication algorithm found for your gerrit server. 'basic' and 'digest' tested".into()))
    }

    /// Convenience method that performs a `GET` request.
    pub fn get(&self, path: &str) -> GGRResult<CallResponse> {
        self.request::<String>(CallMethod::Get, path, None)
    }

    /// Convenience method that performs a `DELETE` request.
    pub fn delete(&self, path: &str) -> GGRResult<CallResponse> {
        self.request::<String>(CallMethod::Delete, path, None)
    }

    /// Convenience method that performs a `POST` request with JSON data.
    pub fn post<S: Serialize>(&self, path: &str, body: &S) -> GGRResult<CallResponse> {
        self.request(CallMethod::Post, path, Some(body))
    }

    /// Convenience method that performs a `PUT` request with JSON data.
    pub fn put<S: Serialize>(&self, path: &str, body: &S) -> GGRResult<CallResponse> {
        self.request(CallMethod::Put, path, Some(body))
    }
}

/// Iterator over response headers
#[allow(dead_code)]
pub struct Headers<'a> {
    lines: &'a [String],
    idx: usize,
}

impl<'a> Iterator for Headers<'a> {
    type Item = (&'a str, &'a str);

    fn next(&mut self) -> Option<(&'a str, &'a str)> {
        self.lines.get(self.idx).map(|line| {
            self.idx += 1;
            match line.find(':') {
                Some(i) => (&line[..i], line[i + 1..].trim()),
                None => (line[..].trim(), ""),
            }
        })
    }
}

pub struct CallRequest<'a> {
    handle: RefMut<'a, curl::easy::Easy>,
    headers: curl::easy::List,
    body: Option<Vec<u8>>,
}

impl<'a> CallRequest<'a> {
    fn new(mut handle: RefMut<'a, curl::easy::Easy>,
           method: &CallMethod,
           url: &str)
           -> GGRResult<CallRequest<'a>> {
        info!("request {} {}", method, url);

        let mut headers = curl::easy::List::new();
        headers.append("Accept: application/json").ok();

        match *method {
            CallMethod::Get => try!(handle.get(true)),
            CallMethod::Post => try!(handle.custom_request("POST")),
            CallMethod::Put => try!(handle.custom_request("PUT")),
            CallMethod::Delete => try!(handle.custom_request("DELETE")),
        }

        handle.url(url)?;

        Ok(CallRequest {
            handle: handle,
            headers: headers,
            body: None,
        })
    }

    /// adds a specific header to the request
    pub fn with_header(mut self, key: &str, value: &str) -> GGRResult<CallRequest<'a>> {
        self.headers.append(&format!("{}: {}", key, value))?;
        Ok(self)
    }

    /// sets the JSON request body for the request.
    pub fn with_json_body<S: Serialize>(&mut self, body: &S) -> GGRResult<&mut CallRequest<'a>> {
        let mut body_bytes: Vec<u8> = vec![];
        serde_json::to_writer(&mut body_bytes, &body)?;
        info!("sending JSON data ({} bytes)", body_bytes.len());
        self.body = Some(body_bytes);
        self.headers.append("Content-Type: application/json")?;
        Ok(self)
    }

    /// attaches some form data to the request.
    pub fn with_form_data(&mut self, form: curl::easy::Form) -> GGRResult<&mut CallRequest<'a>> {
        info!("sending form data");
        self.handle.httppost(form)?;
        self.body = None;
        Ok(self)
    }

    /// enables or disables redirects.  The default is off.
    pub fn follow_location(&mut self, val: bool) -> GGRResult<&mut CallRequest<'a>> {
        info!("follow redirects: {}", val);
        self.handle.follow_location(val)?;
        Ok(self)
    }

    /// Sends the request and writes response data into the given file
    /// instead of the response object's in memory buffer.
    pub fn send_into<W: Write>(mut self, out: &mut W) -> GGRResult<CallResponse> {
        self.handle.http_headers(self.headers)?;
        let local_body = self.body.clone();
        let (status, headers) = send_req(&mut self.handle, out, local_body)?;
        info!("response: {}", status);
        Ok(CallResponse {
            status: status,
            headers: headers,
            body: None,
        })
    }

    /// Sends the request and reads the response body into the response object.
    pub fn send(self) -> GGRResult<CallResponse> {
        let mut out = vec![];
        let mut rv = self.send_into(&mut out)?;

        debug!("return-from-server: {:?}", rv);

        // cut first 4 bytes from output stream
        // *NOTICE**: The first 4 characters are cutted from the returned content. We want only
        // json data which has a prevention against XSSI attacks. More here:
        // <https://gerrit-documentation.storage.googleapis.com/Documentation/2.12.3/rest-api.html#output>
        if out.starts_with(b")]}'") {
            out = out[4..].into();
        }

        rv.body = Some(out);
        Ok(rv)
    }
}

#[derive(Clone, Debug)]
pub struct CallResponse {
    status: u32,
    headers: Vec<String>,
    body: Option<Vec<u8>>,
}

impl CallResponse {
    /// Returns the status code of the response
    pub fn status(&self) -> u32 {
        self.status
    }

    /// Indicates that the request failed
    pub fn failed(&self) -> bool {
        self.status >= 400 && self.status <= 600
    }

    /// Indicates that the request succeeded
    pub fn ok(&self) -> bool {
        !self.failed()
    }

    /// Converts the response into a result object.  This also converts non okay response codes
    /// into errors.
    pub fn to_result(&self) -> GGRResult<&CallResponse> {
        debug!("headers:");
        for (header_key, header_value) in self.headers() {
            if !header_value.is_empty() {
                debug!("  {}: {}", header_key, header_value);
            }
        }
        if let Some(ref body) = self.body {
            debug!("body: {}", String::from_utf8_lossy(body));
        }
        if self.ok() {
            return Ok(self);
        }
        Err(GGRError::General(format!("generic error: {}", self.status())))
    }

    /// Deserializes the response body into the given type
    pub fn deserialize<T: Deserialize>(&self) -> GGRResult<T> {
        Ok(serde_json::from_reader(match self.body {
            Some(ref body) => body,
            None => &b""[..],
        })?)
    }

    /// Like `deserialize` but consumes the response and will convert
    /// failed requests into proper errors.
    pub fn convert<T: Deserialize>(self) -> GGRResult<T> {
        self.to_result().and_then(|x| x.deserialize())
    }

    /// Iterates over the headers.
    #[allow(dead_code)]
    pub fn headers(&self) -> Headers {
        Headers {
            lines: &self.headers[..],
            idx: 0,
        }
    }

    /// Looks up the first matching header for a key.
    #[allow(dead_code)]
    pub fn get_header(&self, key: &str) -> Option<&str> {
        for (header_key, header_value) in self.headers() {
            if header_key.eq_ignore_ascii_case(key) {
                return Some(header_value);
            }
        }
        None
    }

    pub fn get_body(&self) -> Option<Vec<u8>> {
        self.body.clone()
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::borrow::BorrowMut;
use std::marker::PhantomData;
use std::collections::{HashMap, HashSet};
use context::ContextOf;
use framebuffer::FramebufferBinding;
use program::ProgramAttrib;
use vertex_data::{VertexData, VertexBytes, VertexAttribute};
use index_data::{IndexData, IndexDatum};
use buffer::{Buffer, BufferBinderOf, BufferBinding,
             ArrayBufferBinder, ElementArrayBufferBinder,
             ArrayBufferBinding, ElementArrayBufferBinding};
use types::DrawingMode;

#[derive(Debug)]
pub enum AttribAddError {
    DuplicateAttrib(String)
}

#[derive(Debug)]
pub struct AttribError {
    missing_attribs: Vec<String>,
    unknown_attribs: Vec<String>
}

pub struct AttribBinder {
    attribs: HashMap<String, ProgramAttrib>
}

impl AttribBinder {
    pub fn new() -> Self {
        AttribBinder {
            attribs: HashMap::new()
        }
    }

    pub fn add(&mut self, name: &str, attrib: ProgramAttrib)
        -> Result<(), AttribAddError>
    {
        match self.attribs.insert(name.into(), attrib) {
            None => Ok(()),
            Some(_) => Err(AttribAddError::DuplicateAttrib(name.into()))
        }
    }

    fn for_each<T, F>(&self, mut f: F) -> Result<(), AttribError>
        where T: VertexData, F: FnMut(VertexAttribute, ProgramAttrib)
    {
        // TODO: Avoid heap allocations
        // TODO: Avoid redundant calls to T::visit_attributes
        let mut attribs =
            HashMap::<String, (VertexAttribute, ProgramAttrib)>::new();
        let mut missing = Vec::<String>::new();

        T::visit_attributes(|vertex_attrib| {
            match self.attribs.get(&vertex_attrib.name) {
                Some(program_attrib) => {
                    let pair = (vertex_attrib.clone(), *program_attrib);
                    attribs.insert(vertex_attrib.name, pair);
                },
                None => {
                    missing.push(vertex_attrib.name);
                }
            }
        });

        let unknown: Vec<_> = {
            let expected: HashSet<_> = self.attribs.keys().collect();
            let actual: HashSet<_> = attribs.keys().collect();
            expected.difference(&actual).cloned().cloned().collect()
        };

        if missing.is_empty() && unknown.is_empty() {
            for (_, (vertex_attrib, program_attrib)) in attribs.into_iter() {
                f(vertex_attrib, program_attrib);
            }
            Ok(())
        }
        else {
            Err(AttribError {
                missing_attribs: missing,
                unknown_attribs: unknown
            })
        }
    }

    pub fn enable<V, B, F, P, R, T>(&self, gl: &ContextOf<B, F, P, R, T>)
        -> Result<(), AttribError>
        where V: VertexData
    {
        self.for_each::<V, _>(|_, program_attrib| {
            gl.enable_vertex_attrib_array(program_attrib);
        })
    }

    pub fn bind<V: VertexData>(&self, gl_buffer: &ArrayBufferBinding)
        -> Result<(), AttribError>
    {
        self.for_each::<V, _>(|vertex_attrib, program_attrib| {
            unsafe {
                gl_buffer.vertex_attrib_pointer(
                    program_attrib,
                    vertex_attrib.ty.components,
                    vertex_attrib.ty.data,
                    vertex_attrib.ty.normalize,
                    vertex_attrib.stride,
                    vertex_attrib.offset
                );
            }
        })
    }
}

#[derive(Debug)]
pub enum VertexBindError {
    BindingError(AttribError),
    NoAttributeBindings
}

impl From<AttribError> for VertexBindError {
    fn from(attrib_error: AttribError) -> VertexBindError {
        VertexBindError::BindingError(attrib_error)
    }
}

pub struct VertexBuffer<T: VertexData> {
    attrib_binder: Option<AttribBinder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<V: VertexData> VertexBuffer<V> {
    pub fn bind_attrib_pointers(&mut self, binder: AttribBinder) {
        self.attrib_binder = Some(binder);
    }

    pub fn bind<BA, BE, F, P, R, T>(&mut self,
                                    gl: ContextOf<BufferBinderOf<BA, BE>,
                                                  F,
                                                  P,
                                                  R,
                                                  T>)
        -> Result<(), VertexBindError>
        where BA: BorrowMut<ArrayBufferBinder>
    {
        match self.attrib_binder {
            Some(ref binder) => {
                let (mut ba_binder, mut gl) = gl.split_array_buffer();
                let mut ba_binder = ba_binder.borrow_mut();
                let gl_buffer = ba_binder.bind(&mut self.buffer);
                try!(binder.enable::<V, _, _, _, _, _>(&mut gl));
                try!(binder.bind::<V>(&gl_buffer));
                Ok(())
            },
            None => { Err(VertexBindError::NoAttributeBindings) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData + 'a> {
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData + 'a> VertexBufferBinding<'a, T> {
    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

impl<'a> FramebufferBinding<'a> {
    pub fn draw_arrays_range_vbo<V>(&mut self,
                                    gl_vbo: &VertexBufferBinding<V>,
                                    mode: DrawingMode,
                                    start: u32,
                                    length: usize)
        where V: VertexData
    {
        debug_assert!((start as usize) + length <= gl_vbo.vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    pub fn draw_arrays_vbo<V>(&mut self,
                              gl_vbo: &VertexBufferBinding<V>,
                              mode: DrawingMode)
        where V: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   gl_vbo.vbo.count);
        }
    }

    pub fn draw_n_elements_buffered_vbo<V, I>(&mut self,
                                              gl_vbo: &VertexBufferBinding<V>,
                                              gl_ibo: &IndexBufferBinding<I>,
                                              mode: DrawingMode,
                                              length: usize)
        where V: VertexData, I: IndexDatum
    {
        debug_assert!(length <= gl_ibo.ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    pub fn draw_elements_buffered_vbo<V, I>(&mut self,
                                            gl_vbo: &VertexBufferBinding<V>,
                                            gl_ibo: &IndexBufferBinding<I>,
                                            mode: DrawingMode)
        where V: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          gl_ibo.ibo.count,
                                          I::index_datum_type());
        }
    }

    pub fn draw_n_elements_vbo<V, I>(&mut self,
                                     gl_vbo: &VertexBufferBinding<'a, V>,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indices);
        }
    }

    pub fn draw_elements_vbo<V, I>(&mut self,
                                   gl_vbo: &VertexBufferBinding<'a, V>,
                                   mode: DrawingMode,
                                   indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indices);
        }
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_vertex_buffer<V: VertexData>(&self) -> VertexBuffer<V> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

// TODO: Refactor to work with less restrictive generic params
impl<BA, BE, F, P, R, T> ContextOf<BufferBinderOf<BA, BE>, F, P, R, T> {
    pub fn bind_vertex_buffer<'a, V>(mut self, vbo: &'a mut VertexBuffer<V>)
        -> (
            VertexBufferBinding<V>,
            ContextOf<BufferBinderOf<(), BE>, F, P, R, T>
        )
        where V: VertexData,
              BA: BorrowMut<ArrayBufferBinder>
    {
        // NOTE: The mem::transmute here unsafely extends the borrow of
        //       ibo.buffer_mut()
        // TODO: Find a safe(r) way to do this
        {
            let gl = self.borrowed_mut().map_buffers(|b| b.borrowed_mut());

            vbo.bind(gl).unwrap();
        }
        let (mut ba_binder, gl) = self.split_array_buffer();
        let mut ba_binder = ba_binder.borrow_mut();
        let buffer = unsafe { mem::transmute(vbo.buffer_mut() as *mut Buffer) };
        let gl_array_buffer = ba_binder.bind(buffer);
        (
            VertexBufferBinding {
                gl_buffer: gl_array_buffer,
                vbo: vbo
            },
            gl
        )
    }

    pub fn bind_index_buffer<'a, I>(self, ibo: &'a mut IndexBuffer<I>)
        -> (
            IndexBufferBinding<I>,
            ContextOf<BufferBinderOf<BA, ()>, F, P, R, T>
        )
        where I: IndexDatum + 'a,
              BE: BorrowMut<ElementArrayBufferBinder> + 'a
    {
        // NOTE: The mem::transmute here unsafely extends the borrow of
        //       ibo.buffer_mut()
        // TODO: Find a safe(r) way to do this
        let (mut be_binder, gl) = self.split_element_array_buffer();
        let be_binder = be_binder.borrow_mut();
        let buffer = unsafe { mem::transmute(ibo.buffer_mut() as *mut Buffer) };
        let gl_be = be_binder.bind(buffer);
        (
            IndexBufferBinding {
                gl_buffer: gl_be,
                ibo: ibo
            },
            gl
        )
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_index_buffer<I: IndexDatum>(&self) -> IndexBuffer<I> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let mut binder = $crate::AttribBinder::new();
            $(binder.add(stringify!($field_name), $field_attrib).unwrap());*;
            binder
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = {
                attrib_pointers!($gl, vbo, {
                    $($field_name => $field_attrib),*
                })
            };
            vbo.bind_attrib_pointers(binder);
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            use std::borrow::BorrowMut;
            let mut vbo = $vbo;

            let (gl_vbo, _) = $gl.bind_vertex_buffer(vbo.borrow_mut());
            gl_vbo
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            use std::borrow::BorrowMut;
            let mut ibo = $ibo;

            let (gl_ibo, _) = $gl.bind_index_buffer(ibo.borrow_mut());
            gl_ibo
        }
    }
}
<commit_msg>Refactor `VertexBufferBinding` to be safe<commit_after>use std::mem;
use std::borrow::BorrowMut;
use std::marker::PhantomData;
use std::collections::{HashMap, HashSet};
use context::ContextOf;
use framebuffer::FramebufferBinding;
use program::ProgramAttrib;
use vertex_data::{VertexData, VertexBytes, VertexAttribute};
use index_data::{IndexData, IndexDatum};
use buffer::{Buffer, BufferBinderOf, BufferBinding,
             ArrayBufferBinder, ElementArrayBufferBinder,
             ArrayBufferBinding, ElementArrayBufferBinding};
use types::DrawingMode;

#[derive(Debug)]
pub enum AttribAddError {
    DuplicateAttrib(String)
}

#[derive(Debug)]
pub struct AttribError {
    missing_attribs: Vec<String>,
    unknown_attribs: Vec<String>
}

pub struct AttribBinder {
    attribs: HashMap<String, ProgramAttrib>
}

impl AttribBinder {
    pub fn new() -> Self {
        AttribBinder {
            attribs: HashMap::new()
        }
    }

    pub fn add(&mut self, name: &str, attrib: ProgramAttrib)
        -> Result<(), AttribAddError>
    {
        match self.attribs.insert(name.into(), attrib) {
            None => Ok(()),
            Some(_) => Err(AttribAddError::DuplicateAttrib(name.into()))
        }
    }

    fn for_each<T, F>(&self, mut f: F) -> Result<(), AttribError>
        where T: VertexData, F: FnMut(VertexAttribute, ProgramAttrib)
    {
        // TODO: Avoid heap allocations
        // TODO: Avoid redundant calls to T::visit_attributes
        let mut attribs =
            HashMap::<String, (VertexAttribute, ProgramAttrib)>::new();
        let mut missing = Vec::<String>::new();

        T::visit_attributes(|vertex_attrib| {
            match self.attribs.get(&vertex_attrib.name) {
                Some(program_attrib) => {
                    let pair = (vertex_attrib.clone(), *program_attrib);
                    attribs.insert(vertex_attrib.name, pair);
                },
                None => {
                    missing.push(vertex_attrib.name);
                }
            }
        });

        let unknown: Vec<_> = {
            let expected: HashSet<_> = self.attribs.keys().collect();
            let actual: HashSet<_> = attribs.keys().collect();
            expected.difference(&actual).cloned().cloned().collect()
        };

        if missing.is_empty() && unknown.is_empty() {
            for (_, (vertex_attrib, program_attrib)) in attribs.into_iter() {
                f(vertex_attrib, program_attrib);
            }
            Ok(())
        }
        else {
            Err(AttribError {
                missing_attribs: missing,
                unknown_attribs: unknown
            })
        }
    }

    pub fn enable<V, B, F, P, R, T>(&self, gl: &ContextOf<B, F, P, R, T>)
        -> Result<(), AttribError>
        where V: VertexData
    {
        self.for_each::<V, _>(|_, program_attrib| {
            gl.enable_vertex_attrib_array(program_attrib);
        })
    }

    pub fn bind<V: VertexData>(&self, gl_buffer: &ArrayBufferBinding)
        -> Result<(), AttribError>
    {
        self.for_each::<V, _>(|vertex_attrib, program_attrib| {
            unsafe {
                gl_buffer.vertex_attrib_pointer(
                    program_attrib,
                    vertex_attrib.ty.components,
                    vertex_attrib.ty.data,
                    vertex_attrib.ty.normalize,
                    vertex_attrib.stride,
                    vertex_attrib.offset
                );
            }
        })
    }
}

#[derive(Debug)]
pub enum VertexBindError {
    BindingError(AttribError),
    NoAttributeBindings
}

impl From<AttribError> for VertexBindError {
    fn from(attrib_error: AttribError) -> VertexBindError {
        VertexBindError::BindingError(attrib_error)
    }
}

pub struct VertexBuffer<T: VertexData> {
    attrib_binder: Option<AttribBinder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<V: VertexData> VertexBuffer<V> {
    pub fn bind_attrib_pointers(&mut self, binder: AttribBinder) {
        self.attrib_binder = Some(binder);
    }

    pub fn bind<BA, BE, F, P, R, T>(&mut self,
                                    gl: ContextOf<BufferBinderOf<BA, BE>,
                                                  F,
                                                  P,
                                                  R,
                                                  T>)
        -> Result<(), VertexBindError>
        where BA: BorrowMut<ArrayBufferBinder>
    {
        match self.attrib_binder {
            Some(ref binder) => {
                let (mut ba_binder, mut gl) = gl.split_array_buffer();
                let mut ba_binder = ba_binder.borrow_mut();
                let gl_buffer = ba_binder.bind(&mut self.buffer);
                try!(binder.enable::<V, _, _, _, _, _>(&mut gl));
                try!(binder.bind::<V>(&gl_buffer));
                Ok(())
            },
            None => { Err(VertexBindError::NoAttributeBindings) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData + 'a> {
    gl_buffer: ArrayBufferBinding<'a>,
    count: &'a mut usize,
    _phantom: PhantomData<*const VertexBuffer<T>>
}

impl<'a, T: VertexData + 'a> VertexBufferBinding<'a, T> {
    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        *self.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

impl<'a> FramebufferBinding<'a> {
    pub fn draw_arrays_range_vbo<V>(&mut self,
                                    gl_vbo: &VertexBufferBinding<V>,
                                    mode: DrawingMode,
                                    start: u32,
                                    length: usize)
        where V: VertexData
    {
        debug_assert!((start as usize) + length <= *gl_vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    pub fn draw_arrays_vbo<V>(&mut self,
                              gl_vbo: &VertexBufferBinding<V>,
                              mode: DrawingMode)
        where V: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   *gl_vbo.count);
        }
    }

    pub fn draw_n_elements_buffered_vbo<V, I>(&mut self,
                                              gl_vbo: &VertexBufferBinding<V>,
                                              gl_ibo: &IndexBufferBinding<I>,
                                              mode: DrawingMode,
                                              length: usize)
        where V: VertexData, I: IndexDatum
    {
        debug_assert!(length <= gl_ibo.ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    pub fn draw_elements_buffered_vbo<V, I>(&mut self,
                                            gl_vbo: &VertexBufferBinding<V>,
                                            gl_ibo: &IndexBufferBinding<I>,
                                            mode: DrawingMode)
        where V: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          gl_ibo.ibo.count,
                                          I::index_datum_type());
        }
    }

    pub fn draw_n_elements_vbo<V, I>(&mut self,
                                     gl_vbo: &VertexBufferBinding<'a, V>,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indices);
        }
    }

    pub fn draw_elements_vbo<V, I>(&mut self,
                                   gl_vbo: &VertexBufferBinding<'a, V>,
                                   mode: DrawingMode,
                                   indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indices);
        }
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_vertex_buffer<V: VertexData>(&self) -> VertexBuffer<V> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

// TODO: Refactor to work with less restrictive generic params
impl<BA, BE, F, P, R, T> ContextOf<BufferBinderOf<BA, BE>, F, P, R, T> {
    pub fn bind_vertex_buffer<'a, V>(mut self, vbo: &'a mut VertexBuffer<V>)
        -> (
            VertexBufferBinding<V>,
            ContextOf<BufferBinderOf<(), BE>, F, P, R, T>
        )
        where V: VertexData,
              BA: BorrowMut<ArrayBufferBinder>
    {
        {
            let gl = self.borrowed_mut().map_buffers(|b| b.borrowed_mut());

            vbo.bind(gl).unwrap();
        }
        let (mut ba_binder, gl) = self.split_array_buffer();
        let mut ba_binder = ba_binder.borrow_mut();
        let gl_array_buffer = ba_binder.bind(&mut vbo.buffer);
        (
            VertexBufferBinding {
                gl_buffer: gl_array_buffer,
                count: &mut vbo.count,
                _phantom: PhantomData
            },
            gl
        )
    }

    pub fn bind_index_buffer<'a, I>(self, ibo: &'a mut IndexBuffer<I>)
        -> (
            IndexBufferBinding<I>,
            ContextOf<BufferBinderOf<BA, ()>, F, P, R, T>
        )
        where I: IndexDatum + 'a,
              BE: BorrowMut<ElementArrayBufferBinder> + 'a
    {
        // NOTE: The mem::transmute here unsafely extends the borrow of
        //       ibo.buffer_mut()
        // TODO: Find a safe(r) way to do this
        let (mut be_binder, gl) = self.split_element_array_buffer();
        let be_binder = be_binder.borrow_mut();
        let buffer = unsafe { mem::transmute(ibo.buffer_mut() as *mut Buffer) };
        let gl_be = be_binder.bind(buffer);
        (
            IndexBufferBinding {
                gl_buffer: gl_be,
                ibo: ibo
            },
            gl
        )
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_index_buffer<I: IndexDatum>(&self) -> IndexBuffer<I> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let mut binder = $crate::AttribBinder::new();
            $(binder.add(stringify!($field_name), $field_attrib).unwrap());*;
            binder
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = {
                attrib_pointers!($gl, vbo, {
                    $($field_name => $field_attrib),*
                })
            };
            vbo.bind_attrib_pointers(binder);
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            use std::borrow::BorrowMut;
            let mut vbo = $vbo;

            let (gl_vbo, _) = $gl.bind_vertex_buffer(vbo.borrow_mut());
            gl_vbo
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            use std::borrow::BorrowMut;
            let mut ibo = $ibo;

            let (gl_ibo, _) = $gl.bind_index_buffer(ibo.borrow_mut());
            gl_ibo
        }
    }
}
<|endoftext|>


<commit_before>extern crate glium;

use rand::{thread_rng, Rng};

use math3d::Vertex;
use glium::backend::Facade;
use draw::display_object::DisplayInfo;
use draw::shaders::ShaderManager;

#[derive(Debug, Copy, Clone)]
pub enum TerrainType {
	Water,
	Grass,
	TallGrass,
	Sand,
	Snow,
	Tundra
}

#[derive(Debug)]
pub struct Tile {
	typ:TerrainType,
	height:f32,
}

pub struct Terrain<'a> {
	data:Vec<Tile>,
	display_info:DisplayInfo<'a>,
}

impl<'a> Terrain<'a> {
	pub fn new<F>(display: &F, shader_manager: &ShaderManager, size:u16) -> Terrain<'a> where F: Facade + Clone {
		// load the shader
		let shader = shader_manager.load("identity.vert","identity.frag").unwrap();

		// create the terrain data
		let mut terrain = Terrain {
			data:Vec::with_capacity((size*size) as usize),
			display_info:DisplayInfo { x:0f32, y:0f32, z:0f32, shader:Some(shader) }
		};

		// fill up the terrain with random tiles
		let choices = [
			TerrainType::Water,
			TerrainType::Grass,
			TerrainType::TallGrass,
			TerrainType::Sand,
			TerrainType::Snow,
			TerrainType::Tundra,
		];
		let mut rng = thread_rng();
		for n in 0..(size*size) {
			terrain.data.push(Tile { typ:*rng.choose(&choices).unwrap(), height:0f32 });
		}

		//println!("Terrain: {:?}",terrain.data);

		// generate the geometry for the terrain
		terrain.generate_geometry(display,size);

		terrain
	}

	fn generate_geometry<F>(&mut self, display:&F, size:u16) where F: Facade + Clone {
		// create the vertices
		let mut vertices = Vec::new();
		let size_f = size as f32;
		for index in 0..(size*size) {
			let index_f = index as f32;
			let row = index / size;
			let column = index % size;
			// TODO: generate the actual normals
			vertices.push(Vertex { position:[column as f32, row as f32, self.data[index as usize].height], texcoords:[column as f32/size_f,row as f32/size_f], normal:[0f32,0f32,1f32] });
		}

		// create the vertex buffer
		let vertex_buffer = glium::VertexBuffer::new(display,&vertices).unwrap();

		// create the indices
		let mut indices = Vec::new();
		let columnsize = size - 1;
		for index in 0..(columnsize*columnsize){
			let row = index / columnsize;
			let column = index % columnsize;
			// build the 2 triangles for this square
			let baseindex = row*size+column;
			indices.push(baseindex as u16);
			indices.push(baseindex+size as u16);
			indices.push(baseindex+size+1 as u16 );
			indices.push(baseindex as u16);
			indices.push(baseindex+size+1 as u16);
			indices.push(baseindex+1 as u16 );
		}

		// create the index buffer
		let index_buffer = glium::IndexBuffer::new(display, glium::index::PrimitiveType::TrianglesList, &indices).unwrap();
	}

	pub fn draw(&mut self){

	}
}<commit_msg>Fix lifetime issue<commit_after>extern crate glium;

use rand::{thread_rng, Rng};

use math3d::Vertex;
use glium::backend::Facade;
use draw::display_object::DisplayInfo;
use draw::shaders::ShaderManager;

#[derive(Debug, Copy, Clone)]
pub enum TerrainType {
	Water,
	Grass,
	TallGrass,
	Sand,
	Snow,
	Tundra
}

#[derive(Debug)]
pub struct Tile {
	typ:TerrainType,
	height:f32,
}

pub struct Terrain<'a> {
	data:Vec<Tile>,
	display_info:DisplayInfo<'a>,
}

impl<'a> Terrain<'a> {
	pub fn new<F>(display: &F, shader_manager: &'a ShaderManager, size:u16) -> Terrain<'a> where F: Facade + Clone {
		// load the shader
		let shader = shader_manager.load("identity.vert","identity.frag").unwrap();

		// create the terrain data
		let mut terrain = Terrain {
			data:Vec::with_capacity((size*size) as usize),
			display_info:DisplayInfo { x:0f32, y:0f32, z:0f32, shader:Some(shader) }
		};

		// fill up the terrain with random tiles
		let choices = [
			TerrainType::Water,
			TerrainType::Grass,
			TerrainType::TallGrass,
			TerrainType::Sand,
			TerrainType::Snow,
			TerrainType::Tundra,
		];
		let mut rng = thread_rng();
		for n in 0..(size*size) {
			terrain.data.push(Tile { typ:*rng.choose(&choices).unwrap(), height:0f32 });
		}

		//println!("Terrain: {:?}",terrain.data);

		// generate the geometry for the terrain
		terrain.generate_geometry(display,size);

		terrain
	}

	fn generate_geometry<F>(&mut self, display:&F, size:u16) where F: Facade + Clone {
		// create the vertices
		let mut vertices = Vec::new();
		let size_f = size as f32;
		for index in 0..(size*size) {
			let index_f = index as f32;
			let row = index / size;
			let column = index % size;
			// TODO: generate the actual normals
			vertices.push(Vertex { position:[column as f32, row as f32, self.data[index as usize].height], texcoords:[column as f32/size_f,row as f32/size_f], normal:[0f32,0f32,1f32] });
		}

		// create the vertex buffer
		let vertex_buffer = glium::VertexBuffer::new(display,&vertices).unwrap();

		// create the indices
		let mut indices = Vec::new();
		let columnsize = size - 1;
		for index in 0..(columnsize*columnsize){
			let row = index / columnsize;
			let column = index % columnsize;
			// build the 2 triangles for this square
			let baseindex = row*size+column;
			indices.push(baseindex as u16);
			indices.push(baseindex+size as u16);
			indices.push(baseindex+size+1 as u16 );
			indices.push(baseindex as u16);
			indices.push(baseindex+size+1 as u16);
			indices.push(baseindex+1 as u16 );
		}

		// create the index buffer
		let index_buffer = glium::IndexBuffer::new(display, glium::index::PrimitiveType::TrianglesList, &indices).unwrap();
	}

	pub fn draw(&mut self){

	}
}<|endoftext|>


<commit_before>use cpython::*;

fn test_thread_exit_py(py: Python) -> PyResult<()> {
    let m = py.import("sys")?;
    m.add(py, "exit_thread", py_fn!(py, exit_thread()))?;
    py.run(
        "
import sys, threading
# should not abort
threading.Thread(target=sys.exit_thread).start()
",
        None,
        None,
    )?;
    std::thread::sleep(std::time::Duration::from_millis(100));
    Ok(())
}

// This test requires Rust 1.40, namely
// https://github.com/rust-lang/rust/pull/65646.
//
// `pthread_exit` on Linux raises a C++ `__foced_unwind` exception to unwind
// the stack. That exception does not inherit from C++ `std::exception` and
// must be rethrown if caught, otherwise pthread will abort with
// `FATAL: exception not rethrown`. On the Rust land, `catch_unwind` before
// PR65646 will incorrectly silent that C++ exception without rethrowing,
// breaking this test.
//
// Also skip nightly compilers, which might include some unstable changes
// affecting the test.
#[rustversion::all(since(1.40), stable)]
#[test]
fn test_thread_exit() {
    let gil = Python::acquire_gil();
    let py = gil.python();
    test_thread_exit_py(py).unwrap();
}

fn exit_thread(py: Python) -> PyResult<String> {
    #[cfg(unix)]
    {
        py.allow_threads(|| {
            // Emulates PyThread_exit_thread. It can happen during Py_Finalize.
            unsafe { libc::pthread_exit(std::ptr::null_mut()) };
        })
    }
    #[cfg(not(unix))]
    {
        let _ = py;
        // pthread might not exist on this platform.
        Ok(String::new())
    }
}
<commit_msg>Wrap test_thread_exit sleep with allow_threads<commit_after>use cpython::*;

fn test_thread_exit_py(py: Python) -> PyResult<()> {
    let m = py.import("sys")?;
    m.add(py, "exit_thread", py_fn!(py, exit_thread()))?;
    py.run(
        "
import sys, threading
# should not abort
threading.Thread(target=sys.exit_thread).start()
",
        None,
        None,
    )?;
    py.allow_threads(|| {
        std::thread::sleep(std::time::Duration::from_millis(100));
    });
    Ok(())
}

// This test requires Rust 1.40, namely
// https://github.com/rust-lang/rust/pull/65646.
//
// `pthread_exit` on Linux raises a C++ `__foced_unwind` exception to unwind
// the stack. That exception does not inherit from C++ `std::exception` and
// must be rethrown if caught, otherwise pthread will abort with
// `FATAL: exception not rethrown`. On the Rust land, `catch_unwind` before
// PR65646 will incorrectly silent that C++ exception without rethrowing,
// breaking this test.
//
// Also skip nightly compilers, which might include some unstable changes
// affecting the test.
#[rustversion::all(since(1.40), stable)]
#[test]
fn test_thread_exit() {
    let gil = Python::acquire_gil();
    let py = gil.python();
    test_thread_exit_py(py).unwrap();
}

fn exit_thread(py: Python) -> PyResult<String> {
    #[cfg(unix)]
    {
        py.allow_threads(|| {
            // Emulates PyThread_exit_thread. It can happen during Py_Finalize.
            unsafe { libc::pthread_exit(std::ptr::null_mut()) };
        })
    }
    #[cfg(not(unix))]
    {
        let _ = py;
        // pthread might not exist on this platform.
        Ok(String::new())
    }
}
<|endoftext|>