<commit_before>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_config::meta::region::RegionProviderChain;
use aws_sdk_s3::{config, Client, Error, Region, RetryConfig, PKG_VERSION};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    /// The AWS Region.
    #[structopt(short, long)]
    region: Option<String>,

    /// The number of (re)tries.
    #[structopt(short, long, default_value = "2")]
    tries: u32,

    /// Whether to display additional information.
    #[structopt(short, long)]
    verbose: bool,
}

// Shows your buckets.
async fn show_num_buckets(client: &Client) -> Result<(), Error> {
    let resp = client.list_buckets().send().await?;
    let buckets = resp.buckets().unwrap_or_default();

    println!("Found {} buckets in all regions.", buckets.len());

    Ok(())
}

/// Displays how many Amazon S3 buckets you have.
/// # Arguments
///
/// * `[-r REGION]` - The Region in which the client is created.
///   If not supplied, uses the value of the **AWS_REGION** environment variable.
///   If the environment variable is not set, defaults to **us-west-2**.
/// * `[-t TRIES]` - The number of times to (re)try the request.
/// * `[-v]` - Whether to display additional information.
#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt::init();

    let Opt {
        region,
        tries,
        verbose,
    } = Opt::from_args();

    let region_provider = RegionProviderChain::first_try(region.map(Region::new))
        .or_default_provider()
        .or_else(Region::new("us-west-2"));
    println!();

    if verbose {
        println!("S3 client version: {}", PKG_VERSION);
        println!(
            "Region:            {}",
            region_provider.region().await.unwrap().as_ref()
        );
        println!("Retries:           {}", &tries);
        println!();
    }

    assert_ne!(tries, 0, "You cannot set zero retries.");

    // snippet-start:[custom_retries.rust.set_retries]
    let shared_config = aws_config::from_env().region(region_provider).load().await;

    // Construct an S3 client with customized retry configuration.
    let client = Client::from_conf(
        // Start with the shared environment configuration.
        config::Builder::from(&shared_config)
            // Set max attempts.
            // If tries is 1, there are no retries.
            .retry_config(RetryConfig::new().with_max_attempts(tries))
            .build(),
    );
    // snippet-end:[custom_retries.rust.set_retries]

    show_num_buckets(&client).await
}
<commit_msg>Reverts RetryConfig for future breaking change.<commit_after>/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

use aws_config::meta::region::RegionProviderChain;
use aws_sdk_s3::{config, Client, Error, Region, RetryConfig, PKG_VERSION};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    /// The AWS Region.
    #[structopt(short, long)]
    region: Option<String>,

    /// The number of (re)tries.
    #[structopt(short, long, default_value = "2")]
    tries: u32,

    /// Whether to display additional information.
    #[structopt(short, long)]
    verbose: bool,
}

// Shows your buckets.
async fn show_num_buckets(client: &Client) -> Result<(), Error> {
    let resp = client.list_buckets().send().await?;
    let buckets = resp.buckets().unwrap_or_default();

    println!("Found {} buckets in all regions.", buckets.len());

    Ok(())
}

/// Displays how many Amazon S3 buckets you have.
/// # Arguments
///
/// * `[-r REGION]` - The Region in which the client is created.
///   If not supplied, uses the value of the **AWS_REGION** environment variable.
///   If the environment variable is not set, defaults to **us-west-2**.
/// * `[-t TRIES]` - The number of times to (re)try the request.
/// * `[-v]` - Whether to display additional information.
#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt::init();

    let Opt {
        region,
        tries,
        verbose,
    } = Opt::from_args();

    let region_provider = RegionProviderChain::first_try(region.map(Region::new))
        .or_default_provider()
        .or_else(Region::new("us-west-2"));
    println!();

    if verbose {
        println!("S3 client version: {}", PKG_VERSION);
        println!(
            "Region:            {}",
            region_provider.region().await.unwrap().as_ref()
        );
        println!("Retries:           {}", &tries);
        println!();
    }

    assert_ne!(tries, 0, "You cannot set zero retries.");

    // snippet-start:[custom_retries.rust.set_retries]
    let shared_config = aws_config::from_env().region(region_provider).load().await;

    // Construct an S3 client with customized retry configuration.
    let client = Client::from_conf(
        // Start with the shared environment configuration.
        config::Builder::from(&shared_config)
            // Set max attempts.
            // If tries is 1, there are no retries.
            .retry_config(RetryConfig::standard().with_max_attempts(tries))
            .build(),
    );
    // snippet-end:[custom_retries.rust.set_retries]

    show_num_buckets(&client).await
}
<|endoftext|>


<commit_before>use libc::{c_int, c_longlong, c_ulonglong, c_char, c_void};
use std::mem;
use std::sync::{Arc, Once, ONCE_INIT};
use std::cell::Cell;

/// Typedef for initialization function.
type EnergyMonInitFn = extern fn(*mut EMImpl) -> c_int;
/// Typedef for read function.
type EnergyMonReadTotalFn = extern fn(*mut EMImpl) -> c_longlong;
/// Typedef for cleanup function.
type EnergyMonFinishFn = extern fn(*mut EMImpl) -> c_int;
/// Typedef for function to get human-readable name.
type EnergyMonGetSourceFn = extern fn(*mut c_char) -> *mut c_char;
/// Typedef for function to get refresh interval.
type EnergyMonGetIntervalFn = extern fn(*const EMImpl) -> c_ulonglong;

#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
#[repr(C)]
/// Representation of native C struct `em_impl`.
struct EMImpl {
    /// Native C function type signature that initializes the `EMImpl`.
    finit: EnergyMonInitFn,
    /// Native C function type signature that reads energy data from the `EMImpl`.
    fread: EnergyMonReadTotalFn,
    /// Native C function type signature that cleans up the `EMImpl`.
    ffinish: EnergyMonFinishFn,
    /// Native C function type signature that gets the `EMImpl`'s human-readable name.
    fsource: EnergyMonGetSourceFn,
    /// Native C function type signature that gets the `EMImpl`'s refresh interval.
    finterval: EnergyMonGetIntervalFn,
    /// Native C pointer used by the underlying `EMImpl` implementation for storing state.
    state: *mut c_void,
}

extern {
    /// Native C function that fills in the EMImpl struct values and may allocate other resources.
    fn em_impl_get(em: *mut EMImpl) -> c_int;
}

impl EMImpl {
    /// Create an `EMImpl` which represents a C struct.
    fn new() -> Result<EMImpl, &'static str> {
        unsafe {
            let mut em: EMImpl = mem::uninitialized();
            match em_impl_get(&mut em) {
                0 => Ok(em),
                _ => Err("Failed to create EMImpl"),
            }
        }
    }

    /// Initialize the `EMImpl` - may allocate more resources and/or start threads.
    fn init(&mut self) -> Result<(), &'static str> {
        match (self.finit)(self) {
            0 => Ok(()),
            _ => Err("Failed to initialize EMImpl"),
        }
    }

    /// Read the total energy from the `EMImpl`.
    fn read(&mut self) -> i64 {
        (self.fread)(self)
    }

    /// Cleanup the `EMImpl` - may deallocate associated resources and/or stop threads.
    fn finish(&mut self) -> Result<(), &'static str> {
        match (self.ffinish)(self) {
            0 => Ok(()),
            _ => Err("Failed to cleanup EMImpl"),
        }
    }

    /// Utility function to get a human-readable name of the `EMImpl`'s source.
    fn source(&mut self) -> String {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.fsource)(buf.as_mut_ptr());
        if ret.is_null() {
            return "UNKNOWN".to_owned();
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        String::from_utf8_lossy(buf).into_owned()
    }

    /// Get the refresh interval from the `EMImpl`.
    fn interval(&self) -> u64 {
        (self.finterval)(self)
    }
}

/// A basic energy monitor.
pub struct EnergyMon {
    /// The native C struct.
    em: EMImpl,
}

impl EnergyMon {
    /// Create and initialize an `EnergyMon`.
    pub fn new() -> Result<EnergyMon, &'static str> {
        println!("Initializing energy monitor");
        let mut em = try!{EMImpl::new()};
        try!{em.init()};
        Ok(EnergyMon { em: em })
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&mut self) -> i64 {
        self.em.read()
    }

    /// Get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> String {
        self.em.source()
    }

    /// Get the refresh interval for the `EnergyMon`.
    pub fn interval(&self) -> u64 {
        self.em.interval()
    }
}

impl Drop for EnergyMon {
    fn drop(&mut self) {
        println!("Finishing energy monitor");
        let _ = self.em.finish();
    }
}

#[derive(Clone)]
pub struct SingletonEnergyMon {
    em: Arc<Cell<EMImpl>>,
}

impl SingletonEnergyMon {
    pub fn instance() -> Option<SingletonEnergyMon> {
        static mut EM: *const SingletonEnergyMon = 0 as *const SingletonEnergyMon;
        static ONCE: Once = ONCE_INIT;

        unsafe {
            ONCE.call_once(|| {
                println!("Initializing singleton energy monitor");
                let mut em = match EMImpl::new() {
                    Ok(e) => e,
                    Err(e) => {
                        println!("{}", e);
                        return;
                    },
                };
                match em.init() {
                    Ok(_) => (),
                    Err(e) => {
                        println!("{}", e);
                        let _ = em.finish();
                        return;
                    },
                }
                let sem: SingletonEnergyMon = SingletonEnergyMon {
                    em: Arc::new(Cell::new(em))
                };
                // put it on the heap
                EM = mem::transmute(Box::new(sem));
            });
            if EM.is_null() {
                None
            } else {
                Some((*EM).clone())
            }
        }
    }

    pub fn read(&self) -> i64 {
        self.em.get().read()
    }

    pub fn source(&self) -> String {
        self.em.get().source()
    }

    pub fn interval(&self) -> u64 {
        self.em.get().interval()
    }

    pub unsafe fn destroy(&self) {
        println!("Finishing singleton energy monitor");
        let _ = self.em.get().finish();
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        let val = em.read();
        assert!(val >= 0);
        println!("Read {} from {} with refresh interval {}", val, em.source(), em.interval());
    }

    #[test]
    fn test_singleton() {
        for _ in 0..2 {
            let sem: SingletonEnergyMon = SingletonEnergyMon::instance().unwrap();
            let val = sem.read();
            println!("Read {} from {} singleton with refresh interval {}", val, sem.source(),
                     sem.interval());
        }
        unsafe {
            SingletonEnergyMon::instance().unwrap().destroy();
        }
    }

}
<commit_msg>no longer need mutable reference on read<commit_after>use libc::{c_int, c_longlong, c_ulonglong, c_char, c_void};
use std::mem;
use std::sync::{Arc, Once, ONCE_INIT};
use std::cell::Cell;

/// Typedef for initialization function.
type EnergyMonInitFn = extern fn(*mut EMImpl) -> c_int;
/// Typedef for read function.
type EnergyMonReadTotalFn = extern fn(*const EMImpl) -> c_longlong;
/// Typedef for cleanup function.
type EnergyMonFinishFn = extern fn(*mut EMImpl) -> c_int;
/// Typedef for function to get human-readable name.
type EnergyMonGetSourceFn = extern fn(*mut c_char) -> *mut c_char;
/// Typedef for function to get refresh interval.
type EnergyMonGetIntervalFn = extern fn(*const EMImpl) -> c_ulonglong;

