<commit_before>extern crate pkg_config;
extern crate cmake;

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e{
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    let https = env::var("CARGO_FEATURE_HTTPS").is_ok();
    let ssh = env::var("CARGO_FEATURE_SSH").is_ok();
    if ssh {
        register_dep("SSH2");
    }
    if https {
        register_dep("OPENSSL");
    }
    let has_pkgconfig = Command::new("pkg-config").output().is_ok();

    if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");
    let msvc = target.contains("msvc");
    let mut cfg = cmake::Config::new("libgit2");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cfg.cflag("/GL-");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cfg.define("STATIC_CRT", "OFF");
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install
    // (or when pkg-config isn't found). As a result we just manually turn on
    // SSH support in libgit2 (a little jankily) here...
    if ssh && (windows || !has_pkgconfig) {
        if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
            if msvc {
                cfg.cflag(format!(" /I{}", libssh2_include));
            } else {
                cfg.cflag(format!(" -I{}", libssh2_include));
            }
        }
    }

    if ssh {
        cfg.register_dep("SSH2");
    } else {
        cfg.define("USE_SSH", "OFF");
    }
    if https {
        cfg.register_dep("OPENSSL");
    } else {
        cfg.define("USE_OPENSSL", "OFF");
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
                 .define("BUILD_CLAR", "OFF")
                 .define("CURL", "OFF")
                 .register_dep("Z")
                 .build();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if ssh && !msvc {
        let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
        let mut contents = String::new();
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            panic!("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=winhttp");
        println!("cargo:rustc-link-lib=rpcrt4");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    if env::var("HOST") == env::var("TARGET") {
        // libssh2 is linked in elsehwere, don't want it reported via pkg-config
        let pc = dst.join("lib/pkgconfig/libgit2.pc");
        let mut contents = String::new();
        t!(t!(File::open(&pc)).read_to_string(&mut contents));
        let contents = contents.replace(" -lssh2 ", " ");
        t!(t!(File::create(&pc)).write_all(contents.as_bytes()));

        prepend("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        if pkg_config::Config::new().statik(true).find("libgit2").is_ok() {
            return
        }
    }

    println!("cargo:rustc-link-lib=static=git2");
    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=iconv");
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}
<commit_msg>Be sure to pass -DGIT_SSH when forcing libssh2<commit_after>extern crate pkg_config;
extern crate cmake;

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;

macro_rules! t {
    ($e:expr) => (match $e{
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    let https = env::var("CARGO_FEATURE_HTTPS").is_ok();
    let ssh = env::var("CARGO_FEATURE_SSH").is_ok();
    if ssh {
        register_dep("SSH2");
    }
    if https {
        register_dep("OPENSSL");
    }
    let has_pkgconfig = Command::new("pkg-config").output().is_ok();

    if env::var("LIBGIT2_SYS_USE_PKG_CONFIG").is_ok() {
        if pkg_config::find_library("libgit2").is_ok() {
            return
        }
    }

    let target = env::var("TARGET").unwrap();
    let windows = target.contains("windows");
    let msvc = target.contains("msvc");
    let mut cfg = cmake::Config::new("libgit2");

    if msvc {
        // libgit2 passes the /GL flag to enable whole program optimization, but
        // this requires that the /LTCG flag is passed to the linker later on,
        // and currently the compiler does not do that, so we disable whole
        // program optimization entirely.
        cfg.cflag("/GL-");

        // Currently liblibc links to msvcrt which apparently is a dynamic CRT,
        // so we need to turn this off to get it to link right.
        cfg.define("STATIC_CRT", "OFF");
    }

    // libgit2 uses pkg-config to discover libssh2, but this doesn't work on
    // windows as libssh2 doesn't come with a libssh2.pc file in that install
    // (or when pkg-config isn't found). As a result we just manually turn on
    // SSH support in libgit2 (a little jankily) here...
    if ssh && (windows || !has_pkgconfig) {
        if let Ok(libssh2_include) = env::var("DEP_SSH2_INCLUDE") {
            if msvc {
                cfg.cflag(format!("/I{}", libssh2_include))
                   .cflag("/DGIT_SSH");
            } else {
                cfg.cflag(format!("-I{}", libssh2_include))
                   .cflag("-DGIT_SSH");
            }
        }
    }

    if ssh {
        cfg.register_dep("SSH2");
    } else {
        cfg.define("USE_SSH", "OFF");
    }
    if https {
        cfg.register_dep("OPENSSL");
    } else {
        cfg.define("USE_OPENSSL", "OFF");
    }

    let _ = fs::remove_dir_all(env::var("OUT_DIR").unwrap());
    t!(fs::create_dir_all(env::var("OUT_DIR").unwrap()));

    let dst = cfg.define("BUILD_SHARED_LIBS", "OFF")
                 .define("BUILD_CLAR", "OFF")
                 .define("CURL", "OFF")
                 .register_dep("Z")
                 .build();

    // Make sure libssh2 was detected on unix systems, because it definitely
    // should have been!
    if ssh && !msvc {
        let flags = dst.join("build/CMakeFiles/git2.dir/flags.make");
        let mut contents = String::new();
        t!(t!(File::open(flags)).read_to_string(&mut contents));
        if !contents.contains("-DGIT_SSH") {
            panic!("libgit2 failed to find libssh2, and SSH support is required");
        }
    }

    if target.contains("windows") {
        println!("cargo:rustc-link-lib=winhttp");
        println!("cargo:rustc-link-lib=rpcrt4");
        println!("cargo:rustc-link-lib=ole32");
        println!("cargo:rustc-link-lib=crypt32");
        println!("cargo:rustc-link-lib=static=git2");
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        return
    }

    if env::var("HOST") == env::var("TARGET") {
        // libssh2 is linked in elsehwere, don't want it reported via pkg-config
        let pc = dst.join("lib/pkgconfig/libgit2.pc");
        let mut contents = String::new();
        t!(t!(File::open(&pc)).read_to_string(&mut contents));
        let contents = contents.replace(" -lssh2 ", " ");
        t!(t!(File::create(&pc)).write_all(contents.as_bytes()));

        prepend("PKG_CONFIG_PATH", dst.join("lib/pkgconfig"));
        if pkg_config::Config::new().statik(true).find("libgit2").is_ok() {
            return
        }
    }

    println!("cargo:rustc-link-lib=static=git2");
    println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
    if target.contains("apple") {
        println!("cargo:rustc-link-lib=iconv");
    }
}

fn register_dep(dep: &str) {
    match env::var(&format!("DEP_{}_ROOT", dep)) {
        Ok(s) => {
            prepend("PKG_CONFIG_PATH", Path::new(&s).join("lib/pkgconfig"));
        }
        Err(..) => {}
    }
}

fn prepend(var: &str, val: PathBuf) {
    let prefix = env::var(var).unwrap_or(String::new());
    let mut v = vec![val];
    v.extend(env::split_paths(&prefix));
    env::set_var(var, &env::join_paths(v).unwrap());
}
<|endoftext|>


<commit_before>// Copyright 2016 The Gfx-rs Developers.
//
// 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.

#[deny(missing_docs)]

#[macro_use]
extern crate log;
#[macro_use]
extern crate objc;
extern crate cocoa;
extern crate winit;
extern crate metal;
extern crate gfx_core;
extern crate gfx_device_metal;

use winit::os::macos::WindowExt;

use objc::runtime::{Object, Class, BOOL, YES, NO};

use cocoa::base::id as cocoa_id;
use cocoa::base::{selector, class};
use cocoa::foundation::{NSUInteger, NSSize};
use cocoa::appkit::{NSApp,
                    NSApplication, NSApplicationActivationPolicyRegular,
                    NSWindow, NSTitledWindowMask, NSBackingStoreBuffered,
                    NSMenu, NSMenuItem, NSRunningApplication, NSView,
                    NSApplicationActivateIgnoringOtherApps};

use gfx_core::tex::Size;
use gfx_core::format::{RenderFormat, Format};
use gfx_core::handle::{RawRenderTargetView, RenderTargetView};

use gfx_device_metal::{Device, Factory, Resources};

use metal::*;

use winit::{Window};

use std::ops::Deref;
use std::cell::Cell;
use std::mem;

pub struct MetalWindow {
    window: winit::Window,
    layer: CAMetalLayer,
    drawable: *mut CAMetalDrawable,
    backbuffer: *mut MTLTexture
}

impl Deref for MetalWindow {
    type Target = winit::Window;

    fn deref(&self) -> &winit::Window {
        &self.window
    }
}

impl MetalWindow {
    pub fn swap_buffers(&self) -> Result<(), ()> {
        // FIXME: release drawable before swapping
        // TODO: did we fail to swap buffers?
        // TODO: come up with alternative to this hack

        unsafe {
            //self.pool.get().drain();
            //self.pool.set(NSAutoreleasePool::alloc().init());

            let drawable = self.layer.next_drawable().unwrap();
            //drawable.retain();

            if !(*self.drawable).is_null() {
                (*self.drawable).release();
            }

            *self.drawable = drawable;

            *self.backbuffer = drawable.texture();
        }

        Ok(())
    }
}

#[derive(Copy, Clone, Debug)]
pub enum InitError {
    /// Unable to create a window.
    Window,
    /// Unable to map format to Metal.
    Format(Format),
    /// Unable to find a supported driver type.
    DriverType,
}

pub fn init<C: RenderFormat>(title: &str, requested_width: u32, requested_height: u32)
        -> Result<(MetalWindow, Device, Factory, RenderTargetView<Resources, C>), InitError>
{
    use gfx_core::factory::Typed;

    init_raw(title, requested_width, requested_height, C::get_format())
        .map(|(window, device, factory, color)| (window, device, factory, Typed::new(color)))
}

/// Initialize with a given size. Raw format version.
pub fn init_raw(title: &str, requested_width: u32, requested_height: u32, color_format: Format)
        -> Result<(MetalWindow, Device, Factory, RawRenderTargetView<Resources>), InitError>
{
    let winit_window = winit::WindowBuilder::new()
        .with_dimensions(requested_width, requested_height)
        .with_title(title.to_string()).build().unwrap();

    unsafe {
        let wnd: cocoa_id = mem::transmute(winit_window.get_nswindow());

        let layer = CAMetalLayer::layer();
        layer.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
        /*layer.set_pixel_format(match gfx_device_metal::map_format(color_format, true) {
            Some(fm) => fm,
            None => return Err(InitError::Format(color_format)),
        });*/
        let draw_size = winit_window.get_inner_size().unwrap();
        layer.set_drawable_size(NSSize::new(draw_size.0 as f64, draw_size.1 as f64));
        layer.set_presents_with_transaction(false);
        layer.remove_all_animations();

        let view = wnd.contentView();
        view.setWantsLayer(YES);
        view.setLayer(mem::transmute(layer.0));

        let (mut device, factory, color, daddr, addr) = gfx_device_metal::create(color_format, draw_size.0, draw_size.1).unwrap();
        layer.set_device(device.device);

        let drawable = layer.next_drawable().unwrap();

        let window = MetalWindow {
            window: winit_window,
            layer: layer,
            drawable: daddr,
            backbuffer: addr
        };

        (*daddr).0 = drawable.0;
        (*addr).0 = drawable.texture().0;

        Ok((window, device, factory, color))
    }
}
<commit_msg>[metal] fixed warnings in the windowing code<commit_after>// Copyright 2016 The Gfx-rs Developers.
//
// 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.

#[deny(missing_docs)]

#[macro_use]
extern crate log;
#[macro_use]
extern crate objc;
extern crate cocoa;
extern crate winit;
extern crate metal;
extern crate gfx_core;
extern crate gfx_device_metal;

use winit::os::macos::WindowExt;

use objc::runtime::{YES};

use cocoa::base::id as cocoa_id;
//use cocoa::base::{selector, class};
use cocoa::foundation::{NSSize};
use cocoa::appkit::{NSWindow, NSView};

//use gfx_core::tex::Size;
use gfx_core::format::{RenderFormat, Format};
use gfx_core::handle::{RawRenderTargetView, RenderTargetView};

use gfx_device_metal::{Device, Factory, Resources};

use metal::*;

//use winit::{Window};

use std::ops::Deref;
//use std::cell::Cell;
use std::mem;

pub struct MetalWindow {
    window: winit::Window,
    layer: CAMetalLayer,
    drawable: *mut CAMetalDrawable,
    backbuffer: *mut MTLTexture
}

impl Deref for MetalWindow {
    type Target = winit::Window;

    fn deref(&self) -> &winit::Window {
        &self.window
    }
}

impl MetalWindow {
    pub fn swap_buffers(&self) -> Result<(), ()> {
        // FIXME: release drawable before swapping
        // TODO: did we fail to swap buffers?
        // TODO: come up with alternative to this hack

        unsafe {
            //self.pool.get().drain();
            //self.pool.set(NSAutoreleasePool::alloc().init());

            let drawable = self.layer.next_drawable().unwrap();
            //drawable.retain();

            if !(*self.drawable).is_null() {
                (*self.drawable).release();
            }

            *self.drawable = drawable;

            *self.backbuffer = drawable.texture();
        }

        Ok(())
    }
}

#[derive(Copy, Clone, Debug)]
pub enum InitError {
    /// Unable to create a window.
    Window,
    /// Unable to map format to Metal.
    Format(Format),
    /// Unable to find a supported driver type.
    DriverType,
}

pub fn init<C: RenderFormat>(title: &str, requested_width: u32, requested_height: u32)
        -> Result<(MetalWindow, Device, Factory, RenderTargetView<Resources, C>), InitError>
{
    use gfx_core::factory::Typed;

    init_raw(title, requested_width, requested_height, C::get_format())
        .map(|(window, device, factory, color)| (window, device, factory, Typed::new(color)))
}

/// Initialize with a given size. Raw format version.
pub fn init_raw(title: &str, requested_width: u32, requested_height: u32, color_format: Format)
        -> Result<(MetalWindow, Device, Factory, RawRenderTargetView<Resources>), InitError>
{
    let winit_window = winit::WindowBuilder::new()
        .with_dimensions(requested_width, requested_height)
        .with_title(title.to_string()).build().unwrap();

    unsafe {
        let wnd: cocoa_id = mem::transmute(winit_window.get_nswindow());

        let layer = CAMetalLayer::layer();
        layer.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
        /*layer.set_pixel_format(match gfx_device_metal::map_format(color_format, true) {
            Some(fm) => fm,
            None => return Err(InitError::Format(color_format)),
        });*/
        let draw_size = winit_window.get_inner_size().unwrap();
        layer.set_drawable_size(NSSize::new(draw_size.0 as f64, draw_size.1 as f64));
        layer.set_presents_with_transaction(false);
        layer.remove_all_animations();

        let view = wnd.contentView();
        view.setWantsLayer(YES);
        view.setLayer(mem::transmute(layer.0));

        let (device, factory, color, daddr, addr) = gfx_device_metal::create(color_format, draw_size.0, draw_size.1).unwrap();
        layer.set_device(device.device);

        let drawable = layer.next_drawable().unwrap();

        let window = MetalWindow {
            window: winit_window,
            layer: layer,
            drawable: daddr,
            backbuffer: addr
        };

        (*daddr).0 = drawable.0;
        (*addr).0 = drawable.texture().0;

        Ok((window, device, factory, color))
    }
}
<|endoftext|>


<commit_before>//! OAuth 1
//!
//!# Example
//!
//! TODO
extern crate time;

use std::default::Default;
use std::fmt;
use self::time::now_utc;
use std::rand::{thread_rng, Rng};

#[derive(Copy, Show, PartialEq, Eq, Clone)]
#[unstable]
/// Signature Type
pub enum SignatureMethod {
    /// HMAC-SHA1
    HMAC_SHA1,
    /// RSA-SHA1
    RSA_SHA1,
    /// PLAINTEXT
    PLAINTEXT
}

impl Default for SignatureMethod {
    fn default() -> SignatureMethod {
        SignatureMethod::HMAC_SHA1}
}

impl fmt::String for SignatureMethod {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result{
        let out = match *self {
            SignatureMethod::HMAC_SHA1 => {"HMAC-SHA1"},
            SignatureMethod::RSA_SHA1  => {"RSA-SHA1"},
            SignatureMethod::PLAINTEXT => {"PLAINTEXT"}
        };
        write!(f, "{}", out)
    }
}

/// A generic trait for retrieving the authorization header from a value
pub trait AuthorizationHeader {
    fn get_header(&self) -> String;
}

#[unstable]
pub struct Session<'a> {
    oauth_consumer_key : &'a str,
    oauth_token : &'a str,
    oauth_token_secret : &'a str,
    oauth_signature_method : SignatureMethod,
    oauth_signature : &'a str,
}

// TODO: add to crypto library?
// TODO: Should we have a longer nonce than 10?
fn generate_nonce() -> String {
    thread_rng().gen_ascii_chars()
                .take(10)
                .collect()
}

// Creates a Session Object, which contains all reused
// parameters for OAuth 1.0A
impl<'a> Session<'a> {
    pub fn new (consumer_key: &'a str, token: &'a str, secret: &'a str,
                signature_method: SignatureMethod) -> Session<'a> {
        Session {
            oauth_consumer_key: consumer_key,
            oauth_token: token,
            oauth_token_secret : secret,
            oauth_signature_method: signature_method,
            oauth_signature: "TODO",
        }
    }
}

// Creates a URL encoded String containing headers
// This should be called everytime you make a request, since the
// `oauth_timestamp` and `oauth_nonce` need to freshly made

impl<'a> AuthorizationHeader for Session<'a>{
    fn get_header(&self) -> String {
        let header = format!("oauth_consumer_key={}&oauth_signature={}\
                            &oauth_signature_method={}&oauth_token={}\
                            &oauth_version=1.0",
        self.oauth_consumer_key, self.oauth_signature,
        self.oauth_signature_method, self.oauth_token);

        match self.oauth_signature_method {
            SignatureMethod::PLAINTEXT => header,
            _ => format!("{}, oauth_timestamp=\"{}\", oauth_nonce=\"{}\"",
                        header, now_utc().to_timespec().sec, generate_nonce())
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate curl;
    use self::curl::http;
    use super::{Session, SignatureMethod, AuthorizationHeader};

    // Session initialization and setup test
    #[test]
    fn hw() {
        let s = Session::new("k0azC44q2c0DgF7ua9YZ6Q",
                            "119544186-6YZKqkECA9Z0bxq9bA1vzzG7tfPotCml4oTySkzj",
                            "zvNmU9daj9V00118H9KQBozQQsZt4pyLQcZdc",
                            SignatureMethod::HMAC_SHA1);
        println!("{}", s.get_header());
    }
}

#[derive(Clone)]
pub struct Builder<'a> {
    request_url         : &'a str,
    consumer_key        : &'a str,
    callback_url        : &'a str,
    signature_method    : SignatureMethod,
    require_nonce       : bool,
    require_timestamp   : bool,
    realm               : Option<&'a str>
}

impl<'a> Builder<'a> {
    pub fn new(request_url : &'a str, consumer_key : &'a str, callback_url : &'a str, signature_method : SignatureMethod) -> Builder<'a> {
        let require = match signature_method {SignatureMethod::PLAINTEXT => false, _ => true};
        Builder {
            request_url         : request_url,
            consumer_key        : consumer_key,
            callback_url        : callback_url,
            signature_method    : signature_method,
            require_nonce       : require,
            require_timestamp   : require,
            version             : None,
            realm               : None
        }
    }

    pub fn set_realm(mut self, realm : &'a str) -> Builder<'a> {
        self.realm = Some(realm);
        self
    }

    pub fn require_nonce(mut self) -> Builder<'a> {
        self.require_nonce = true;
        self
    }

    pub fn require_timestamp(mut self) -> Builder<'a> {
        self.require_timestamp = true;
        self
    }

    pub fn create(self) -> TemporaryCredentialsRequest<'a> {
        TemporaryCredentialsRequest {
            request_url         : self.request_url,
            consumer_key        : self.consumer_key,
            callback_url        : self.callback_url,
            signature_method    : self.signature_method,
            realm               : self.realm,
            require_nonce       : self.require_nonce,
            require_timestamp   : self.require_timestamp

        }
    }
}

#[derive(Clone)]
pub struct TemporaryCredentialsRequest<'a> {
    request_url         : &'a str,
    consumer_key        : &'a str,
    callback_url        : &'a str,
    signature_method    : SignatureMethod,
    realm               : Option<&'a str>,
    require_nonce       : bool,
    require_timestamp   : bool
}