#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
#[repr(C)]
/// Representation of native C struct `em_impl`.
struct EMImpl {
    /// Native C function type signature that initializes the `EMImpl`.
    finit: EnergyMonInitFn,
    /// Native C function type signature that reads energy data from the `EMImpl`.
    fread: EnergyMonReadTotalFn,
    /// Native C function type signature that cleans up the `EMImpl`.
    ffinish: EnergyMonFinishFn,
    /// Native C function type signature that gets the `EMImpl`'s human-readable name.
    fsource: EnergyMonGetSourceFn,
    /// Native C function type signature that gets the `EMImpl`'s refresh interval.
    finterval: EnergyMonGetIntervalFn,
    /// Native C pointer used by the underlying `EMImpl` implementation for storing state.
    state: *mut c_void,
}

extern {
    /// Native C function that fills in the EMImpl struct values and may allocate other resources.
    fn em_impl_get(em: *mut EMImpl) -> c_int;
}

impl EMImpl {
    /// Create an `EMImpl` which represents a C struct.
    fn new() -> Result<EMImpl, &'static str> {
        unsafe {
            let mut em: EMImpl = mem::uninitialized();
            match em_impl_get(&mut em) {
                0 => Ok(em),
                _ => Err("Failed to create EMImpl"),
            }
        }
    }

    /// Initialize the `EMImpl` - may allocate more resources and/or start threads.
    fn init(&mut self) -> Result<(), &'static str> {
        match (self.finit)(self) {
            0 => Ok(()),
            _ => Err("Failed to initialize EMImpl"),
        }
    }

    /// Read the total energy from the `EMImpl`.
    fn read(&self) -> i64 {
        (self.fread)(self)
    }

    /// Cleanup the `EMImpl` - may deallocate associated resources and/or stop threads.
    fn finish(&mut self) -> Result<(), &'static str> {
        match (self.ffinish)(self) {
            0 => Ok(()),
            _ => Err("Failed to cleanup EMImpl"),
        }
    }

    /// Utility function to get a human-readable name of the `EMImpl`'s source.
    fn source(&mut self) -> String {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.fsource)(buf.as_mut_ptr());
        if ret.is_null() {
            return "UNKNOWN".to_owned();
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        String::from_utf8_lossy(buf).into_owned()
    }

    /// Get the refresh interval from the `EMImpl`.
    fn interval(&self) -> u64 {
        (self.finterval)(self)
    }
}

/// A basic energy monitor.
pub struct EnergyMon {
    /// The native C struct.
    em: EMImpl,
}

impl EnergyMon {
    /// Create and initialize an `EnergyMon`.
    pub fn new() -> Result<EnergyMon, &'static str> {
        println!("Initializing energy monitor");
        let mut em = try!{EMImpl::new()};
        try!{em.init()};
        Ok(EnergyMon { em: em })
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&self) -> i64 {
        self.em.read()
    }

    /// Get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> String {
        self.em.source()
    }

    /// Get the refresh interval for the `EnergyMon`.
    pub fn interval(&self) -> u64 {
        self.em.interval()
    }
}

impl Drop for EnergyMon {
    fn drop(&mut self) {
        println!("Finishing energy monitor");
        let _ = self.em.finish();
    }
}

#[derive(Clone)]
pub struct SingletonEnergyMon {
    em: Arc<Cell<EMImpl>>,
}

impl SingletonEnergyMon {
    pub fn instance() -> Option<SingletonEnergyMon> {
        static mut EM: *const SingletonEnergyMon = 0 as *const SingletonEnergyMon;
        static ONCE: Once = ONCE_INIT;

        unsafe {
            ONCE.call_once(|| {
                println!("Initializing singleton energy monitor");
                let mut em = match EMImpl::new() {
                    Ok(e) => e,
                    Err(e) => {
                        println!("{}", e);
                        return;
                    },
                };
                match em.init() {
                    Ok(_) => (),
                    Err(e) => {
                        println!("{}", e);
                        let _ = em.finish();
                        return;
                    },
                }
                let sem: SingletonEnergyMon = SingletonEnergyMon {
                    em: Arc::new(Cell::new(em))
                };
                // put it on the heap
                EM = mem::transmute(Box::new(sem));
            });
            if EM.is_null() {
                None
            } else {
                Some((*EM).clone())
            }
        }
    }

    pub fn read(&self) -> i64 {
        self.em.get().read()
    }

    pub fn source(&self) -> String {
        self.em.get().source()
    }

    pub fn interval(&self) -> u64 {
        self.em.get().interval()
    }

    pub unsafe fn destroy(&self) {
        println!("Finishing singleton energy monitor");
        let _ = self.em.get().finish();
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        let val = em.read();
        assert!(val >= 0);
        println!("Read {} from {} with refresh interval {}", val, em.source(), em.interval());
    }

    #[test]
    fn test_singleton() {
        for _ in 0..2 {
            let sem: SingletonEnergyMon = SingletonEnergyMon::instance().unwrap();
            let val = sem.read();
            println!("Read {} from {} singleton with refresh interval {}", val, sem.source(),
                     sem.interval());
        }
        unsafe {
            SingletonEnergyMon::instance().unwrap().destroy();
        }
    }

}
<|endoftext|>


<commit_before>use crate::cargo::TestBinary;
use crate::ptrace_control::*;
use crate::statemachine::{ProcessInfo, TracerAction};
use nix::libc::*;
use nix::sys::{signal::Signal, wait::WaitStatus};
use serde::{Deserialize, Serialize};
use std::cell::RefCell;

#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Event {
    ConfigLaunch(String),
    BinaryLaunch(TestBinary),
    Trace(TraceEvent),
}

#[derive(Clone, Default, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct TraceEvent {
    pid: Option<pid_t>,
    child: Option<pid_t>,
    signal: Option<String>,
    addr: Option<u64>,
    return_val: Option<i64>,
    description: String,
}

impl TraceEvent {
    pub(crate) fn new_from_action(action: &TracerAction<ProcessInfo>) -> Self {
        match *action {
            TracerAction::TryContinue(t) => TraceEvent {
                pid: Some(t.pid.as_raw()),
                signal: t.signal.map(|x| x.to_string()),
                description: "Trying to continuing child".to_string(),
                ..Default::default()
            },
            TracerAction::Continue(t) => TraceEvent {
                pid: Some(t.pid.as_raw()),
                signal: t.signal.map(|x| x.to_string()),
                description: "Continuing child".to_string(),
                ..Default::default()
            },
            TracerAction::Step(t) => TraceEvent {
                pid: Some(t.pid.as_raw()),
                description: "Stepping child".to_string(),
                ..Default::default()
            },
            TracerAction::Detach(t) => TraceEvent {
                pid: Some(t.pid.as_raw()),
                description: "Detaching child".to_string(),
                ..Default::default()
            },
            _ => TraceEvent {
                description: "Unexpected action".to_string(),
                ..Default::default()
            },
        }
    }

    pub(crate) fn new_from_wait(wait: &WaitStatus) -> Self {
        let pid = wait.pid().map(|p| p.as_raw());
        let mut event = TraceEvent {
            pid,
            ..Default::default()
        };
        match wait {
            WaitStatus::Exited(_, i) => {
                event.description = "Exited".to_string();
                event.return_val = Some(*i as _);
            }
            WaitStatus::Signaled(_, sig, _) => {
                event.signal = Some(sig.to_string());
                event.description = "Signaled".to_string();
            }
            WaitStatus::Stopped(c, sig) => {
                event.signal = Some(sig.to_string());
                if *sig == Signal::SIGTRAP {
                    event.description = "Stopped".to_string();
                    event.addr = current_instruction_pointer(*c).ok().map(|x| (x - 1) as u64);
                } else {
                    event.description = "Non-trace stop".to_string();
                }
            }
            WaitStatus::PtraceEvent(pid, sig, val) => {
                event.signal = Some(sig.to_string());
                match *val {
                    PTRACE_EVENT_CLONE => {
                        event.description = "Ptrace Clone".to_string();
                        if *sig == Signal::SIGTRAP {
                            event.child = get_event_data(*pid).ok().map(|x| x as pid_t);
                        }
                    }
                    PTRACE_EVENT_FORK => {
                        event.description = "Ptrace fork".to_string();
                    }
                    PTRACE_EVENT_VFORK => {
                        event.description = "Ptrace vfork".to_string();
                    }
                    PTRACE_EVENT_EXEC => {
                        event.description = "Ptrace exec".to_string();
                    }
                    PTRACE_EVENT_EXIT => {
                        event.description = "Ptrace exit".to_string();
                    }
                    _ => {
                        event.description = "Ptrace unknown event".to_string();
                    }
                }
            }
            WaitStatus::Continued(_) => {
                event.description = "Continued".to_string();
            }
            WaitStatus::StillAlive => {
                event.description = "StillAlive".to_string();
            }
            WaitStatus::PtraceSyscall(_) => {
                event.description = "PtraceSyscall".to_string();
            }
        }
        event
    }
}

#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EventLog {
    events: RefCell<Vec<Event>>,
}

impl EventLog {
    pub fn new() -> Self {
        Self {
            events: RefCell::new(vec![]),
        }
    }

    pub fn push_binary(&self, binary: TestBinary) {
        self.events.borrow_mut().push(Event::BinaryLaunch(binary));
    }

    pub fn push_trace(&self, event: TraceEvent) {
        self.events.borrow_mut().push(Event::Trace(event));
    }

    pub fn push_config(&self, name: String) {
        self.events.borrow_mut().push(Event::ConfigLaunch(name));
    }
}
<commit_msg>Update messages<commit_after>use crate::cargo::TestBinary;
use crate::ptrace_control::*;
use crate::statemachine::{ProcessInfo, TracerAction};
use nix::libc::*;
use nix::sys::{signal::Signal, wait::WaitStatus};
use serde::{Deserialize, Serialize};
use std::cell::RefCell;

#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Event {
    ConfigLaunch(String),
    BinaryLaunch(TestBinary),
    Trace(TraceEvent),
}

#[derive(Clone, Default, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct TraceEvent {
    pid: Option<pid_t>,
    child: Option<pid_t>,
    signal: Option<String>,
    addr: Option<u64>,
    return_val: Option<i64>,
    description: String,
}

impl TraceEvent {
    pub(crate) fn new_from_action(action: &TracerAction<ProcessInfo>) -> Self {
        match *action {
            TracerAction::TryContinue(t) => TraceEvent {
                pid: Some(t.pid.as_raw()),
                signal: t.signal.map(|x| x.to_string()),
                description: "Try continue child".to_string(),
                ..Default::default()
            },
            TracerAction::Continue(t) => TraceEvent {
                pid: Some(t.pid.as_raw()),
                signal: t.signal.map(|x| x.to_string()),
                description: "Continue child".to_string(),
                ..Default::default()
            },
            TracerAction::Step(t) => TraceEvent {
                pid: Some(t.pid.as_raw()),
                description: "Step child".to_string(),
                ..Default::default()
            },
            TracerAction::Detach(t) => TraceEvent {
                pid: Some(t.pid.as_raw()),
                description: "Detach child".to_string(),
                ..Default::default()
            },
            _ => TraceEvent {
                description: "Unexpected action".to_string(),
                ..Default::default()
            },
        }
    }

    pub(crate) fn new_from_wait(wait: &WaitStatus) -> Self {
        let pid = wait.pid().map(|p| p.as_raw());
        let mut event = TraceEvent {
            pid,
            ..Default::default()
        };
        match wait {
            WaitStatus::Exited(_, i) => {
                event.description = "Exited".to_string();
                event.return_val = Some(*i as _);
            }
            WaitStatus::Signaled(_, sig, _) => {
                event.signal = Some(sig.to_string());
                event.description = "Signaled".to_string();
            }
            WaitStatus::Stopped(c, sig) => {
                event.signal = Some(sig.to_string());
                if *sig == Signal::SIGTRAP {
                    event.description = "Stopped".to_string();
                    event.addr = current_instruction_pointer(*c).ok().map(|x| (x - 1) as u64);
                } else {
                    event.description = "Non-trace stop".to_string();
                }
            }
            WaitStatus::PtraceEvent(pid, sig, val) => {
                event.signal = Some(sig.to_string());
                match *val {
                    PTRACE_EVENT_CLONE => {
                        event.description = "Ptrace Clone".to_string();
                        if *sig == Signal::SIGTRAP {
                            event.child = get_event_data(*pid).ok().map(|x| x as pid_t);
                        }
                    }
                    PTRACE_EVENT_FORK => {
                        event.description = "Ptrace fork".to_string();
                    }
                    PTRACE_EVENT_VFORK => {
                        event.description = "Ptrace vfork".to_string();
                    }
                    PTRACE_EVENT_EXEC => {
                        event.description = "Ptrace exec".to_string();
                    }
                    PTRACE_EVENT_EXIT => {
                        event.description = "Ptrace exit".to_string();
                    }
                    _ => {
                        event.description = "Ptrace unknown event".to_string();
                    }
                }
            }
            WaitStatus::Continued(_) => {
                event.description = "Continued".to_string();
            }
            WaitStatus::StillAlive => {
                event.description = "StillAlive".to_string();
            }
            WaitStatus::PtraceSyscall(_) => {
                event.description = "PtraceSyscall".to_string();
            }
        }
        event
    }
}

#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EventLog {
    events: RefCell<Vec<Event>>,
}

impl EventLog {
    pub fn new() -> Self {
        Self {
            events: RefCell::new(vec![]),
        }
    }

    pub fn push_binary(&self, binary: TestBinary) {
        self.events.borrow_mut().push(Event::BinaryLaunch(binary));
    }

    pub fn push_trace(&self, event: TraceEvent) {
        self.events.borrow_mut().push(Event::Trace(event));
    }

    pub fn push_config(&self, name: String) {
        self.events.borrow_mut().push(Event::ConfigLaunch(name));
    }
}
<|endoftext|>


<commit_before>//! Create or redefine SQL functions
use std::ffi::CStr;
use std::mem;
use std::ptr;
use std::str;
use libc::{c_int, c_double, c_char};

use ffi;
pub use ffi::sqlite3_context;
pub use ffi::sqlite3_value;
pub use ffi::sqlite3_value_type;
pub use ffi::sqlite3_value_numeric_type;

use types::Null;

use {SqliteResult, SqliteError, SqliteConnection, str_to_cstring, InnerSqliteConnection};

/// A trait for types that can be converted into the result of an SQL function.
pub trait ToResult {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context);
}

macro_rules! raw_to_impl(
    ($t:ty, $f:ident) => (
        impl ToResult for $t {
            unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
                ffi::$f(ctx, *self)
            }
        }
    )
);

raw_to_impl!(c_int, sqlite3_result_int);
raw_to_impl!(i64, sqlite3_result_int64);
raw_to_impl!(c_double, sqlite3_result_double);

impl<'a> ToResult for bool {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        match *self {
            true => ffi::sqlite3_result_int(ctx, 1),
            _ => ffi::sqlite3_result_int(ctx, 0),
        }
    }
}

impl<'a> ToResult for &'a str {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        let length = self.len();
        if length > ::std::i32::MAX as usize {
            ffi::sqlite3_result_error_toobig(ctx);
            return;
        }
        match str_to_cstring(self) {
            Ok(c_str) => {
                ffi::sqlite3_result_text(ctx,
                                         c_str.as_ptr(),
                                         length as c_int,
                                         ffi::SQLITE_TRANSIENT())
            }
            Err(_) => ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_MISUSE), // TODO sqlite3_result_error
        }
    }
}

impl ToResult for String {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        (&self[..]).set_result(ctx)
    }
}

impl<'a> ToResult for &'a [u8] {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        if self.len() > ::std::i32::MAX as usize {
            ffi::sqlite3_result_error_toobig(ctx);
            return;
        }
        ffi::sqlite3_result_blob(ctx,
                                 mem::transmute(self.as_ptr()),
                                 self.len() as c_int,
                                 ffi::SQLITE_TRANSIENT())
    }
}

impl ToResult for Vec<u8> {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        (&self[..]).set_result(ctx)
    }
}

impl<T: ToResult> ToResult for Option<T> {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        match *self {
            None => ffi::sqlite3_result_null(ctx),
            Some(ref t) => t.set_result(ctx),
        }
    }
}

impl ToResult for Null {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        ffi::sqlite3_result_null(ctx)
    }
}

// sqlite3_result_error_code, c_int
// sqlite3_result_error_nomem
// sqlite3_result_error_toobig
// sqlite3_result_error, *const c_char, c_int
// sqlite3_result_zeroblob
// sqlite3_result_value

/// A trait for types that can be created from a SQLite function parameter value.
pub trait FromValue: Sized {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<Self>;

    /// FromValue types can implement this method and use sqlite3_value_type to check that
    /// the type reported by SQLite matches a type suitable for Self. This method is used
    /// by `???` to confirm that the parameter contains a valid type before
    /// attempting to retrieve the value.
    unsafe fn parameter_has_valid_sqlite_type(_: *mut sqlite3_value) -> bool {
        true
    }
}

macro_rules! raw_from_impl(
    ($t:ty, $f:ident, $c:expr) => (
        impl FromValue for $t {
            unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<$t> {
                Ok(ffi::$f(v))
            }

            unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
                sqlite3_value_numeric_type(v) == $c
            }
        }
    )
);

raw_from_impl!(c_int, sqlite3_value_int, ffi::SQLITE_INTEGER);
raw_from_impl!(i64, sqlite3_value_int64, ffi::SQLITE_INTEGER);

impl FromValue for bool {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<bool> {
        match ffi::sqlite3_value_int(v) {
            0 => Ok(false),
            _ => Ok(true),
        }
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_numeric_type(v) == ffi::SQLITE_INTEGER
    }
}

impl FromValue for c_double {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<c_double> {
        Ok(ffi::sqlite3_value_double(v))
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_numeric_type(v) == ffi::SQLITE_FLOAT ||
        sqlite3_value_numeric_type(v) == ffi::SQLITE_INTEGER
    }
}

impl FromValue for String {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<String> {
        let c_text = ffi::sqlite3_value_text(v);
        if c_text.is_null() {
            Ok("".to_string())
        } else {
            let c_slice = CStr::from_ptr(c_text as *const c_char).to_bytes();
            let utf8_str = str::from_utf8(c_slice);
            utf8_str.map(|s| s.to_string())
                    .map_err(|e| {
                        SqliteError {
                            code: 0,
                            message: e.to_string(),
                        }
                    })
        }
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_type(v) == ffi::SQLITE_TEXT
    }
}

impl FromValue for Vec<u8> {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<Vec<u8>> {
        use std::slice::from_raw_parts;
        let c_blob = ffi::sqlite3_value_blob(v);
        let len = ffi::sqlite3_value_bytes(v);

        assert!(len >= 0,
                "unexpected negative return from sqlite3_value_bytes");
        let len = len as usize;

        Ok(from_raw_parts(mem::transmute(c_blob), len).to_vec())
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_type(v) == ffi::SQLITE_BLOB
    }
}

impl<T: FromValue> FromValue for Option<T> {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<Option<T>> {
        if sqlite3_value_type(v) == ffi::SQLITE_NULL {
            Ok(None)
        } else {
            FromValue::parameter_value(v).map(|t| Some(t))
        }
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_type(v) == ffi::SQLITE_NULL || T::parameter_has_valid_sqlite_type(v)
    }
}

// sqlite3_user_data
// sqlite3_get_auxdata
// sqlite3_set_auxdata

pub type ScalarFunc = Option<extern "C" fn(ctx: *mut sqlite3_context,
                                           argc: c_int,
                                           argv: *mut *mut sqlite3_value)
                                          >;

impl SqliteConnection {
    // TODO pApp
    pub fn create_scalar_function(&self,
                                  fn_name: &str,
                                  n_arg: c_int,
                                  deterministic: bool,
                                  x_func: ScalarFunc)
                                  -> SqliteResult<()> {
        self.db.borrow_mut().create_scalar_function(fn_name, n_arg, deterministic, x_func)
    }
}

impl InnerSqliteConnection {
    pub fn create_scalar_function(&mut self,
                                  fn_name: &str,
                                  n_arg: c_int,
                                  deterministic: bool,
                                  x_func: ScalarFunc)
                                  -> SqliteResult<()> {
        let c_name = try!(str_to_cstring(fn_name));
        let mut flags = ffi::SQLITE_UTF8;
        if deterministic {
            flags |= ffi::SQLITE_DETERMINISTIC;
        }
        let r = unsafe {
            ffi::sqlite3_create_function_v2(self.db(),
                                            c_name.as_ptr(),
                                            n_arg,
                                            flags,
                                            ptr::null_mut(),
                                            x_func,
                                            None,
                                            None,
                                            None)
        };
        self.decode_result(r)
    }
}

#[cfg(test)]
mod test {
    extern crate regex;

    use std::boxed::Box;
    use std::ffi::CString;
    use std::mem;
    use libc::{c_int, c_double, c_void};
    use self::regex::Regex;

    use SqliteConnection;
    use ffi;
    use ffi::sqlite3_context;
    use ffi::sqlite3_value;
    use functions::{FromValue, ToResult};

    extern "C" fn half(ctx: *mut sqlite3_context, _: c_int, argv: *mut *mut sqlite3_value) {
        unsafe {
            let arg = *argv.offset(0);
            if c_double::parameter_has_valid_sqlite_type(arg) {
                let value = c_double::parameter_value(arg).unwrap() / 2f64;
                value.set_result(ctx);
            } else {
                ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_MISMATCH);
            }
        }
    }

    #[test]
    fn test_half() {
        let db = SqliteConnection::open_in_memory().unwrap();
        db.create_scalar_function("half", 1, true, Some(half)).unwrap();
        let result = db.query_row("SELECT half(6)", &[], |r| r.get::<f64>(0));

        assert_eq!(3f64, result.unwrap());
    }

    extern "C" fn regexp_free(raw: *mut c_void) {
        let _: Box<Regex> = unsafe { Box::from_raw(mem::transmute(raw)) };
    }

    extern "C" fn regexp(ctx: *mut sqlite3_context, _: c_int, argv: *mut *mut sqlite3_value) {
        unsafe {
            let mut re_ptr = ffi::sqlite3_get_auxdata(ctx, 0) as *const Regex;
            let need_re = re_ptr.is_null();
            if need_re {
                let raw = String::parameter_value(*argv.offset(0));
                if raw.is_err() {
                    let msg = CString::new(format!("{}", raw.unwrap_err())).unwrap();
                    ffi::sqlite3_result_error(ctx, msg.as_ptr(), -1);
                    return;
                }
                let comp = Regex::new(raw.unwrap().as_ref());
                if comp.is_err() {
                    let msg = CString::new(format!("{}", comp.unwrap_err())).unwrap();
                    ffi::sqlite3_result_error(ctx, msg.as_ptr(), -1);
                    return;
                }
                let re = Box::new(comp.unwrap());
                re_ptr = Box::into_raw(re);
            }

            let text = String::parameter_value(*argv.offset(1));
            if text.is_ok() {
                let text = text.unwrap();
                (*re_ptr).is_match(text.as_ref()).set_result(ctx);
            }

            if need_re {
                ffi::sqlite3_set_auxdata(ctx, 0, mem::transmute(re_ptr), Some(regexp_free));
            }
        }
    }

    #[test]
    fn test_regexp() {
        let db = SqliteConnection::open_in_memory().unwrap();
        db.create_scalar_function("regexp", 2, true, Some(regexp)).unwrap();
        let result = db.query_row("SELECT regexp('l.s[aeiouy]', 'lisa')",
                                  &[],
                                  |r| r.get::<bool>(0));

        assert_eq!(true, result.unwrap());
    }
}
<commit_msg>Let create_scalar_function take an FnMut instead of a extern "C" fn.<commit_after>//! Create or redefine SQL functions
use std::ffi::CStr;
use std::mem;
use std::str;
use libc::{c_int, c_double, c_char, c_void};