impl<'a> TemporaryCredentialsRequest<'a> {
    pub fn get_temporary_credentials(self)->Result<TemporaryCredentials,()>{
        Ok(TemporaryCredentials{oauth_token: Default::default(), oauth_token_secret: Default::default()})
    }
}

impl<'a> AuthorizationHeader for TemporaryCredentialsRequest<'a> {
    fn get_header(&self) -> String {
        Default::default()
    }
}

#[derive(Clone)]
pub struct TemporaryCredentials {
    oauth_token        : String,
    oauth_token_secret : String
}
<commit_msg>Forgot to remove version from Builder<commit_after>//! OAuth 1
//!
//!# Example
//!
//! TODO
extern crate time;

use std::default::Default;
use std::fmt;
use self::time::now_utc;
use std::rand::{thread_rng, Rng};

#[derive(Copy, Show, PartialEq, Eq, Clone)]
#[unstable]
/// Signature Type
pub enum SignatureMethod {
    /// HMAC-SHA1
    HMAC_SHA1,
    /// RSA-SHA1
    RSA_SHA1,
    /// PLAINTEXT
    PLAINTEXT
}

impl Default for SignatureMethod {
    fn default() -> SignatureMethod {
        SignatureMethod::HMAC_SHA1}
}

impl fmt::String for SignatureMethod {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result{
        let out = match *self {
            SignatureMethod::HMAC_SHA1 => {"HMAC-SHA1"},
            SignatureMethod::RSA_SHA1  => {"RSA-SHA1"},
            SignatureMethod::PLAINTEXT => {"PLAINTEXT"}
        };
        write!(f, "{}", out)
    }
}

/// A generic trait for retrieving the authorization header from a value
pub trait AuthorizationHeader {
    fn get_header(&self) -> String;
}

#[unstable]
pub struct Session<'a> {
    oauth_consumer_key : &'a str,
    oauth_token : &'a str,
    oauth_token_secret : &'a str,
    oauth_signature_method : SignatureMethod,
    oauth_signature : &'a str,
}

// TODO: add to crypto library?
// TODO: Should we have a longer nonce than 10?
fn generate_nonce() -> String {
    thread_rng().gen_ascii_chars()
                .take(10)
                .collect()
}

// Creates a Session Object, which contains all reused
// parameters for OAuth 1.0A
impl<'a> Session<'a> {
    pub fn new (consumer_key: &'a str, token: &'a str, secret: &'a str,
                signature_method: SignatureMethod) -> Session<'a> {
        Session {
            oauth_consumer_key: consumer_key,
            oauth_token: token,
            oauth_token_secret : secret,
            oauth_signature_method: signature_method,
            oauth_signature: "TODO",
        }
    }
}

// Creates a URL encoded String containing headers
// This should be called everytime you make a request, since the
// `oauth_timestamp` and `oauth_nonce` need to freshly made

impl<'a> AuthorizationHeader for Session<'a>{
    fn get_header(&self) -> String {
        let header = format!("oauth_consumer_key={}&oauth_signature={}\
                            &oauth_signature_method={}&oauth_token={}\
                            &oauth_version=1.0",
        self.oauth_consumer_key, self.oauth_signature,
        self.oauth_signature_method, self.oauth_token);

        match self.oauth_signature_method {
            SignatureMethod::PLAINTEXT => header,
            _ => format!("{}, oauth_timestamp=\"{}\", oauth_nonce=\"{}\"",
                        header, now_utc().to_timespec().sec, generate_nonce())
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate curl;
    use self::curl::http;
    use super::{Session, SignatureMethod, AuthorizationHeader};

    // Session initialization and setup test
    #[test]
    fn hw() {
        let s = Session::new("k0azC44q2c0DgF7ua9YZ6Q",
                            "119544186-6YZKqkECA9Z0bxq9bA1vzzG7tfPotCml4oTySkzj",
                            "zvNmU9daj9V00118H9KQBozQQsZt4pyLQcZdc",
                            SignatureMethod::HMAC_SHA1);
        println!("{}", s.get_header());
    }
}

#[derive(Clone)]
pub struct Builder<'a> {
    request_url         : &'a str,
    consumer_key        : &'a str,
    callback_url        : &'a str,
    signature_method    : SignatureMethod,
    require_nonce       : bool,
    require_timestamp   : bool,
    realm               : Option<&'a str>
}

impl<'a> Builder<'a> {
    pub fn new(request_url : &'a str, consumer_key : &'a str, callback_url : &'a str, signature_method : SignatureMethod) -> Builder<'a> {
        let require = match signature_method {SignatureMethod::PLAINTEXT => false, _ => true};
        Builder {
            request_url         : request_url,
            consumer_key        : consumer_key,
            callback_url        : callback_url,
            signature_method    : signature_method,
            require_nonce       : require,
            require_timestamp   : require,
            realm               : None
        }
    }

    pub fn set_realm(mut self, realm : &'a str) -> Builder<'a> {
        self.realm = Some(realm);
        self
    }

    pub fn require_nonce(mut self) -> Builder<'a> {
        self.require_nonce = true;
        self
    }

    pub fn require_timestamp(mut self) -> Builder<'a> {
        self.require_timestamp = true;
        self
    }