use ffi;
pub use ffi::sqlite3_context;
pub use ffi::sqlite3_value;
pub use ffi::sqlite3_value_type;
pub use ffi::sqlite3_value_numeric_type;

use types::Null;

use {SqliteResult, SqliteError, SqliteConnection, str_to_cstring, InnerSqliteConnection};

/// A trait for types that can be converted into the result of an SQL function.
pub trait ToResult {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context);
}

macro_rules! raw_to_impl(
    ($t:ty, $f:ident) => (
        impl ToResult for $t {
            unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
                ffi::$f(ctx, *self)
            }
        }
    )
);

raw_to_impl!(c_int, sqlite3_result_int);
raw_to_impl!(i64, sqlite3_result_int64);
raw_to_impl!(c_double, sqlite3_result_double);

impl<'a> ToResult for bool {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        match *self {
            true => ffi::sqlite3_result_int(ctx, 1),
            _ => ffi::sqlite3_result_int(ctx, 0),
        }
    }
}

impl<'a> ToResult for &'a str {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        let length = self.len();
        if length > ::std::i32::MAX as usize {
            ffi::sqlite3_result_error_toobig(ctx);
            return;
        }
        match str_to_cstring(self) {
            Ok(c_str) => {
                ffi::sqlite3_result_text(ctx,
                                         c_str.as_ptr(),
                                         length as c_int,
                                         ffi::SQLITE_TRANSIENT())
            }
            Err(_) => ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_MISUSE), // TODO sqlite3_result_error
        }
    }
}

impl ToResult for String {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        (&self[..]).set_result(ctx)
    }
}

impl<'a> ToResult for &'a [u8] {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        if self.len() > ::std::i32::MAX as usize {
            ffi::sqlite3_result_error_toobig(ctx);
            return;
        }
        ffi::sqlite3_result_blob(ctx,
                                 mem::transmute(self.as_ptr()),
                                 self.len() as c_int,
                                 ffi::SQLITE_TRANSIENT())
    }
}

impl ToResult for Vec<u8> {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        (&self[..]).set_result(ctx)
    }
}

impl<T: ToResult> ToResult for Option<T> {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        match *self {
            None => ffi::sqlite3_result_null(ctx),
            Some(ref t) => t.set_result(ctx),
        }
    }
}

impl ToResult for Null {
    unsafe fn set_result(&self, ctx: *mut sqlite3_context) {
        ffi::sqlite3_result_null(ctx)
    }
}

// sqlite3_result_error_code, c_int
// sqlite3_result_error_nomem
// sqlite3_result_error_toobig
// sqlite3_result_error, *const c_char, c_int
// sqlite3_result_zeroblob
// sqlite3_result_value

/// A trait for types that can be created from a SQLite function parameter value.
pub trait FromValue: Sized {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<Self>;

    /// FromValue types can implement this method and use sqlite3_value_type to check that
    /// the type reported by SQLite matches a type suitable for Self. This method is used
    /// by `???` to confirm that the parameter contains a valid type before
    /// attempting to retrieve the value.
    unsafe fn parameter_has_valid_sqlite_type(_: *mut sqlite3_value) -> bool {
        true
    }
}

macro_rules! raw_from_impl(
    ($t:ty, $f:ident, $c:expr) => (
        impl FromValue for $t {
            unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<$t> {
                Ok(ffi::$f(v))
            }

            unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
                sqlite3_value_numeric_type(v) == $c
            }
        }
    )
);

raw_from_impl!(c_int, sqlite3_value_int, ffi::SQLITE_INTEGER);
raw_from_impl!(i64, sqlite3_value_int64, ffi::SQLITE_INTEGER);

impl FromValue for bool {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<bool> {
        match ffi::sqlite3_value_int(v) {
            0 => Ok(false),
            _ => Ok(true),
        }
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_numeric_type(v) == ffi::SQLITE_INTEGER
    }
}

impl FromValue for c_double {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<c_double> {
        Ok(ffi::sqlite3_value_double(v))
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_numeric_type(v) == ffi::SQLITE_FLOAT ||
        sqlite3_value_numeric_type(v) == ffi::SQLITE_INTEGER
    }
}

impl FromValue for String {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<String> {
        let c_text = ffi::sqlite3_value_text(v);
        if c_text.is_null() {
            Ok("".to_string())
        } else {
            let c_slice = CStr::from_ptr(c_text as *const c_char).to_bytes();
            let utf8_str = str::from_utf8(c_slice);
            utf8_str.map(|s| s.to_string())
                    .map_err(|e| {
                        SqliteError {
                            code: 0,
                            message: e.to_string(),
                        }
                    })
        }
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_type(v) == ffi::SQLITE_TEXT
    }
}

impl FromValue for Vec<u8> {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<Vec<u8>> {
        use std::slice::from_raw_parts;
        let c_blob = ffi::sqlite3_value_blob(v);
        let len = ffi::sqlite3_value_bytes(v);

        assert!(len >= 0,
                "unexpected negative return from sqlite3_value_bytes");
        let len = len as usize;

        Ok(from_raw_parts(mem::transmute(c_blob), len).to_vec())
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_type(v) == ffi::SQLITE_BLOB
    }
}

impl<T: FromValue> FromValue for Option<T> {
    unsafe fn parameter_value(v: *mut sqlite3_value) -> SqliteResult<Option<T>> {
        if sqlite3_value_type(v) == ffi::SQLITE_NULL {
            Ok(None)
        } else {
            FromValue::parameter_value(v).map(|t| Some(t))
        }
    }

    unsafe fn parameter_has_valid_sqlite_type(v: *mut sqlite3_value) -> bool {
        sqlite3_value_type(v) == ffi::SQLITE_NULL || T::parameter_has_valid_sqlite_type(v)
    }
}

// sqlite3_user_data
// sqlite3_get_auxdata
// sqlite3_set_auxdata

pub trait ScalarFunction: FnMut(*mut sqlite3_context, c_int, *mut *mut sqlite3_value) {}
impl<F: FnMut(*mut sqlite3_context, c_int, *mut *mut sqlite3_value)> ScalarFunction for F {}

impl SqliteConnection {
    pub fn create_scalar_function<F>(&self,
                                     fn_name: &str,
                                     n_arg: c_int,
                                     deterministic: bool,
                                     x_func: F)
                                     -> SqliteResult<()>
        where F: ScalarFunction
    {
        self.db.borrow_mut().create_scalar_function(fn_name, n_arg, deterministic, x_func)
    }
}

impl InnerSqliteConnection {
    pub fn create_scalar_function<F>(&mut self,
                                     fn_name: &str,
                                     n_arg: c_int,
                                     deterministic: bool,
                                     x_func: F)
                                     -> SqliteResult<()>
        where F: ScalarFunction
    {
        extern "C" fn free_boxed_closure<F>(p: *mut c_void)
            where F: ScalarFunction
        {
            let _: Box<F> = unsafe { Box::from_raw(mem::transmute(p)) };
        }

        extern "C" fn call_boxed_closure<F>(ctx: *mut sqlite3_context,
                                            argc: c_int,
                                            argv: *mut *mut sqlite3_value)
            where F: ScalarFunction
        {
            unsafe {
                let boxed_f: *mut F = mem::transmute(ffi::sqlite3_user_data(ctx));
                assert!(!boxed_f.is_null(), "Internal error - null function pointer");
                (*boxed_f)(ctx, argc, argv);
            }
        }

        let boxed_f: *mut F = Box::into_raw(Box::new(x_func));
        let c_name = try!(str_to_cstring(fn_name));
        let mut flags = ffi::SQLITE_UTF8;
        if deterministic {
            flags |= ffi::SQLITE_DETERMINISTIC;
        }
        let r = unsafe {
            ffi::sqlite3_create_function_v2(self.db(),
                                            c_name.as_ptr(),
                                            n_arg,
                                            flags,
                                            mem::transmute(boxed_f),
                                            Some(call_boxed_closure::<F>),
                                            None,
                                            None,
                                            Some(free_boxed_closure::<F>))
        };
        self.decode_result(r)
    }
}

#[cfg(test)]
mod test {
    extern crate regex;

    use std::boxed::Box;
    use std::ffi::CString;
    use std::mem;
    use libc::{c_int, c_double, c_void};
    use self::regex::Regex;

    use SqliteConnection;
    use ffi;
    use ffi::sqlite3_context;
    use ffi::sqlite3_value;
    use functions::{FromValue, ToResult};

    fn half(ctx: *mut sqlite3_context, _: c_int, argv: *mut *mut sqlite3_value) {
        unsafe {
            let arg = *argv.offset(0);
            if c_double::parameter_has_valid_sqlite_type(arg) {
                let value = c_double::parameter_value(arg).unwrap() / 2f64;
                value.set_result(ctx);
            } else {
                ffi::sqlite3_result_error_code(ctx, ffi::SQLITE_MISMATCH);
            }
        }
    }

    #[test]
    fn test_function_half() {
        let db = SqliteConnection::open_in_memory().unwrap();
        db.create_scalar_function("half", 1, true, half).unwrap();
        let result = db.query_row("SELECT half(6)", &[], |r| r.get::<f64>(0));

        assert_eq!(3f64, result.unwrap());
    }

    extern "C" fn regexp_free(raw: *mut c_void) {
        let _: Box<Regex> = unsafe { Box::from_raw(mem::transmute(raw)) };
    }

    fn regexp(ctx: *mut sqlite3_context, _: c_int, argv: *mut *mut sqlite3_value) {
        unsafe {
            let mut re_ptr = ffi::sqlite3_get_auxdata(ctx, 0) as *const Regex;
            let need_re = re_ptr.is_null();
            if need_re {
                let raw = String::parameter_value(*argv.offset(0));
                if raw.is_err() {
                    let msg = CString::new(format!("{}", raw.unwrap_err())).unwrap();
                    ffi::sqlite3_result_error(ctx, msg.as_ptr(), -1);
                    return;
                }
                let comp = Regex::new(raw.unwrap().as_ref());
                if comp.is_err() {
                    let msg = CString::new(format!("{}", comp.unwrap_err())).unwrap();
                    ffi::sqlite3_result_error(ctx, msg.as_ptr(), -1);
                    return;
                }
                let re = Box::new(comp.unwrap());
                re_ptr = Box::into_raw(re);
            }

            let text = String::parameter_value(*argv.offset(1));
            if text.is_ok() {
                let text = text.unwrap();
                (*re_ptr).is_match(text.as_ref()).set_result(ctx);
            }

            if need_re {
                ffi::sqlite3_set_auxdata(ctx, 0, mem::transmute(re_ptr), Some(regexp_free));
            }
        }
    }

    #[test]
    fn test_function_regexp() {
        let db = SqliteConnection::open_in_memory().unwrap();
        db.create_scalar_function("regexp", 2, true, regexp).unwrap();
        let result = db.query_row("SELECT regexp('l.s[aeiouy]', 'lisa')",
                                  &[],
                                  |r| r.get::<bool>(0));

        assert_eq!(true, result.unwrap());
    }
}
<|endoftext|>