    pub fn create(self) -> TemporaryCredentialsRequest<'a> {
        TemporaryCredentialsRequest {
            request_url         : self.request_url,
            consumer_key        : self.consumer_key,
            callback_url        : self.callback_url,
            signature_method    : self.signature_method,
            realm               : self.realm,
            require_nonce       : self.require_nonce,
            require_timestamp   : self.require_timestamp

        }
    }
}

#[derive(Clone)]
pub struct TemporaryCredentialsRequest<'a> {
    request_url         : &'a str,
    consumer_key        : &'a str,
    callback_url        : &'a str,
    signature_method    : SignatureMethod,
    realm               : Option<&'a str>,
    require_nonce       : bool,
    require_timestamp   : bool
}

impl<'a> TemporaryCredentialsRequest<'a> {
    pub fn get_temporary_credentials(self)->Result<TemporaryCredentials,()>{
        Ok(TemporaryCredentials{oauth_token: Default::default(), oauth_token_secret: Default::default()})
    }
}

impl<'a> AuthorizationHeader for TemporaryCredentialsRequest<'a> {
    fn get_header(&self) -> String {
        Default::default()
    }
}

#[derive(Clone)]
pub struct TemporaryCredentials {
    oauth_token        : String,
    oauth_token_secret : String
}
<|endoftext|>


<commit_before>// 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.

// Parser nodes represent the grammar that is defined
// by the currently permissible set of commands and their
// parameters.

use std::rc::Rc;

use super::{Completion, Parser};
use super::constants::*;
use tokenizer::Token;

/// Enumeration of node types used to have vectors of `Node` and so on.
pub enum Node {
    /// `Node` variant wrapping a `CommandNode`.
    Command(CommandNode),
    /// `Node` variant wrapping a `ParameterNode`.
    Parameter(ParameterNode),
    /// `Node` variant wrapping a `ParameterNameNode`.
    ParameterName(ParameterNameNode),
    /// `Node` variant wrapping a `RootNode`.
    Root(RootNode),
}

/// The operations that every node must implement.
pub trait NodeOps {
    /// Accept this node with the given `token` as data.
    ///
    /// By default, nothing needs to happen for `accept`.
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token);

    /// Can this node be accepted in the current parser state?
    /// By default, a node can be accepted when it hasn't been seen yet.
    fn acceptable(&self, _parser: &Parser) -> bool;

    /// Given a node and an optional token, provide the completion options.
    ///
    /// By default, completion should complete for the name of the given
    /// node.
    ///
    /// This is the expected behavior for [`CommandNode`] as well as
    /// [`ParameterNameNode`].
    ///
    /// [`CommandNode`]: struct.CommandNode.html
    /// [`ParameterNameNode`]: struct.ParameterNameNode.html
    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text>;

    /// By default, a node matches a `token` when the name of the
    /// node starts with the `token`.
    ///
    /// This is the desired behavior for ...
    fn matches(&self, _parser: &Parser, token: Token) -> bool;
}

/// A parse tree node.
pub struct TreeNode {
    /// The name of this node.
    pub name: String,
    /// The text used to identify this node in help text.
    /// This is typically the node name, either in plain
    /// form or decorated for parameters.
    pub help_symbol: String,
    /// Help text describing this node.
    pub help_text: String,
    /// Hidden nodes are not completed. This doesn't modify matching.
    pub hidden: bool,
    /// Match and complete priority.
    pub priority: i32,
    /// Whether or not this node can be repeated. A repeated
    /// node can be `accept`ed multiple times.
    pub repeatable: bool,
    /// If present, this node will no longer be `acceptable`.
    pub repeat_marker: Option<Rc<Node>>,
    /// Possible successor nodes. Collected while building.
    pub successors: Vec<Rc<Node>>,
}

/// The root of a command tree.
pub struct RootNode {
    /// `TreeNode` data.
    pub node: TreeNode,
}

/// A node representing a command. Constructed via [`Command`] and [`CommandTree`].
///
/// If `wrapped_root` is set then this node wraps another command.
/// This is used for the help command so that it can complete
/// normal commands. The `successors` will be those of the wrapped node.
///
/// [`Command`]: struct.Command.html
/// [`CommandTree`]: struct.CommandTree.html
pub struct CommandNode {
    /// `TreeNode` data.
    pub node: TreeNode,
    /// The handler which is executed once this node has been accepted.
    pub handler: Option<fn(&node: Node) -> ()>,
    /// Parameter nodes for this command
    ///
    /// XXX: This should be Vec<Rc<ParameterNode>> or similar.
    pub parameters: Vec<Rc<Node>>,
    /// If present, the command wrapped by this node.
    pub wrapped_root: Option<Rc<Node>>,
}

/// A node that represented the name portion of a named
/// parameter.
pub struct ParameterNameNode {
    /// `TreeNode` data.
    pub node: TreeNode,
    /// The `parameter` named by this node.
    ///
    /// XXX: This should be Rc<ParameterNode> or similar.
    pub parameter: Rc<Node>,
}

/// A node representing a parameter for a command.
pub struct ParameterNode {
    /// `TreeNode` data.
    pub node: TreeNode,
    /// A `required` parameter must be supplied for the
    /// command line being parsed to be valid.
    pub required: bool,
    /// What type of `ParameterKind` this is.
    pub kind: ParameterKind,
}

impl PartialEq for Node {
    /// Nodes are equal based on pointer equality.
    fn eq(&self, other: &Self) -> bool {
        self as *const _ == other as *const _
    }
}

/// The node in the tree of commands and parameters used in the
/// parser.
///
/// This trait defines the core operations which a node must
/// support.
impl Node {
    /// Get the `TreeNode` data for a given `Node`.
    pub fn node(&self) -> &TreeNode {
        match *self {
            Node::Command(ref command) => &command.node,
            Node::Parameter(ref parameter) => &parameter.node,
            Node::ParameterName(ref name) => &name.node,
            Node::Root(ref root) => &root.node,
        }
    }

    /// Get or calculate successors of this node.
    pub fn successors(&self) -> &Vec<Rc<Node>> {
        match *self {
            Node::Root(ref root) => &root.node.successors,
            _ => &self.node().successors,
        }
    }
}

impl NodeOps for Node {
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token) {
        match *self {
            Node::Command(ref command) => command.accept(parser, token),
            Node::Parameter(ref parameter) => parameter.accept(parser, token),
            Node::ParameterName(ref name) => name.accept(parser, token),
            Node::Root(ref root) => root.accept(parser, token),
        }
    }

    fn acceptable(&self, parser: &Parser) -> bool {
        match *self {
            Node::Command(ref command) => command.acceptable(parser),
            Node::Parameter(ref parameter) => parameter.acceptable(parser),
            Node::ParameterName(ref name) => name.acceptable(parser),
            Node::Root(ref root) => root.acceptable(parser),
        }
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        match *self {
            Node::Command(ref command) => command.complete(token),
            Node::Parameter(ref parameter) => parameter.complete(token),
            Node::ParameterName(ref name) => name.complete(token),
            Node::Root(ref root) => root.complete(token),
        }
    }

    fn matches(&self, parser: &Parser, token: Token) -> bool {
        match *self {
            Node::Command(ref command) => command.matches(parser, token),
            Node::Parameter(ref parameter) => parameter.matches(parser, token),
            Node::ParameterName(ref name) => name.matches(parser, token),
            Node::Root(ref root) => root.matches(parser, token),
        }
    }
}

impl RootNode {
    /// Create a new `RootNode`
    pub fn new(successors: Vec<Rc<Node>>) -> Self {
        RootNode {
            node: TreeNode {
                name: "__root__".to_string(),
                help_symbol: "".to_string(),
                help_text: "".to_string(),
                hidden: false,
                priority: PRIORITY_DEFAULT,
                repeat_marker: None,
                repeatable: false,
                successors: successors,
            },
        }
    }
}

impl NodeOps for RootNode {
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token) {}

    fn acceptable(&self, _parser: &Parser) -> bool {
        false
    }

    /// A `RootNode` can not be completed.
    fn complete<'text>(&self, _token: Option<Token<'text>>) -> Completion<'text> {
        panic!("BUG: Can not complete a root node.");
    }

    fn matches(&self, _parser: &Parser, _token: Token) -> bool {
        false
    }
}

impl CommandNode {
    /// Construct a new `CommandNode`.
    pub fn new(name: &str,
               help_text: Option<&str>,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               handler: Option<fn(&node: Node) -> ()>,
               parameters: Vec<Rc<Node>>)
               -> Self {
        CommandNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: name.to_string(),
                help_text: help_text.unwrap_or("Command").to_string(),
                hidden: hidden,
                priority: priority,
                repeat_marker: None,
                repeatable: false,
                successors: successors,
            },
            handler: handler,
            parameters: parameters,
            wrapped_root: None,
        }
    }
}