<commit_before>use std::num::One;
use extra::arc::Arc;
use nalgebra::na::{Cast, Translation, Rotate, Transform, AbsoluteRotate, AlgebraicVecExt};
use bounding_volume::{HasAABB, AABB};
use geom::{Plane, Ball, Box, Cone, Cylinder, Capsule, Implicit, HasMargin, CompoundAABB};
use ray::{Ray, RayCast, RayCastWithTransform};
use narrow::algorithm::minkowski_sampling::PreferedSamplingDirections;

/// Enumeration grouping all common shapes. Used to simplify collision detection
/// dispatch.
pub enum Geom<N, V, M> { // FIXME: rename that
    /// A plane geometry.
    PlaneGeom(Plane<N, V>),
    /// A compound geometry.
    CompoundGeom(Arc<CompoundAABB<N, V, M, Geom<N, V, M>>>),
    /// Geometry describable with a support function.
    ImplicitGeom(IGeom<N, V, M>)
}

/// Geometries with a support function.
#[deriving(Clone, Encodable, Decodable)]
pub enum IGeom<N, V, M> {
    /// A ball geometry.
    BallGeom(Ball<N>),
    /// A box geometry.
    BoxGeom(Box<N, V>),
    /// A cone geometry.
    ConeGeom(Cone<N>),
    /// A cylinder geometry.
    CylinderGeom(Cylinder<N>),
    /// A capsule geometry.
    CapsuleGeom(Capsule<N>)
}

impl<N: Send + Freeze + Clone,
     V: Send + Freeze + Clone,
     M: Send + Freeze + Clone>
Clone for Geom<N, V, M> {
    fn clone(&self) -> Geom<N, V, M> {
        match *self {
            PlaneGeom(ref p)    => PlaneGeom(p.clone()),
            CompoundGeom(ref c) => CompoundGeom(c.clone()),
            ImplicitGeom(ref i) => ImplicitGeom(i.clone())
        }
    }
}

impl<N: One, V, M> Geom<N, V, M> {
    /// Creates a new `Geom` from a plane.
    #[inline]
    pub fn new_plane(p: Plane<N, V>) -> Geom<N, V, M> {
        PlaneGeom(p)
    }

    /// Creates a new `Geom` from a compound geometry.
    #[inline]
    pub fn new_compound(c: Arc<CompoundAABB<N, V, M, Geom<N, V, M>>>)
        -> Geom<N, V, M> {
        CompoundGeom(c)
    }

    /// Creates a new `Geom` from a ball.
    #[inline]
    pub fn new_ball(b: Ball<N>) -> Geom<N, V, M> {
        ImplicitGeom(BallGeom(b))
    }

    /// Creates a new `Geom` from a cylinder.
    #[inline]
    pub fn new_cylinder(b: Cylinder<N>) -> Geom<N, V, M> {
        ImplicitGeom(CylinderGeom(b))
    }

    /// Creates a new `Geom` from a box.
    #[inline]
    pub fn new_box(b: Box<N, V>) -> Geom<N, V, M> {
        ImplicitGeom(BoxGeom(b))
    }

    /// Creates a new `Geom` from a cone.
    #[inline]
    pub fn new_cone(b: Cone<N>) -> Geom<N, V, M> {
        ImplicitGeom(ConeGeom(b))
    }

}

impl<N: Send + Freeze, V: Send + Freeze, M: Send + Freeze> Geom<N, V, M> {
    /**
     * Convenience method to extract a plane from the enumation. Fails if the
     * pattern `Plane(_)` is not matched.
     */
    #[inline]
    pub fn plane<'r>(&'r self) -> &'r Plane<N, V> {
        match *self {
            PlaneGeom(ref p) => p,
            _ => fail!("Unexpected geometry: this is not a plane.")
        }
    }

    /**
     * Convenience method to extract a compound geometry from the enumation. Fails if the
     * pattern `Compound(_)` is not matched.
     */
    #[inline]
    pub fn compound<'r>(&'r self) -> &'r CompoundAABB<N, V, M, Geom<N, V, M>> {
        match *self {
            CompoundGeom(ref c) => c.get(),
            _ => fail!("Unexpected geometry: this is not a compound.")
        }
    }

    /**
     * Convenience method to extract an implicit geometry from the enumation. Fails if the
     * pattern `Implicit(_)` is not matched.
     */
    #[inline]
    pub fn implicit<'r>(&'r self) -> &'r IGeom<N, V, M> {
        match *self {
            ImplicitGeom(ref i) => i,
            _ => fail!("Unexpected geometry: this is not an implicit.")
        }
    }

    /**
     * Convenience method to extract a ball from the enumation. Fails if the
     * pattern `Implicit(Ball(_))` is not matched.
     */
    #[inline]
    pub fn ball<'r>(&'r self) -> &'r Ball<N> {
        match *self {
            ImplicitGeom(BallGeom(ref b)) => b,
            _ => fail!("Unexpected geometry: this is not a ball.")
        }
    }

    /**
     * Convenience method to extract a cone from the enumation. Fails if the
     * pattern `Implicit(Cone(_))` is not matched.
     */
    #[inline]
    pub fn cone<'r>(&'r self) -> &'r Cone<N> {
        match *self {
            ImplicitGeom(ConeGeom(ref c)) => c,
            _ => fail!("Unexpected geometry: this is not a ball.")
        }
    }

    /**
     * Convenience method to extract a cylinder from the enumation. Fails if the
     * pattern `Implicit(Cylinder(_))` is not matched.
     */
    #[inline]
    pub fn cylinder<'r>(&'r self) -> &'r Cylinder<N> {
        match *self {
            ImplicitGeom(CylinderGeom(ref c)) => c,
            _ => fail!("Unexpected geometry: this is not a ball.")
        }
    }

    /**
     * Convenience method to extract a box from the enumation. Fails if the
     * pattern `Implicit(Box(_))` is not matched.
     */
    #[inline]
    pub fn box<'r>(&'r self) -> &'r Box<N, V> {
        match *self {
            ImplicitGeom(BoxGeom(ref b)) => b,
            _ => fail!("Unexpected geometry: this is not a ball.")
        }
    }
}

impl<N: Send + Freeze + Primitive + Orderable + Algebraic + Signed + Cast<f32> + Clone,
     V: Send + Freeze + AlgebraicVecExt<N> + Clone,
     M: Send + Freeze + Translation<V> + Rotate<V> + Transform<V> + Mul<M, M> + AbsoluteRotate<V>>
HasAABB<N, V, M> for Geom<N, V, M> {
    #[inline]
    fn aabb(&self, m: &M) -> AABB<N, V> {
        match *self {
            PlaneGeom(ref p)    => p.aabb(m),
            CompoundGeom(ref c) => c.get().aabb(m),
            ImplicitGeom(ref i) => {
                match *i {
                    BallGeom(ref b)     => b.aabb(m),
                    BoxGeom(ref b)      => b.aabb(m),
                    ConeGeom(ref c)     => c.aabb(m),
                    CylinderGeom(ref c) => c.aabb(m),
                    CapsuleGeom(ref c)  => c.aabb(m)
                }
            }
        }
    }
}

// FIXME: move this to the ray folder?
impl<N: Send + Freeze + Algebraic + Bounded + Orderable + Primitive + Float + Cast<f32> + Clone,
     V: 'static + Send + Freeze + AlgebraicVecExt<N> + Clone,
     M: Send + Freeze + Rotate<V> + Transform<V>>
RayCast<N, V> for Geom<N, V, M> {
    #[inline]
    fn toi_with_ray(&self, ray: &Ray<V>) -> Option<N> {
        match *self {
            PlaneGeom(ref p)    => p.toi_with_ray(ray),
            CompoundGeom(ref c) => c.get().toi_with_ray(ray),
            ImplicitGeom(ref i) => {
                match *i {
                    BallGeom(ref b)     => b.toi_with_ray(ray),
                    BoxGeom(ref b)      => b.toi_with_ray(ray),
                    ConeGeom(ref c)     => c.toi_with_ray(ray),
                    CylinderGeom(ref c) => c.toi_with_ray(ray),
                    CapsuleGeom(ref c)  => c.toi_with_ray(ray),
                }
            }
        }
    }

    #[inline]
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        match *self {
            PlaneGeom(ref p)    => p.toi_and_normal_with_ray(ray),
            CompoundGeom(ref c) => c.get().toi_and_normal_with_ray(ray),
            ImplicitGeom(ref i) => {
                match *i {
                    BallGeom(ref b)     => b.toi_and_normal_with_ray(ray),
                    BoxGeom(ref b)      => b.toi_and_normal_with_ray(ray),
                    ConeGeom(ref c)     => c.toi_and_normal_with_ray(ray),
                    CylinderGeom(ref c) => c.toi_and_normal_with_ray(ray),
                    CapsuleGeom(ref c)  => c.toi_and_normal_with_ray(ray),
                }
            }
        }
    }
}

impl<N: Algebraic + Bounded + Orderable + Primitive + Float + Cast<f32> + Clone,
     V: 'static + AlgebraicVecExt<N> + Clone,
     M: Rotate<V> + Transform<V>>
RayCastWithTransform<N, V, M> for Geom<N, V, M> { }

impl<N: Clone + Add<N, N>, V, M> HasMargin<N> for IGeom<N, V, M> {
    #[inline]
    fn margin(&self) -> N {
        match *self {
            BallGeom(ref b)     => b.margin(),
            BoxGeom(ref b)      => b.margin(),
            ConeGeom(ref c)     => c.margin(),
            CylinderGeom(ref c) => c.margin(),
            CapsuleGeom(ref c)  => c.margin()
        }
    }
}

impl<N: Algebraic + Signed + Orderable + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Translation<V> + Rotate<V> + Transform<V>>
Implicit<N, V, M> for IGeom<N, V, M> {
    #[inline]
    fn support_point_without_margin(&self, transform: &M, dir: &V) -> V {
        match *self {
            BallGeom(ref b)     => b.support_point_without_margin(transform, dir),
            BoxGeom(ref b)      => b.support_point_without_margin(transform, dir),
            ConeGeom(ref c)     => c.support_point_without_margin(transform, dir),
            CylinderGeom(ref c) => c.support_point_without_margin(transform, dir),
            CapsuleGeom(ref c)  => c.support_point_without_margin(transform, dir)
        }
    }

    #[inline]
    fn support_point(&self, transform: &M, dir: &V) -> V {
        match *self {
            BallGeom(ref b)     => b.support_point(transform, dir),
            BoxGeom(ref b)      => b.support_point(transform, dir),
            ConeGeom(ref c)     => c.support_point(transform, dir),
            CylinderGeom(ref c) => c.support_point(transform, dir),
            CapsuleGeom(ref c)  => c.support_point(transform, dir)
        }
    }
}

impl<N: One,
     V: AlgebraicVecExt<N>,
     M: Rotate<V>>
PreferedSamplingDirections<V, M> for IGeom<N, V, M> {
    #[inline(always)]
    fn sample(&self, transform: &M, f: &fn(V)) {
        match *self {
            BallGeom(ref b)     => b.sample(transform, f),
            BoxGeom(ref b)      => b.sample(transform, f),
            ConeGeom(ref c)     => c.sample(transform, f),
            CylinderGeom(ref c) => c.sample(transform, f),
            CapsuleGeom(ref c)  => c.sample(transform, f)
        }
    }
}
<commit_msg>Simplify the construction of a Geom geometry.<commit_after>use std::num::One;
use extra::arc::Arc;
use nalgebra::na::{Cast, Translation, Rotate, Transform, AbsoluteRotate, AlgebraicVecExt, Dim};
use bounding_volume::{HasAABB, AABB};
use geom::{Plane, Ball, Box, Cone, Cylinder, Capsule, Implicit, HasMargin, CompoundAABB};
use ray::{Ray, RayCast, RayCastWithTransform};
use narrow::algorithm::minkowski_sampling::PreferedSamplingDirections;

/// Enumeration grouping all common shapes. Used to simplify collision detection
/// dispatch.
pub enum Geom<N, V, M> { // FIXME: rename that
    /// A plane geometry.
    PlaneGeom(Plane<N, V>),
    /// A compound geometry.
    CompoundGeom(Arc<CompoundAABB<N, V, M, Geom<N, V, M>>>),
    /// Geometry describable with a support function.
    ImplicitGeom(IGeom<N, V, M>)
}

/// Geometries with a support function.
#[deriving(Clone, Encodable, Decodable)]
pub enum IGeom<N, V, M> {
    /// A ball geometry.
    BallGeom(Ball<N>),
    /// A box geometry.
    BoxGeom(Box<N, V>),
    /// A cone geometry.
    ConeGeom(Cone<N>),
    /// A cylinder geometry.
    CylinderGeom(Cylinder<N>),
    /// A capsule geometry.
    CapsuleGeom(Capsule<N>)
}

impl<N: Send + Freeze + Clone,
     V: Send + Freeze + Clone,
     M: Send + Freeze + Clone>
Clone for Geom<N, V, M> {
    fn clone(&self) -> Geom<N, V, M> {
        match *self {
            PlaneGeom(ref p)    => PlaneGeom(p.clone()),
            CompoundGeom(ref c) => CompoundGeom(c.clone()),
            ImplicitGeom(ref i) => ImplicitGeom(i.clone())
        }
    }
}

impl<N: One + Algebraic + Signed + Cast<f32>,
     V: Dim + AlgebraicVecExt<N>,
     M>
Geom<N, V, M> {
    /// Creates a new `Geom` from a plane.
    #[inline]
    pub fn new_plane(normal: V) -> Geom<N, V, M> {
        PlaneGeom(Plane::new(normal))
    }

    /// Creates a new `Geom` from a compound geometry.
    #[inline]
    pub fn new_compound(c: Arc<CompoundAABB<N, V, M, Geom<N, V, M>>>)
        -> Geom<N, V, M> {
        CompoundGeom(c)
    }

    /// Creates a new `Geom` from a ball.
    #[inline]
    pub fn new_ball(radius: N) -> Geom<N, V, M> {
        ImplicitGeom(BallGeom(Ball::new(radius)))
    }

    /// Creates a new `Geom` from a cylinder.
    #[inline]
    pub fn new_cylinder(half_height: N, radius: N) -> Geom<N, V, M> {
        ImplicitGeom(CylinderGeom(Cylinder::new(half_height, radius)))
    }

    /// Creates a new `Geom` from a cylinder.
    #[inline]
    pub fn new_cylinder_with_margin(half_height: N,
                                    radius:      N,
                                    margin:      N)
                                    -> Geom<N, V, M> {
        ImplicitGeom(CylinderGeom(Cylinder::new_with_margin(half_height, radius, margin)))
    }

    /// Creates a new `Geom` from a box.
    #[inline]
    pub fn new_box(half_extents: V) -> Geom<N, V, M> {
        ImplicitGeom(BoxGeom(Box::new(half_extents)))
    }

    /// Creates a new `Geom` from a box.
    #[inline]
    pub fn new_box_with_margin(half_extents: V, margin: N) -> Geom<N, V, M> {
        ImplicitGeom(BoxGeom(Box::new_with_margin(half_extents, margin)))
    }

    /// Creates a new `Geom` from a cone.
    #[inline]
    pub fn new_cone(half_height: N, radius: N) -> Geom<N, V, M> {
        ImplicitGeom(ConeGeom(Cone::new(half_height, radius)))
    }

    /// Creates a new `Geom` from a cone.
    #[inline]
    pub fn new_cone_with_margin(half_height: N, radius: N, margin: N) -> Geom<N, V, M> {
        ImplicitGeom(ConeGeom(Cone::new_with_margin(half_height, radius, margin)))
    }
}

impl<N: Send + Freeze, V: Send + Freeze, M: Send + Freeze> Geom<N, V, M> {
    /**
     * Convenience method to extract a plane from the enumation. Fails if the
     * pattern `Plane(_)` is not matched.
     */
    #[inline]
    pub fn plane<'r>(&'r self) -> &'r Plane<N, V> {
        match *self {
            PlaneGeom(ref p) => p,
            _ => fail!("Unexpected geometry: this is not a plane.")
        }
    }

    /**
     * Convenience method to extract a compound geometry from the enumation. Fails if the
     * pattern `Compound(_)` is not matched.
     */
    #[inline]
    pub fn compound<'r>(&'r self) -> &'r CompoundAABB<N, V, M, Geom<N, V, M>> {
        match *self {
            CompoundGeom(ref c) => c.get(),
            _ => fail!("Unexpected geometry: this is not a compound.")
        }
    }

    /**
     * Convenience method to extract an implicit geometry from the enumation. Fails if the
     * pattern `Implicit(_)` is not matched.
     */
    #[inline]
    pub fn implicit<'r>(&'r self) -> &'r IGeom<N, V, M> {
        match *self {
            ImplicitGeom(ref i) => i,
            _ => fail!("Unexpected geometry: this is not an implicit.")
        }
    }

    /**
     * Convenience method to extract a ball from the enumation. Fails if the
     * pattern `Implicit(Ball(_))` is not matched.
     */
    #[inline]
    pub fn ball<'r>(&'r self) -> &'r Ball<N> {
        match *self {
            ImplicitGeom(BallGeom(ref b)) => b,
            _ => fail!("Unexpected geometry: this is not a ball.")
        }
    }

    /**
     * Convenience method to extract a cone from the enumation. Fails if the
     * pattern `Implicit(Cone(_))` is not matched.
     */
    #[inline]
    pub fn cone<'r>(&'r self) -> &'r Cone<N> {
        match *self {
            ImplicitGeom(ConeGeom(ref c)) => c,
            _ => fail!("Unexpected geometry: this is not a ball.")
        }
    }

    /**
     * Convenience method to extract a cylinder from the enumation. Fails if the
     * pattern `Implicit(Cylinder(_))` is not matched.
     */
    #[inline]
    pub fn cylinder<'r>(&'r self) -> &'r Cylinder<N> {
        match *self {
            ImplicitGeom(CylinderGeom(ref c)) => c,
            _ => fail!("Unexpected geometry: this is not a ball.")
        }
    }

    /**
     * Convenience method to extract a box from the enumation. Fails if the
     * pattern `Implicit(Box(_))` is not matched.
     */
    #[inline]
    pub fn box<'r>(&'r self) -> &'r Box<N, V> {
        match *self {
            ImplicitGeom(BoxGeom(ref b)) => b,
            _ => fail!("Unexpected geometry: this is not a ball.")
        }
    }
}

impl<N: Send + Freeze + Primitive + Orderable + Algebraic + Signed + Cast<f32> + Clone,
     V: Send + Freeze + AlgebraicVecExt<N> + Clone,
     M: Send + Freeze + Translation<V> + Rotate<V> + Transform<V> + Mul<M, M> + AbsoluteRotate<V>>
HasAABB<N, V, M> for Geom<N, V, M> {
    #[inline]
    fn aabb(&self, m: &M) -> AABB<N, V> {
        match *self {
            PlaneGeom(ref p)    => p.aabb(m),
            CompoundGeom(ref c) => c.get().aabb(m),
            ImplicitGeom(ref i) => {
                match *i {
                    BallGeom(ref b)     => b.aabb(m),
                    BoxGeom(ref b)      => b.aabb(m),
                    ConeGeom(ref c)     => c.aabb(m),
                    CylinderGeom(ref c) => c.aabb(m),
                    CapsuleGeom(ref c)  => c.aabb(m)
                }
            }
        }
    }
}

// FIXME: move this to the ray folder?
impl<N: Send + Freeze + Algebraic + Bounded + Orderable + Primitive + Float + Cast<f32> + Clone,
     V: 'static + Send + Freeze + AlgebraicVecExt<N> + Clone,
     M: Send + Freeze + Rotate<V> + Transform<V>>
RayCast<N, V> for Geom<N, V, M> {
    #[inline]
    fn toi_with_ray(&self, ray: &Ray<V>) -> Option<N> {
        match *self {
            PlaneGeom(ref p)    => p.toi_with_ray(ray),
            CompoundGeom(ref c) => c.get().toi_with_ray(ray),
            ImplicitGeom(ref i) => {
                match *i {
                    BallGeom(ref b)     => b.toi_with_ray(ray),
                    BoxGeom(ref b)      => b.toi_with_ray(ray),
                    ConeGeom(ref c)     => c.toi_with_ray(ray),
                    CylinderGeom(ref c) => c.toi_with_ray(ray),
                    CapsuleGeom(ref c)  => c.toi_with_ray(ray),
                }
            }
        }
    }

    #[inline]
    fn toi_and_normal_with_ray(&self, ray: &Ray<V>) -> Option<(N, V)> {
        match *self {
            PlaneGeom(ref p)    => p.toi_and_normal_with_ray(ray),
            CompoundGeom(ref c) => c.get().toi_and_normal_with_ray(ray),
            ImplicitGeom(ref i) => {
                match *i {
                    BallGeom(ref b)     => b.toi_and_normal_with_ray(ray),
                    BoxGeom(ref b)      => b.toi_and_normal_with_ray(ray),
                    ConeGeom(ref c)     => c.toi_and_normal_with_ray(ray),
                    CylinderGeom(ref c) => c.toi_and_normal_with_ray(ray),
                    CapsuleGeom(ref c)  => c.toi_and_normal_with_ray(ray),
                }
            }
        }
    }
}

impl<N: Algebraic + Bounded + Orderable + Primitive + Float + Cast<f32> + Clone,
     V: 'static + AlgebraicVecExt<N> + Clone,
     M: Rotate<V> + Transform<V>>
RayCastWithTransform<N, V, M> for Geom<N, V, M> { }

impl<N: Clone + Add<N, N>, V, M> HasMargin<N> for IGeom<N, V, M> {
    #[inline]
    fn margin(&self) -> N {
        match *self {
            BallGeom(ref b)     => b.margin(),
            BoxGeom(ref b)      => b.margin(),
            ConeGeom(ref c)     => c.margin(),
            CylinderGeom(ref c) => c.margin(),
            CapsuleGeom(ref c)  => c.margin()
        }
    }
}

impl<N: Algebraic + Signed + Orderable + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Translation<V> + Rotate<V> + Transform<V>>
Implicit<N, V, M> for IGeom<N, V, M> {
    #[inline]
    fn support_point_without_margin(&self, transform: &M, dir: &V) -> V {
        match *self {
            BallGeom(ref b)     => b.support_point_without_margin(transform, dir),
            BoxGeom(ref b)      => b.support_point_without_margin(transform, dir),
            ConeGeom(ref c)     => c.support_point_without_margin(transform, dir),
            CylinderGeom(ref c) => c.support_point_without_margin(transform, dir),
            CapsuleGeom(ref c)  => c.support_point_without_margin(transform, dir)
        }
    }

    #[inline]
    fn support_point(&self, transform: &M, dir: &V) -> V {
        match *self {
            BallGeom(ref b)     => b.support_point(transform, dir),
            BoxGeom(ref b)      => b.support_point(transform, dir),
            ConeGeom(ref c)     => c.support_point(transform, dir),
            CylinderGeom(ref c) => c.support_point(transform, dir),
            CapsuleGeom(ref c)  => c.support_point(transform, dir)
        }
    }
}