impl NodeOps for CommandNode {
    /// Record this command.
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token) {
        if self.handler.is_some() {
            unimplemented!();
            // parser.commands.push(self)
        }
    }

    fn acceptable(&self, _parser: &Parser) -> bool {
        true
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        Completion::new(self.node.help_symbol.clone(),
                        self.node.help_text.clone(),
                        token,
                        true,
                        vec![&self.node.name],
                        vec![])
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        self.node.name.starts_with(token.text)
    }
}

impl ParameterNameNode {
    /// Construct a new `ParameterNameNode`.
    pub fn new(name: &str,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               repeatable: bool,
               repeat_marker: Option<Rc<Node>>,
               parameter: Rc<Node>)
               -> Self {
        let param_node = &parameter.node();
        let help_text = param_node.help_text.clone();
        let help_symbol = name.to_string() + " " + param_node.help_symbol.as_str();
        ParameterNameNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: help_symbol,
                help_text: help_text,
                hidden: hidden,
                priority: priority,
                repeat_marker: repeat_marker,
                repeatable: repeatable,
                successors: successors,
            },
            parameter: parameter.clone(),
        }
    }
}

impl NodeOps for ParameterNameNode {
    /// Record this command.
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token) {}

    /// A repeatable node can be accepted.
    fn acceptable(&self, _parser: &Parser) -> bool {
        if self.node.repeatable {
            return true;
        }
        unimplemented!()
        // This should check nodes.contains, but then go on to check
        // for a repeat marker and whether or not that's been seen.
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        Completion::new(self.node.help_symbol.clone(),
                        self.node.help_text.clone(),
                        token,
                        true,
                        vec![&self.node.name],
                        vec![])
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        self.node.name.starts_with(token.text)
    }
}

impl ParameterNode {
    /// Construct a new `ParameterNode`.
    pub fn new(name: &str,
               help_text: Option<&str>,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               repeatable: bool,
               repeat_marker: Option<Rc<Node>>,
               kind: ParameterKind,
               required: bool)
               -> Self {
        let help_symbol = if repeatable {
            String::from("<") + name + ">..."
        } else {
            String::from("<") + name + ">"
        };
        let default_help_text = match kind {
            ParameterKind::Flag => "Flag",
            ParameterKind::Named | ParameterKind::Simple => "Parameter",
        };
        let help_text = help_text.unwrap_or(default_help_text).to_string();
        ParameterNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: help_symbol,
                help_text: help_text,
                hidden: hidden,
                priority: priority,
                repeat_marker: repeat_marker,
                repeatable: repeatable,
                successors: successors,
            },
            kind: kind,
            required: required,
        }
    }
}

impl NodeOps for ParameterNode {
    /// Record this parameter value.
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token) {
        if self.node.repeatable {
            unimplemented!();
        } else {
            parser.parameters.insert(self.node.name.clone(), token.text.to_string());
        }
    }

    fn acceptable(&self, _parser: &Parser) -> bool {
        true
    }

    /// By default named and simple parameters complete only to the token
    /// being input while flag parameters complete to the name of the flag.
    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        match self.kind {
            ParameterKind::Named | ParameterKind::Simple => {
                Completion::new(self.node.help_symbol.clone(),
                                self.node.help_text.clone(),
                                token,
                                true,
                                vec![],
                                vec![])
            }
            ParameterKind::Flag => {
                Completion::new(self.node.help_symbol.clone(),
                                self.node.help_text.clone(),
                                token,
                                true,
                                vec![&self.node.name],
                                vec![])
            }
        }
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        match self.kind {
            ParameterKind::Named | ParameterKind::Simple => true,
            ParameterKind::Flag => self.node.name.starts_with(token.text),
        }
    }
}
<commit_msg>RootNode can't be matched.<commit_after>// 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.

// Parser nodes represent the grammar that is defined
// by the currently permissible set of commands and their
// parameters.

use std::rc::Rc;

use super::{Completion, Parser};
use super::constants::*;
use tokenizer::Token;

/// Enumeration of node types used to have vectors of `Node` and so on.
pub enum Node {
    /// `Node` variant wrapping a `CommandNode`.
    Command(CommandNode),
    /// `Node` variant wrapping a `ParameterNode`.
    Parameter(ParameterNode),
    /// `Node` variant wrapping a `ParameterNameNode`.
    ParameterName(ParameterNameNode),
    /// `Node` variant wrapping a `RootNode`.
    Root(RootNode),
}

/// The operations that every node must implement.
pub trait NodeOps {
    /// Accept this node with the given `token` as data.
    ///
    /// By default, nothing needs to happen for `accept`.
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token);

    /// Can this node be accepted in the current parser state?
    /// By default, a node can be accepted when it hasn't been seen yet.
    fn acceptable(&self, _parser: &Parser) -> bool;

    /// Given a node and an optional token, provide the completion options.
    ///
    /// By default, completion should complete for the name of the given
    /// node.
    ///
    /// This is the expected behavior for [`CommandNode`] as well as
    /// [`ParameterNameNode`].
    ///
    /// [`CommandNode`]: struct.CommandNode.html
    /// [`ParameterNameNode`]: struct.ParameterNameNode.html
    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text>;

    /// By default, a node matches a `token` when the name of the
    /// node starts with the `token`.
    ///
    /// This is the desired behavior for ...
    fn matches(&self, _parser: &Parser, token: Token) -> bool;
}

/// A parse tree node.
pub struct TreeNode {
    /// The name of this node.
    pub name: String,
    /// The text used to identify this node in help text.
    /// This is typically the node name, either in plain
    /// form or decorated for parameters.
    pub help_symbol: String,
    /// Help text describing this node.
    pub help_text: String,
    /// Hidden nodes are not completed. This doesn't modify matching.
    pub hidden: bool,
    /// Match and complete priority.
    pub priority: i32,
    /// Whether or not this node can be repeated. A repeated
    /// node can be `accept`ed multiple times.
    pub repeatable: bool,
    /// If present, this node will no longer be `acceptable`.
    pub repeat_marker: Option<Rc<Node>>,
    /// Possible successor nodes. Collected while building.
    pub successors: Vec<Rc<Node>>,
}

/// The root of a command tree.
pub struct RootNode {
    /// `TreeNode` data.
    pub node: TreeNode,
}

/// A node representing a command. Constructed via [`Command`] and [`CommandTree`].
///
/// If `wrapped_root` is set then this node wraps another command.
/// This is used for the help command so that it can complete
/// normal commands. The `successors` will be those of the wrapped node.
///
/// [`Command`]: struct.Command.html
/// [`CommandTree`]: struct.CommandTree.html
pub struct CommandNode {
    /// `TreeNode` data.
    pub node: TreeNode,
    /// The handler which is executed once this node has been accepted.
    pub handler: Option<fn(&node: Node) -> ()>,
    /// Parameter nodes for this command
    ///
    /// XXX: This should be Vec<Rc<ParameterNode>> or similar.
    pub parameters: Vec<Rc<Node>>,
    /// If present, the command wrapped by this node.
    pub wrapped_root: Option<Rc<Node>>,
}

/// A node that represented the name portion of a named
/// parameter.
pub struct ParameterNameNode {
    /// `TreeNode` data.
    pub node: TreeNode,
    /// The `parameter` named by this node.
    ///
    /// XXX: This should be Rc<ParameterNode> or similar.
    pub parameter: Rc<Node>,
}

/// A node representing a parameter for a command.
pub struct ParameterNode {
    /// `TreeNode` data.
    pub node: TreeNode,
    /// A `required` parameter must be supplied for the
    /// command line being parsed to be valid.
    pub required: bool,
    /// What type of `ParameterKind` this is.
    pub kind: ParameterKind,
}

impl PartialEq for Node {
    /// Nodes are equal based on pointer equality.
    fn eq(&self, other: &Self) -> bool {
        self as *const _ == other as *const _
    }
}

/// The node in the tree of commands and parameters used in the
/// parser.
///
/// This trait defines the core operations which a node must
/// support.
impl Node {
    /// Get the `TreeNode` data for a given `Node`.
    pub fn node(&self) -> &TreeNode {
        match *self {
            Node::Command(ref command) => &command.node,
            Node::Parameter(ref parameter) => &parameter.node,
            Node::ParameterName(ref name) => &name.node,
            Node::Root(ref root) => &root.node,
        }
    }

    /// Get or calculate successors of this node.
    pub fn successors(&self) -> &Vec<Rc<Node>> {
        match *self {
            Node::Root(ref root) => &root.node.successors,
            _ => &self.node().successors,
        }
    }
}

impl NodeOps for Node {
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token) {
        match *self {
            Node::Command(ref command) => command.accept(parser, token),
            Node::Parameter(ref parameter) => parameter.accept(parser, token),
            Node::ParameterName(ref name) => name.accept(parser, token),
            Node::Root(ref root) => root.accept(parser, token),
        }
    }

    fn acceptable(&self, parser: &Parser) -> bool {
        match *self {
            Node::Command(ref command) => command.acceptable(parser),
            Node::Parameter(ref parameter) => parameter.acceptable(parser),
            Node::ParameterName(ref name) => name.acceptable(parser),
            Node::Root(ref root) => root.acceptable(parser),
        }
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        match *self {
            Node::Command(ref command) => command.complete(token),
            Node::Parameter(ref parameter) => parameter.complete(token),
            Node::ParameterName(ref name) => name.complete(token),
            Node::Root(ref root) => root.complete(token),
        }
    }

    fn matches(&self, parser: &Parser, token: Token) -> bool {
        match *self {
            Node::Command(ref command) => command.matches(parser, token),
            Node::Parameter(ref parameter) => parameter.matches(parser, token),
            Node::ParameterName(ref name) => name.matches(parser, token),
            Node::Root(ref root) => root.matches(parser, token),
        }
    }
}

impl RootNode {
    /// Create a new `RootNode`
    pub fn new(successors: Vec<Rc<Node>>) -> Self {
        RootNode {
            node: TreeNode {
                name: "__root__".to_string(),
                help_symbol: "".to_string(),
                help_text: "".to_string(),
                hidden: false,
                priority: PRIORITY_DEFAULT,
                repeat_marker: None,
                repeatable: false,
                successors: successors,
            },
        }
    }
}

impl NodeOps for RootNode {
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token) {}

    fn acceptable(&self, _parser: &Parser) -> bool {
        false
    }

    /// A `RootNode` can not be completed.
    fn complete<'text>(&self, _token: Option<Token<'text>>) -> Completion<'text> {
        panic!("BUG: Can not complete a root node.");
    }

    fn matches(&self, _parser: &Parser, _token: Token) -> bool {
        panic!("BUG: Can not match a root node.");
    }
}

impl CommandNode {
    /// Construct a new `CommandNode`.
    pub fn new(name: &str,
               help_text: Option<&str>,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               handler: Option<fn(&node: Node) -> ()>,
               parameters: Vec<Rc<Node>>)
               -> Self {
        CommandNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: name.to_string(),
                help_text: help_text.unwrap_or("Command").to_string(),
                hidden: hidden,
                priority: priority,
                repeat_marker: None,
                repeatable: false,
                successors: successors,
            },
            handler: handler,
            parameters: parameters,
            wrapped_root: None,
        }
    }
}

impl NodeOps for CommandNode {
    /// Record this command.
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token) {
        if self.handler.is_some() {
            unimplemented!();
            // parser.commands.push(self)
        }
    }

    fn acceptable(&self, _parser: &Parser) -> bool {
        true
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        Completion::new(self.node.help_symbol.clone(),
                        self.node.help_text.clone(),
                        token,
                        true,
                        vec![&self.node.name],
                        vec![])
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        self.node.name.starts_with(token.text)
    }
}

impl ParameterNameNode {
    /// Construct a new `ParameterNameNode`.
    pub fn new(name: &str,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               repeatable: bool,
               repeat_marker: Option<Rc<Node>>,
               parameter: Rc<Node>)
               -> Self {
        let param_node = &parameter.node();
        let help_text = param_node.help_text.clone();
        let help_symbol = name.to_string() + " " + param_node.help_symbol.as_str();
        ParameterNameNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: help_symbol,
                help_text: help_text,
                hidden: hidden,
                priority: priority,
                repeat_marker: repeat_marker,
                repeatable: repeatable,
                successors: successors,
            },
            parameter: parameter.clone(),
        }
    }
}

impl NodeOps for ParameterNameNode {
    /// Record this command.
    fn accept<'text>(&self, _parser: &mut Parser<'text>, _token: Token) {}

    /// A repeatable node can be accepted.
    fn acceptable(&self, _parser: &Parser) -> bool {
        if self.node.repeatable {
            return true;
        }
        unimplemented!()
        // This should check nodes.contains, but then go on to check
        // for a repeat marker and whether or not that's been seen.
    }

    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        Completion::new(self.node.help_symbol.clone(),
                        self.node.help_text.clone(),
                        token,
                        true,
                        vec![&self.node.name],
                        vec![])
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        self.node.name.starts_with(token.text)
    }
}

impl ParameterNode {
    /// Construct a new `ParameterNode`.
    pub fn new(name: &str,
               help_text: Option<&str>,
               hidden: bool,
               priority: i32,
               successors: Vec<Rc<Node>>,
               repeatable: bool,
               repeat_marker: Option<Rc<Node>>,
               kind: ParameterKind,
               required: bool)
               -> Self {
        let help_symbol = if repeatable {
            String::from("<") + name + ">..."
        } else {
            String::from("<") + name + ">"
        };
        let default_help_text = match kind {
            ParameterKind::Flag => "Flag",
            ParameterKind::Named | ParameterKind::Simple => "Parameter",
        };
        let help_text = help_text.unwrap_or(default_help_text).to_string();
        ParameterNode {
            node: TreeNode {
                name: name.to_string(),
                help_symbol: help_symbol,
                help_text: help_text,
                hidden: hidden,
                priority: priority,
                repeat_marker: repeat_marker,
                repeatable: repeatable,
                successors: successors,
            },
            kind: kind,
            required: required,
        }
    }
}

impl NodeOps for ParameterNode {
    /// Record this parameter value.
    fn accept<'text>(&self, parser: &mut Parser<'text>, token: Token) {
        if self.node.repeatable {
            unimplemented!();
        } else {
            parser.parameters.insert(self.node.name.clone(), token.text.to_string());
        }
    }

    fn acceptable(&self, _parser: &Parser) -> bool {
        true
    }

    /// By default named and simple parameters complete only to the token
    /// being input while flag parameters complete to the name of the flag.
    fn complete<'text>(&self, token: Option<Token<'text>>) -> Completion<'text> {
        match self.kind {
            ParameterKind::Named | ParameterKind::Simple => {
                Completion::new(self.node.help_symbol.clone(),
                                self.node.help_text.clone(),
                                token,
                                true,
                                vec![],
                                vec![])
            }
            ParameterKind::Flag => {
                Completion::new(self.node.help_symbol.clone(),
                                self.node.help_text.clone(),
                                token,
                                true,
                                vec![&self.node.name],
                                vec![])
            }
        }
    }

    fn matches(&self, _parser: &Parser, token: Token) -> bool {
        match self.kind {
            ParameterKind::Named | ParameterKind::Simple => true,
            ParameterKind::Flag => self.node.name.starts_with(token.text),
        }
    }
}
<|endoftext|>


<commit_before>//! Agent policy module.

// TODO: Add support for generic action spaces representation.
pub trait Policy {
    fn sample(&mut self, qs: &[f64]) -> usize;
    fn probabilities(&mut self, qs: &[f64]) -> Vec<f64>;

    fn handle_terminal(&mut self) {}
}

mod random;
pub use self::random::Random;

mod greedy;
pub use self::greedy::Greedy;

mod epsilon_greedy;
pub use self::epsilon_greedy::EpsilonGreedy;

mod boltzmann;
pub use self::boltzmann::{Boltzmann, TruncatedBoltzmann};
<commit_msg>docs(policies): add docs for `Policy` trait<commit_after>//! Agent policy module.

// TODO: Add support for generic action spaces representation.
/// Policy trait for functions that select between a set of values.
pub trait Policy {
    /// Sample the policy distribution for a set of exogenous input values.
    fn sample(&mut self, qs: &[f64]) -> usize;

    /// Return the probability of selecting each value in a given set of input values.
    fn probabilities(&mut self, qs: &[f64]) -> Vec<f64>;

    /// Update the policy after reaching a terminal state.
    fn handle_terminal(&mut self) {}
}

mod random;
pub use self::random::Random;

mod greedy;
pub use self::greedy::Greedy;

mod epsilon_greedy;
pub use self::epsilon_greedy::EpsilonGreedy;

mod boltzmann;
pub use self::boltzmann::{Boltzmann, TruncatedBoltzmann};
<|endoftext|>


<commit_before>//! way-cooler registry.

use std::ops::Deref;
use std::cmp::Eq;
use std::fmt::Display;
use std::hash::Hash;
use std::borrow::Borrow;