impl<N: One,
     V: AlgebraicVecExt<N>,
     M: Rotate<V>>
PreferedSamplingDirections<V, M> for IGeom<N, V, M> {
    #[inline(always)]
    fn sample(&self, transform: &M, f: &fn(V)) {
        match *self {
            BallGeom(ref b)     => b.sample(transform, f),
            BoxGeom(ref b)      => b.sample(transform, f),
            ConeGeom(ref c)     => c.sample(transform, f),
            CylinderGeom(ref c) => c.sample(transform, f),
            CapsuleGeom(ref c)  => c.sample(transform, f)
        }
    }
}
<|endoftext|>


<commit_before>use fall_tree::{File, AstNode};
use fall_tree::visitor::{Visitor, NodeVisitor};

use {FallFile, RefExpr, CallExpr};
use editor_api::{Diagnostic, Severity};

mod diagnostics;
mod db;
mod query;

use self::diagnostics::DiagnosticSink;
pub use self::query::{CallKind, RefKind};

pub struct Analysis<'f> {
    db: db::DB<'f>,
    file: FallFile<'f>,
}

impl<'f> Analysis<'f> {
    pub fn new(file: FallFile) -> Analysis {
        Analysis { db: db::DB::new(file), file }
    }

    pub fn file(&self) -> FallFile<'f> {
        self.file
    }

    pub fn resolve_call(&self, call: CallExpr<'f>) -> Option<CallKind<'f>> {
        self.db.get(query::ResolveCall(call))
    }

    pub fn resolve_reference(&self, ref_: RefExpr<'f>) -> Option<RefKind<'f>> {
        self.db.get(query::ResolveRefExpr(ref_))
    }

    pub fn collect_all_diagnostics(&self) -> Vec<Diagnostic> {
        Visitor(())
            .visit::<RefExpr, _>(|_, ref_| { self.resolve_reference(ref_); })
            .visit::<CallExpr, _>(|_, call| { self.resolve_call(call); })
            .walk_recursively_children_first(self.file().node());
        self.db.get(query::UnusedRules);
        self.diagnostics()
    }

    #[allow(unused)] // for debugging
    pub fn debug_diagnostics(&self) -> String {
        diagnostics::debug_diagnostics(&self.diagnostics(), self.file().node().text())
    }

    fn diagnostics(&self) -> Vec<Diagnostic> {
        let mut result = self.db.diagnostics.lock().unwrap().clone();

        result.sort_by_key(|d| {
            let priority = match d.severity {
                Severity::Error => 0,
                Severity::Warning => 1,
            };
            (priority, d.range.start(), d.range.end())
        });
        result
    }
}

pub struct FileWithAnalysis {
    rent: rent::R
}

impl FileWithAnalysis {
    pub fn new(text: String) -> FileWithAnalysis {
        FileWithAnalysis::from_file(::parse(text))
    }

    fn from_file(file: File) -> FileWithAnalysis {
        FileWithAnalysis {
            rent: rent::R::new(Box::new(file), |file| {
                Analysis::new(FallFile::new(file.root()))
            })
        }
    }

    pub fn file(&self) -> &File {
        self.rent.head()
    }

    pub fn analyse<T, F: FnOnce(&Analysis) -> T>(&self, f: F) -> T {
        self.rent.rent(|a: &Analysis| f(a))
    }
}

rental! {
    mod rent {
        use super::*;

        #[rental]
        pub struct R {
            file: Box<File>,
            analysis: Analysis<'file>
        }
    }
}

#[test]
fn analysis_is_sync() {
    fn assert_is_sync<T: Sync>() {}
    assert_is_sync::<Analysis>();
}

#[cfg(test)]
fn check_diagnostics(code: &str, expected_diagnostics: &str) {
    use editor_api::Severity;
    use fall_tree::test_util::report_diff;
    let file = ::editor_api::analyse(code.to_string());

    file.analyse(|a| {
        let d = a.collect_all_diagnostics();
        let actual = d.into_iter().map(|d| {
            let s = match d.severity {
                Severity::Error => 'E',
                Severity::Warning => 'W',
            };
            format!("{}: {} {}", a.file().node().text().slice(d.range), s, d.message)
        }).collect::<Vec<_>>().join("\n");

        report_diff(expected_diagnostics, &actual);
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use analysis::CallKind;

    use fall_tree::search;
    use fall_tree::search::ast;

    use ::test_util::parse_with_caret;

    #[test]
    fn test_diagnostics() {
        check_diagnostics(r"
       pub rule foo { <eof x> }
       rule bar { foo <abracadabra>}
       rule baz { <prev_is foo> <prev_is bar> <prev_is {foo}>}
       rule dupe { dupe }
       rule dupe { dupe }
    ", "\
<eof x>: E Wrong number of arguments, expected 0, got 1
x: E Unresolved reference
abracadabra: E Unresolved reference
<prev_is bar>: E <prev_is> arguments must be public rules
<prev_is {foo}>: E <prev_is> arguments must be public rules
dupe: E Duplicate rule
baz: W Unused rule
dupe: W Unused rule");
    }

    #[test]
    fn test_resolve_no_args() {
        check_resolved("rule foo { <^eof> }", "Eof");
        check_resolved("rule foo { <^any> }", "Any");
        check_resolved("rule foo { <^commit> }", "Commit");
    }

    #[test]
    fn test_resolve_simple_args() {
        check_resolved("rule foo { <^not a> }", "Not(RefExpr@[16; 17))");
        check_resolved("rule foo { <^with_skip a b> }", "WithSkip(RefExpr@[22; 23), RefExpr@[24; 25))");
        check_resolved("rule foo { <^layer a b> }", "Layer(RefExpr@[18; 19), RefExpr@[20; 21))");
    }

    #[test]
    fn test_resolve_layer() {
        check_resolved("rule foo { <^enter 'ctx' a> <is_in 'ctx' >}", "Enter(0, RefExpr@[24; 25))");
        check_resolved("rule foo { <^exit  'ctx' a> <is_in 'ctx' >}", "Exit(0, RefExpr@[24; 25))");

        check_resolved("rule foo { <is_in 'ctx1'> <^enter 'ctx2' a> <is_in 'ctx1'> <enter 'ctx2' a> }", "Enter(1, RefExpr@[40; 41))");
        check_resolved("rule foo { <is_in 'ctx1'> <^exit  'ctx2' a> <is_in 'ctx1'> <exit  'ctx2' a> }", "Exit(1, RefExpr@[40; 41))");

        check_resolved(
            "rule foo { <enter 'ctx1' a> <enter 'ctx2' b> <^is_in 'ctx2'> <is_in 'ctx1'> }",
            "IsIn(1)"
        );

        check(
            r" rule foo { <^is_in foo>}",
            None,
            r#"[(foo, "Context should be a single quoted string")]"#,
        )
    }

    #[test]
    fn test_not() {
        resolve_call("rule foo { <^not bar>}", |c, _| {
            let c = c.unwrap();
            assert_eq!(format!("{:?}", c), "Not(RefExpr@[16; 19))");
        })
    }

    #[test]
    fn test_unresolved_call() {
        check(
            r"rule foo { <^abracadabra>}",
            None,
            r#"[(abracadabra, "Unresolved reference")]"#
        );
    }

    #[test]
    fn wrong_arity() {
        check(
            "rule foo { <^eof foo> }",
            Some(CallKind::Eof),
            r#"[(<eof foo>, "Wrong number of arguments, expected 0, got 1")]"#
        );

        check(
            "rule foo { <^any foo bar> }",
            Some(CallKind::Any),
            r#"[(<any foo bar>, "Wrong number of arguments, expected 0, got 2")]"#
        );

        check(
            "rule foo { <^commit foo bar baz> }",
            Some(CallKind::Commit),
            r#"[(<commit foo bar baz>, "Wrong number of arguments, expected 0, got 3")]"#
        );

        check(
            "rule foo { <^not> }",
            None,
            r#"[(<not>, "Wrong number of arguments, expected 1, got 0")]"#
        );
    }

    #[test]
    fn check_prev_is() {
        check_resolved(
            "pub rule foo {} pub rule bar {} rule baz { <^prev_is foo bar> }",
            "PrevIs([1, 2])"
        )
    }

    #[test]
    fn call_custom_rule() {
        check_resolved(
            "rule foo { <^bar a b>} rule bar(x, y) { }",
            "RuleCall(SynRule@[22; 40), [(0, RefExpr@[16; 17)), (1, RefExpr@[18; 19))])"
        );
        ::analysis::check_diagnostics(
            "rule foo { <bar <eof>>} rule bar(x, y) { }",
            "<bar <eof>>: E Expected 2 arguments, got 1"
        )
    }

    fn check(text: &str, kind: Option<CallKind>, diagnostics: &str) {
        resolve_call(text, |c, a| {
            assert_eq!(c, kind);
            assert_eq!(a.debug_diagnostics(), diagnostics);
        })
    }

    fn check_resolved(text: &str, kind: &str) {
        resolve_call(text, |c, a| {
            let c = c.unwrap();
            assert_eq!(format!("{:?}", c), kind);
            assert_eq!(a.debug_diagnostics(), "[]");
        })
    }

    fn resolve_call<F: FnOnce(Option<CallKind>, Analysis)>(text: &str, f: F) {
        let (file, caret) = parse_with_caret(&text);
        let call = {
            let leaf = search::find_leaf_at_offset(file.root(), caret)
                .left_biased().unwrap();
            ast::ancestor_exn(leaf)
        };
        let a = Analysis::new(::ast(&file));
        let c = a.resolve_call(call);
        f(c, a)
    }
}

<commit_msg>Minor<commit_after>use fall_tree::{File, AstNode};
use fall_tree::visitor::{Visitor, NodeVisitor};

use {FallFile, RefExpr, CallExpr};
use editor_api::{Diagnostic, Severity};

mod diagnostics;
mod db;
mod query;

use self::diagnostics::DiagnosticSink;
pub use self::query::{CallKind, RefKind};

pub struct Analysis<'f> {
    db: db::DB<'f>,
    file: FallFile<'f>,
}

impl<'f> Analysis<'f> {
    pub fn new(file: FallFile) -> Analysis {
        Analysis { db: db::DB::new(file), file }
    }

    pub fn file(&self) -> FallFile<'f> {
        self.file
    }

    pub fn resolve_call(&self, call: CallExpr<'f>) -> Option<CallKind<'f>> {
        self.db.get(query::ResolveCall(call))
    }

    pub fn resolve_reference(&self, ref_: RefExpr<'f>) -> Option<RefKind<'f>> {
        self.db.get(query::ResolveRefExpr(ref_))
    }

    pub fn collect_all_diagnostics(&self) -> Vec<Diagnostic> {
        Visitor(())
            .visit::<RefExpr, _>(|_, ref_| { self.resolve_reference(ref_); })
            .visit::<CallExpr, _>(|_, call| { self.resolve_call(call); })
            .walk_recursively_children_first(self.file().node());
        self.db.get(query::UnusedRules);
        self.diagnostics()
    }

    #[allow(unused)] // for debugging
    pub fn debug_diagnostics(&self) -> String {
        diagnostics::debug_diagnostics(&self.diagnostics(), self.file().node().text())
    }

    fn diagnostics(&self) -> Vec<Diagnostic> {
        let mut result = self.db.diagnostics.lock().unwrap().clone();

        result.sort_by_key(|d| {
            let priority = match d.severity {
                Severity::Error => 0,
                Severity::Warning => 1,
            };
            (priority, d.range.start(), d.range.end())
        });
        result
    }
}

pub struct FileWithAnalysis {
    rent: rent::R
}

impl FileWithAnalysis {
    pub fn new(text: String) -> FileWithAnalysis {
        FileWithAnalysis::from_file(::parse(text))
    }

    fn from_file(file: File) -> FileWithAnalysis {
        FileWithAnalysis {
            rent: rent::R::new(Box::new(file), |file| {
                Analysis::new(FallFile::new(file.root()))
            })
        }
    }

    pub fn file(&self) -> &File {
        self.rent.head()
    }

    pub fn analyse<T, F: FnOnce(&Analysis) -> T>(&self, f: F) -> T {
        self.rent.rent(|a: &Analysis| f(a))
    }
}

rental! {
    mod rent {
        use super::*;

        #[rental]
        pub struct R {
            file: Box<File>,
            analysis: Analysis<'file>
        }
    }
}

#[test]
fn analysis_is_sync() {
    fn assert_is_sync<T: Sync>() {}
    assert_is_sync::<Analysis>();
}

#[cfg(test)]
fn check_diagnostics(code: &str, expected_diagnostics: &str) {
    use editor_api::Severity;
    use fall_tree::test_util::report_diff;
    let file = ::editor_api::analyse(code.to_string());

    file.analyse(|a| {
        let d = a.collect_all_diagnostics();
        let actual = d.into_iter().map(|d| {
            let s = match d.severity {
                Severity::Error => 'E',
                Severity::Warning => 'W',
            };
            format!("{} {}: {}", s, a.file().node().text().slice(d.range), d.message)
        }).collect::<Vec<_>>().join("\n");

        report_diff(expected_diagnostics, &actual);
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use analysis::CallKind;

    use fall_tree::search;
    use fall_tree::search::ast;

    use ::test_util::parse_with_caret;

    #[test]
    fn test_diagnostics() {
        check_diagnostics(r"
       pub rule foo { <eof x> }
       rule bar { foo <abracadabra>}
       rule baz { <prev_is foo> <prev_is bar> <prev_is {foo}>}
       rule dupe { dupe }
       rule dupe { dupe }
    ", "\
E <eof x>: Wrong number of arguments, expected 0, got 1
E x: Unresolved reference
E abracadabra: Unresolved reference
E <prev_is bar>: <prev_is> arguments must be public rules
E <prev_is {foo}>: <prev_is> arguments must be public rules
E dupe: Duplicate rule
W baz: Unused rule
W dupe: Unused rule");
    }

    #[test]
    fn test_resolve_no_args() {
        check_resolved("rule foo { <^eof> }", "Eof");
        check_resolved("rule foo { <^any> }", "Any");
        check_resolved("rule foo { <^commit> }", "Commit");
    }

    #[test]
    fn test_resolve_simple_args() {
        check_resolved("rule foo { <^not a> }", "Not(RefExpr@[16; 17))");
        check_resolved("rule foo { <^with_skip a b> }", "WithSkip(RefExpr@[22; 23), RefExpr@[24; 25))");
        check_resolved("rule foo { <^layer a b> }", "Layer(RefExpr@[18; 19), RefExpr@[20; 21))");
    }

    #[test]
    fn test_resolve_layer() {
        check_resolved("rule foo { <^enter 'ctx' a> <is_in 'ctx' >}", "Enter(0, RefExpr@[24; 25))");
        check_resolved("rule foo { <^exit  'ctx' a> <is_in 'ctx' >}", "Exit(0, RefExpr@[24; 25))");

        check_resolved("rule foo { <is_in 'ctx1'> <^enter 'ctx2' a> <is_in 'ctx1'> <enter 'ctx2' a> }", "Enter(1, RefExpr@[40; 41))");
        check_resolved("rule foo { <is_in 'ctx1'> <^exit  'ctx2' a> <is_in 'ctx1'> <exit  'ctx2' a> }", "Exit(1, RefExpr@[40; 41))");

        check_resolved(
            "rule foo { <enter 'ctx1' a> <enter 'ctx2' b> <^is_in 'ctx2'> <is_in 'ctx1'> }",
            "IsIn(1)"
        );

        check(
            r" rule foo { <^is_in foo>}",
            None,
            r#"[(foo, "Context should be a single quoted string")]"#,
        )
    }

    #[test]
    fn test_not() {
        resolve_call("rule foo { <^not bar>}", |c, _| {
            let c = c.unwrap();
            assert_eq!(format!("{:?}", c), "Not(RefExpr@[16; 19))");
        })
    }

    #[test]
    fn test_unresolved_call() {
        check(
            r"rule foo { <^abracadabra>}",
            None,
            r#"[(abracadabra, "Unresolved reference")]"#
        );
    }

    #[test]
    fn wrong_arity() {
        check(
            "rule foo { <^eof foo> }",
            Some(CallKind::Eof),
            r#"[(<eof foo>, "Wrong number of arguments, expected 0, got 1")]"#
        );

        check(
            "rule foo { <^any foo bar> }",
            Some(CallKind::Any),
            r#"[(<any foo bar>, "Wrong number of arguments, expected 0, got 2")]"#
        );

        check(
            "rule foo { <^commit foo bar baz> }",
            Some(CallKind::Commit),
            r#"[(<commit foo bar baz>, "Wrong number of arguments, expected 0, got 3")]"#
        );

        check(
            "rule foo { <^not> }",
            None,
            r#"[(<not>, "Wrong number of arguments, expected 1, got 0")]"#
        );
    }

    #[test]
    fn check_prev_is() {
        check_resolved(
            "pub rule foo {} pub rule bar {} rule baz { <^prev_is foo bar> }",
            "PrevIs([1, 2])"
        )
    }

    #[test]
    fn call_custom_rule() {
        check_resolved(
            "rule foo { <^bar a b>} rule bar(x, y) { }",
            "RuleCall(SynRule@[22; 40), [(0, RefExpr@[16; 17)), (1, RefExpr@[18; 19))])"
        );
        ::analysis::check_diagnostics(
            "rule foo { <bar <eof>>} rule bar(x, y) { }",
            "E <bar <eof>>: Expected 2 arguments, got 1"
        )
    }

    fn check(text: &str, kind: Option<CallKind>, diagnostics: &str) {
        resolve_call(text, |c, a| {
            assert_eq!(c, kind);
            assert_eq!(a.debug_diagnostics(), diagnostics);
        })
    }

    fn check_resolved(text: &str, kind: &str) {
        resolve_call(text, |c, a| {
            let c = c.unwrap();
            assert_eq!(format!("{:?}", c), kind);
            assert_eq!(a.debug_diagnostics(), "[]");
        })
    }

    fn resolve_call<F: FnOnce(Option<CallKind>, Analysis)>(text: &str, f: F) {
        let (file, caret) = parse_with_caret(&text);
        let call = {
            let leaf = search::find_leaf_at_offset(file.root(), caret)
                .left_biased().unwrap();
            ast::ancestor_exn(leaf)
        };
        let a = Analysis::new(::ast(&file));
        let c = a.resolve_call(call);
        f(c, a)
    }
}

<|endoftext|>


<commit_before>#![feature(globs)]

extern crate graphics;
extern crate piston;
extern crate sdl2_game_window;
extern crate opengl_graphics;

use opengl_graphics::{
    Gl,
    Texture,
};
use sdl2_game_window::GameWindowSDL2;
use graphics::*;
use piston::{
    AssetStore,
    Game,
    GameIteratorSettings,
    GameWindowSettings,
    RenderArgs,
};

pub struct App {
    gl: Gl,
    image: Option<Texture>,
}

impl App {
    /// Creates a new application.
    pub fn new() -> App {
        App {
            image: None,
            gl: Gl::new(),
        }
    }
}

impl Game for App {
    fn load(&mut self) {
        let asset_store = AssetStore::from_folder("assets");
        let image = asset_store.path("rust-logo.png").unwrap();
        self.image = Some(Texture::from_path(&image).unwrap());
    }

    fn render(&mut self, args: &mut RenderArgs) {
        let ref mut gl = self.gl;
        gl.viewport(0, 0, args.width as i32, args.height as i32);
        let ref c = Context::abs(args.width as f64, args.height as f64);
        c.rgb(1.0, 1.0, 1.0).draw(gl);

        // Draw image.
        c.image(self.image.as_ref().unwrap()).draw(gl);
    }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
    // Run gui on the main thread.
    native::start(argc, argv, main)
}

fn main() {
    let mut window = GameWindowSDL2::new(
        GameWindowSettings {
            title: "Image".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
        }
    );

    let mut app = App::new();
    let game_iter_settings = GameIteratorSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    app.run(&mut window, &game_iter_settings);
}

<commit_msg>Removed example 'image.rs'<commit_after><|endoftext|>


<commit_before>extern crate discord;

use discord::{Discord, VoiceConnection};
use discord::model::{Event, ChannelId, ServerId};
use std::env;

fn main() {
	// Log in to Discord using the email and password in the environment
	let discord = Discord::new(
		&env::var("DISCORD_EMAIL").expect("DISCORD_EMAIL"),
		&env::var("DISCORD_PASSWORD").expect("DISCORD_PASSWORD")
	).expect("login failed");

	// Establish and use a websocket connection
	let (mut connection, ready) = discord.connect().expect("connect failed");
	let mut voice = VoiceConnection::new(ready.user.id.clone());

	connection.voice_connect(
		&ServerId(env::var("DISCORD_SERVER").expect("DISCORD_SERVER")),
		&ChannelId(env::var("DISCORD_CHANNEL").expect("DISCORD_CHANNEL")),
	);

	voice.push_file(&env::var("DISCORD_AUDIO").expect("DISCORD_AUDIO")).expect("File read failed");

	println!("Ready.");
	loop {
		let event = match connection.recv_event() {
			Ok(event) => event,
			Err(err) => {
				println!("Receive error: {:?}", err);
				break
			}
		};
		voice.update(&event);
		match event {
			Event::Closed(n) => {
				println!("Discord closed on us with status {}", n);
				break
			}
			_ => {}
		}
	}

	// Log out from the API
	discord.logout().expect("logout failed");
}
<commit_msg>Update voice example for changes<commit_after>extern crate discord;

use discord::Discord;
use discord::voice::{self, VoiceConnection};
use discord::model::{Event, ChannelId, ServerId};
use std::env;

fn main() {
	// Log in to Discord using the email and password in the environment
	let discord = Discord::new(
		&env::var("DISCORD_EMAIL").expect("DISCORD_EMAIL"),
		&env::var("DISCORD_PASSWORD").expect("DISCORD_PASSWORD")
	).expect("login failed");

	// Establish and use a websocket connection
	let (mut connection, ready) = discord.connect().expect("connect failed");
	let mut voice = VoiceConnection::new(ready.user.id.clone());

	connection.voice_connect(
		&ServerId(env::var("DISCORD_SERVER").expect("DISCORD_SERVER")),
		&ChannelId(env::var("DISCORD_CHANNEL").expect("DISCORD_CHANNEL")),
	);

	voice.play(
		voice::open_ffmpeg_stream(
			&env::var("DISCORD_AUDIO").expect("DISCORD_AUDIO")
		).expect("File read failed")
	);

	println!("Ready.");
	loop {
		let event = match connection.recv_event() {
			Ok(event) => event,
			Err(err) => {
				println!("Receive error: {:?}", err);
				break
			}
		};
		voice.update(&event);
		match event {
			Event::Closed(n) => {
				println!("Discord closed on us with status {}", n);
				break
			}
			_ => {}
		}
	}

	// Log out from the API
	discord.logout().expect("logout failed");
}
<|endoftext|>