use std::collections::HashMap;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

use rustc_serialize::{Decodable, json};
use rustc_serialize::json::{Json, ToJson};

mod types;
pub use self::types::{RegistryAccess, RegistryValue};

#[cfg(test)]
mod tests;

type RegMap = HashMap<String, RegistryValue>;

lazy_static! {
    /// Registry variable for the registry
    static ref REGISTRY: RwLock<RegMap> =
        RwLock::new(HashMap::new());
}

/// Error types that can happen
#[derive(Debug, PartialEq, Eq)]
pub enum RegistryError {
    /// The value in the registry could not be parsed
    InvalidJson,
    /// The registry key was not found
    KeyNotFound
}

/// Acquires a read lock on the registry.
fn read_lock<'a>() -> RwLockReadGuard<'a, RegMap> {
    REGISTRY.read().unwrap()
}

/// Acquires a write lock on the registry.
fn write_lock<'a>() -> RwLockWriteGuard<'a, RegMap> {
    REGISTRY.write().unwrap()
}

/// Gets a Json object from a registry key
pub fn get_json<K>(name: &K) -> Option<Arc<Json>>
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("get_json: {}", *name);
    let ref reg = *read_lock();
    if let Some(val) = reg.get(name) {
        Some(val.get_json())
    }
    else {
        None
    }
}

/// Gets an object from the regsitry, decoding its internal json
/// representation.
pub fn get<K, T>(name: &K) -> Result<T, RegistryError>
where T: Decodable, String: Borrow<K>, K: Hash + Eq + Display {
    let maybe_json = get_json(name);
    if let Some(json_arc) = maybe_json {
        let mut decoder = json::Decoder::new(json_arc.deref().to_json());
        match T::decode(&mut decoder) {
            Ok(val) => Ok(val),
            Err(e) => Err(RegistryError::InvalidJson)
        }
    }
    else {
        Err(RegistryError::KeyNotFound)
    }
}

/// Set a key in the registry to a particular value
pub fn set<T: ToJson>(key: String, val: T) {
    trace!("set: {}", key);
    let ref mut write_reg = *write_lock();
    let regvalue = RegistryValue::new(RegistryAccess::Public, val);
    write_reg.insert(key, regvalue);
}

/// Whether this map contains a key
pub fn contains_key<K>(key: &K) -> bool
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("contains_key: {}", *key);
    let ref read_reg = *read_lock();
    read_reg.contains_key(key)
}
<commit_msg>Made registry read_lock and write_lock public<commit_after>//! way-cooler registry.

use std::ops::Deref;
use std::cmp::Eq;
use std::fmt::Display;
use std::hash::Hash;
use std::borrow::Borrow;

use std::collections::HashMap;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

use rustc_serialize::{Decodable, json};
use rustc_serialize::json::{Json, ToJson};

mod types;
pub use self::types::{RegistryAccess, RegistryValue};

#[cfg(test)]
mod tests;

type RegMap = HashMap<String, RegistryValue>;

lazy_static! {
    /// Registry variable for the registry
    static ref REGISTRY: RwLock<RegMap> =
        RwLock::new(HashMap::new());
}

/// Error types that can happen
#[derive(Debug, PartialEq, Eq)]
pub enum RegistryError {
    /// The value in the registry could not be parsed
    InvalidJson,
    /// The registry key was not found
    KeyNotFound
}

/// Acquires a read lock on the registry.
pub fn read_lock<'a>() -> RwLockReadGuard<'a, RegMap> {
    REGISTRY.read().unwrap()
}

/// Acquires a write lock on the registry.
pub fn write_lock<'a>() -> RwLockWriteGuard<'a, RegMap> {
    REGISTRY.write().unwrap()
}

/// Gets a Json object from a registry key
pub fn get_json<K>(name: &K) -> Option<Arc<Json>>
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("get_json: {}", *name);
    let ref reg = *read_lock();
    if let Some(val) = reg.get(name) {
        Some(val.get_json())
    }
    else {
        None
    }
}

/// Gets an object from the regsitry, decoding its internal json
/// representation.
pub fn get<K, T>(name: &K) -> Result<T, RegistryError>
where T: Decodable, String: Borrow<K>, K: Hash + Eq + Display {
    let maybe_json = get_json(name);
    if let Some(json_arc) = maybe_json {
        let mut decoder = json::Decoder::new(json_arc.deref().to_json());
        match T::decode(&mut decoder) {
            Ok(val) => Ok(val),
            Err(e) => Err(RegistryError::InvalidJson)
        }
    }
    else {
        Err(RegistryError::KeyNotFound)
    }
}

/// Set a key in the registry to a particular value
pub fn set<T: ToJson>(key: String, val: T) {
    trace!("set: {}", key);
    let ref mut write_reg = *write_lock();
    let regvalue = RegistryValue::new(RegistryAccess::Public, val);
    write_reg.insert(key, regvalue);
}

/// Whether this map contains a key
pub fn contains_key<K>(key: &K) -> bool
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("contains_key: {}", *key);
    let ref read_reg = *read_lock();
    read_reg.contains_key(key)
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

//! Shader parameter handling.

use dev = device::shade;

/// Helper trait to transform base types into their corresponding uniforms
pub trait ToUniform {
    /// Create a `UniformValue` representing this value.
    fn to_uniform(&self) -> dev::UniformValue;
}

impl ToUniform for i32 {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueI32(*self)
    }
}

impl ToUniform for f32 {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueF32(*self)
    }
}

impl ToUniform for [i32, ..4] {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueI32Vec(*self)
    }
}

impl ToUniform for [f32, ..4] {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueF32Vec(*self)
    }
}
impl ToUniform for [[f32, ..4], ..4] {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueF32Matrix(*self)

    }
}

/// Variable index of a uniform.
pub type VarUniform = u16;
/// Variable index of a uniform block.
pub type VarBlock = u8;
/// Variable index of a texture.
pub type VarTexture = u8;
/// A texture parameter: consists of a texture handle with an optional sampler.
pub type TextureParam = (super::TextureHandle, Option<super::SamplerHandle>);
/// Borrowed parts of the `ProgramMeta`, used for data link construction
pub type ParamLinkInput<'a> = (
    &'a [dev::UniformVar],
    &'a [dev::BlockVar],
    &'a [dev::SamplerVar]
);
/// A borrowed mutable storage for shader parameter values.
pub struct ParamValues<'a> {
    /// uniform values to be provided
    pub uniforms: &'a mut [dev::UniformValue],
    /// uniform buffers to be provided
    pub blocks  : &'a mut [super::BufferHandle],
    /// textures to be provided
    pub textures: &'a mut [TextureParam]
}

/// Encloses a shader program with its parameter
pub trait ProgramShell {
    /// Get the contained program
    fn get_program(&self) -> super::ProgramHandle;
    /// Get all the contained parameter values
    fn fill_params(&self, ParamValues);
}

impl ProgramShell for super::ProgramHandle {
    fn get_program(&self) -> super::ProgramHandle {
        self.clone()
    }
    fn fill_params(&self, params: ParamValues) {
        debug_assert!(
            params.uniforms.is_empty() &&
            params.blocks.is_empty() &&
            params.textures.is_empty()
        );
    }
}

/// An error type on either the parameter storage or the program side
#[deriving(Clone, Show)]
pub enum ParameterError<'a> {
    /// Internal error
    ErrorInternal,
    /// Error with the named uniform
    ErrorUniform(&'a str),
    /// Error with the named uniform block
    ErrorBlock(&'a str),
    /// Error with the named texture.
    ErrorTexture(&'a str),
}

/// An error type for the link creation
#[deriving(Clone, Show)]
pub enum ParameterLinkError<'a> {
    /// Program is not valid
    ErrorBadProgram,
    /// A given parameter is not used by the program
    ErrorUnusedParameter(ParameterError<'a>),
    /// A program parameter that is not provided
    ErrorMissingParameter(ParameterError<'a>),
}

/// Abstracts the shader parameter structure, generated by the `shader_param` attribute
pub trait ShaderParam<L> {
    /// Creates a new link, self is passed as a workaround for Rust to not be lost in generics
    fn create_link(&self, ParamLinkInput) -> Result<L, ParameterError<'static>>;
    /// Get all the contained parameter values, using a given link.
    fn fill_params(&self, link: &L, ParamValues);
}

/// A bundle that encapsulates a program and a custom user-provided
/// structure containing the program parameters.
/// # Type parameters:
///
/// * `L` - auto-generated structure that has a variable index for every field of T
/// * `T` - user-provided structure containing actual parameter values
#[deriving(Clone)]
pub struct CustomShell<L, T> {
    /// Shader program
    program: super::ProgramHandle,
    /// Hidden link that provides parameter indices for user data
    link: L,
    /// Global data in a user-provided struct
    pub data: T,
}

impl<L, T: ShaderParam<L>> CustomShell<L, T> {
    /// Create a new custom shell
    pub fn new(program: super::ProgramHandle, link: L, data: T) -> CustomShell<L, T> {
        CustomShell {
            program: program,
            link: link,
            data: data,
        }
    }
}

impl<L, T: ShaderParam<L>> ProgramShell for CustomShell<L, T> {
    fn get_program(&self) -> super::ProgramHandle {
        self.program
    }
    fn fill_params(&self, params: ParamValues) {
        self.data.fill_params(&self.link, params);
    }
}

/// A serializable less-safe binding of a program with its parameters
#[deriving(Clone)]
pub struct SerialShell {
    program: super::ProgramHandle,
    uniforms: Vec<dev::UniformValue>,
    blocks: Vec<super::BufferHandle>,
    textures: Vec<TextureParam>,
}

impl ProgramShell for SerialShell {
    fn get_program(&self) -> super::ProgramHandle {
        self.program
    }
    fn fill_params(&self, param: ParamValues) {
        debug_assert!(param.uniforms.len() == self.uniforms.len());
        for (dst, src) in param.uniforms.mut_iter().zip(self.uniforms.iter()) {
            *dst = *src;
        }
        debug_assert!(param.blocks.len() == self.blocks.len());
        for (dst, src) in param.blocks.mut_iter().zip(self.blocks.iter()) {
            *dst = *src;
        }
        debug_assert!(param.textures.len() == self.textures.len());
        for (dst, src) in param.textures.mut_iter().zip(self.textures.iter()) {
            *dst = *src;
        }
    }
}
<commit_msg>Implemented ParamDictionary<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

//! Shader parameter handling.

use std::cell::Cell;
use std::rc::Rc;
use dev = device::shade;

/// Helper trait to transform base types into their corresponding uniforms
pub trait ToUniform {
    /// Create a `UniformValue` representing this value.
    fn to_uniform(&self) -> dev::UniformValue;
}

impl ToUniform for i32 {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueI32(*self)
    }
}

impl ToUniform for f32 {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueF32(*self)
    }
}

impl ToUniform for [i32, ..4] {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueI32Vec(*self)
    }
}

impl ToUniform for [f32, ..4] {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueF32Vec(*self)
    }
}
impl ToUniform for [[f32, ..4], ..4] {
    fn to_uniform(&self) -> dev::UniformValue {
        dev::ValueF32Matrix(*self)

    }
}

/// Variable index of a uniform.
pub type VarUniform = u16;
/// Variable index of a uniform block.
pub type VarBlock = u8;
/// Variable index of a texture.
pub type VarTexture = u8;
/// A texture parameter: consists of a texture handle with an optional sampler.
pub type TextureParam = (super::TextureHandle, Option<super::SamplerHandle>);
/// Borrowed parts of the `ProgramMeta`, used for data link construction
pub type ParamLinkInput<'a> = (
    &'a [dev::UniformVar],
    &'a [dev::BlockVar],
    &'a [dev::SamplerVar]
);
/// A borrowed mutable storage for shader parameter values.
pub struct ParamValues<'a> {
    /// uniform values to be provided
    pub uniforms: &'a mut [dev::UniformValue],
    /// uniform buffers to be provided
    pub blocks  : &'a mut [super::BufferHandle],
    /// textures to be provided
    pub textures: &'a mut [TextureParam]
}

/// Encloses a shader program with its parameter
pub trait ProgramShell {
    /// Get the contained program
    fn get_program(&self) -> super::ProgramHandle;
    /// Get all the contained parameter values
    fn fill_params(&self, ParamValues);
}

impl ProgramShell for super::ProgramHandle {
    fn get_program(&self) -> super::ProgramHandle {
        self.clone()
    }
    fn fill_params(&self, params: ParamValues) {
        debug_assert!(
            params.uniforms.is_empty() &&
            params.blocks.is_empty() &&
            params.textures.is_empty()
        );
    }
}

/// An error type on either the parameter storage or the program side
#[deriving(Clone, Show)]
pub enum ParameterError<'a> {
    /// Internal error
    ErrorInternal,
    /// Error with the named uniform
    ErrorUniform(&'a str),
    /// Error with the named uniform block
    ErrorBlock(&'a str),
    /// Error with the named texture.
    ErrorTexture(&'a str),
}

/// An error type for the link creation
#[deriving(Clone, Show)]
pub enum ParameterLinkError<'a> {
    /// Program is not valid
    ErrorBadProgram,
    /// A given parameter is not used by the program
    ErrorUnusedParameter(ParameterError<'a>),
    /// A program parameter that is not provided
    ErrorMissingParameter(ParameterError<'a>),
}

/// Abstracts the shader parameter structure, generated by the `shader_param` attribute
pub trait ShaderParam<L> {
    /// Creates a new link, self is passed as a workaround for Rust to not be lost in generics
    fn create_link(&self, ParamLinkInput) -> Result<L, ParameterError<'static>>;
    /// Get all the contained parameter values, using a given link.
    fn fill_params(&self, &L, ParamValues);
}

/// A bundle that encapsulates a program and a custom user-provided
/// structure containing the program parameters.
/// # Type parameters:
///
/// * `L` - auto-generated structure that has a variable index for every field of T
/// * `T` - user-provided structure containing actual parameter values
#[deriving(Clone)]
pub struct CustomShell<L, T> {
    /// Shader program
    program: super::ProgramHandle,
    /// Hidden link that provides parameter indices for user data
    link: L,
    /// Global data in a user-provided struct
    pub data: T,
}

impl<L, T: ShaderParam<L>> CustomShell<L, T> {
    /// Create a new custom shell
    pub fn new(program: super::ProgramHandle, link: L, data: T) -> CustomShell<L, T> {
        CustomShell {
            program: program,
            link: link,
            data: data,
        }
    }
}

impl<L, T: ShaderParam<L>> ProgramShell for CustomShell<L, T> {
    fn get_program(&self) -> super::ProgramHandle {
        self.program
    }
    fn fill_params(&self, params: ParamValues) {
        self.data.fill_params(&self.link, params);
    }
}

/// A named cell containing arbitrary value
pub struct NamedCell<T> {
    /// Name
    pub name: String,
    /// Value
    pub value: Cell<T>,
}

/// A dictionary of parameters, meant to be shared between different programs
pub struct ParamDictionary {
    /// Uniform dictionary
    pub uniforms: Vec<NamedCell<dev::UniformValue>>,
    /// Block dictionary
    pub blocks: Vec<NamedCell<super::BufferHandle>>,
    /// Texture dictionary
    pub textures: Vec<NamedCell<TextureParam>>,
}

/// Accelerating link structure for ParamDictionary
pub struct ParamDictionaryLink {
    uniforms: Vec<uint>,
    blocks: Vec<uint>,
    textures: Vec<uint>,
}

impl<'a> ShaderParam<ParamDictionaryLink> for &'a ParamDictionary {
    fn create_link(&self, (in_uni, in_buf, in_tex): ParamLinkInput)
                   -> Result<ParamDictionaryLink, ParameterError<'static>> {
        Ok(ParamDictionaryLink {
            uniforms: in_uni.iter().map(|var|
                self.uniforms.iter().position(|c| c.name == var.name).unwrap()
                ).collect(),
            blocks: in_buf.iter().map(|var|
                self.blocks  .iter().position(|c| c.name == var.name).unwrap()
                ).collect(),
            textures: in_tex.iter().map(|var|
                self.textures.iter().position(|c| c.name == var.name).unwrap()
                ).collect(),
        })
    }

    fn fill_params(&self, link: &ParamDictionaryLink, out: ParamValues) {
        for (&id, var) in link.uniforms.iter().zip(out.uniforms.mut_iter()) {
            *var = self.uniforms[id].value.get();
        }
        for (&id, var) in link.blocks.iter().zip(out.blocks.mut_iter()) {
            *var = self.blocks[id].value.get();
        }
        for (&id, var) in link.textures.iter().zip(out.textures.mut_iter()) {
            *var = self.textures[id].value.get();
        }
    }
}

impl ShaderParam<ParamDictionaryLink> for Rc<ParamDictionary> {
    fn create_link(&self, input: ParamLinkInput) -> Result<ParamDictionaryLink,
                   ParameterError<'static>> {
        self.deref().create_link(input)
    }
    fn fill_params(&self, link: &ParamDictionaryLink, out: ParamValues) {
        self.deref().fill_params(link, out)
    }
}
<|endoftext|>