<commit_before>use std::{mem, ptr};
use libc::{self, c_char};
use std::slice;
use std::cell::RefCell;
use std::collections::VecMap;

use super::get_ladspa_descriptor;

// essentially ladspa.h API translated to rust.
mod ladspa {
    use libc::{c_void, c_char};

    pub type Data = f32;
    pub type Properties = i32;
    pub type PortDescriptor = i32;
    pub type PortRangeHintDescriptor = i32;

    pub type Handle = *mut c_void;

    #[repr(C)]
    #[derive(Copy)]
    pub struct PortRangeHint {
        pub hint_descriptor: PortRangeHintDescriptor,
        pub lower_bound: Data,
        pub upper_bound: Data,
    }

    #[repr(C)]
    #[allow(missing_copy_implementations)] // Remove this for a fun warning/suggestion cycle!
    pub struct Descriptor {
        pub unique_id: u64,
        pub label: *const c_char,
        pub properties: Properties,
        pub name: *const c_char,
        pub maker: *const c_char,
        pub copyright: *const c_char,
        pub port_count: u64,
        pub port_descriptors: *mut PortDescriptor,
        pub port_names: *mut *const c_char,
        pub port_range_hints: *mut PortRangeHint,
        pub implementation_data: *mut c_void,
        pub instantiate: extern "C" fn(descriptor: *const Descriptor, sample_rate: u64) -> Handle,
        pub connect_port: extern "C" fn(instance: Handle, port: u64, data_location: *mut Data),
        pub activate: extern "C" fn(instance: Handle),
        pub run: extern "C" fn(instance: Handle, sample_count: u64),
        pub run_adding: extern "C" fn(instance: Handle, sample_count: u64),
        pub set_run_adding_gain: extern "C" fn(instance: Handle, gain: Data),
        pub deactivate: extern "C" fn(instance: Handle),
        pub cleanup: extern "C" fn(instance: Handle),
    }
}

unsafe fn alloc<T>(num: u64) -> *mut T {
    let ptr: *mut T = mem::transmute(libc::malloc(num * mem::size_of::<T>() as u64));
    if ptr == ptr::null_mut() {
        panic!("malloc returned null!");
    }
    ptr
}

unsafe fn free<T>(x: *const T) {
    libc::free(mem::transmute(x));
}

unsafe fn make_c_str(s: &'static str) -> *const c_char {
    let c_str: *mut c_char = alloc::<c_char>(s.len() as u64 + 1);
    ptr::copy_memory(c_str, mem::transmute(s.as_ptr()), s.len());
    slice::from_raw_parts_mut(c_str, s.len() + 1)[s.len()] = 0; // add the null terminator
    c_str
}

static mut init_done: bool = false;
static mut num_descriptors: u64 = 0;
static mut descriptors: Option<*mut *mut ladspa::Descriptor> = None;
static MAX_DESCRIPTORS: u64 = 32;

// It seems that ladspa_descriptor is deleted during link time optimization unless we
// call it from somewhere.
#[allow(dead_code)]
unsafe fn _lto_workaround() {
    ladspa_descriptor(0);
}

#[no_mangle]
/// This is exported so that your plugin is recognised by LADSPA hosts. Don't worry about it.
pub unsafe extern "C" fn ladspa_descriptor(index: u64) -> *mut ladspa::Descriptor {
    if !init_done {
        libc::atexit(global_destruct);
        descriptors = Some(alloc(MAX_DESCRIPTORS));
        init_done = true;
    }

    // If it's already been generated, return the cached copy.
    if index < num_descriptors {
        return *descriptors.unwrap().offset(index as isize);
    }

    match get_ladspa_descriptor(index) {
        Some(plugin) => {
            let desc: &mut ladspa::Descriptor = mem::transmute(alloc::<ladspa::Descriptor>(1));

            // the following is ok because none of the fields in the descriptor have
            // destructors. if they did rust would try to drop null pointers on write.

            // copy data fields
            desc.unique_id = plugin.unique_id;
            desc.label = make_c_str(plugin.label);
            desc.properties = plugin.properties.bits();
            desc.name = make_c_str(plugin.name);
            desc.maker = make_c_str(plugin.maker);
            desc.copyright = make_c_str(plugin.copyright);
            desc.port_count = plugin.ports.len() as u64;
            desc.port_descriptors = alloc::<ladspa::PortDescriptor>(desc.port_count);
            desc.port_names = alloc::<*const c_char>(desc.port_count);
            desc.port_range_hints = alloc::<ladspa::PortRangeHint>(desc.port_count);
            for i in 0..desc.port_count as usize {
                *desc.port_descriptors.offset(i as isize)
                    = plugin.ports[i].desc as i32;

                *desc.port_names.offset(i as isize)
                    = make_c_str(plugin.ports[i].name);

                let port = &plugin.ports[i];
                *desc.port_range_hints.offset(i as isize)
                    = ladspa::PortRangeHint {
                        hint_descriptor: port.hint.map(|x| x.bits()).unwrap_or(0) |
                            port.default.map(|x| x as i32).unwrap_or(0) |
                            port.lower_bound.map(|_| 1).unwrap_or(0) |
                            port.upper_bound.map(|_| 2).unwrap_or(0),
                        lower_bound: port.lower_bound.unwrap_or(0_f32),
                        upper_bound: port.upper_bound.unwrap_or(0_f32),
                    };
            }

            // implementation_data holds the original rustic descriptor
            desc.implementation_data = mem::transmute(alloc::<super::PluginDescriptor>(1));
            ptr::write(mem::transmute::<_, *mut super::PluginDescriptor>
                    (desc.implementation_data), plugin);

            // attach functions
            desc.instantiate = instantiate;
            desc.connect_port = connect_port;
            desc.run = run;
            desc.cleanup = cleanup;
            // u8 is arbitrary, just need some type here
            desc.run_adding = mem::transmute(ptr::null::<*const u8>());
            desc.set_run_adding_gain = mem::transmute(ptr::null::<*const u8>());
            desc.activate = activate;
            desc.deactivate = deactivate;

            // store in global descriptor table
            let ptr = mem::transmute(desc);
            *descriptors.unwrap().offset(num_descriptors as isize) = ptr;
            num_descriptors += 1;
            if num_descriptors >= MAX_DESCRIPTORS {
                panic!("The program tried to define more than the max supported number of descriptors currently supported - this usually means you forgot to return None at some point in get_ladspa_descriptor.");
            }

            ptr
        }
        None => ptr::null_mut()
    }
}

// these next two should free everything allocated in ladspa_descriptor - checked with valgrind.
extern "C" fn global_destruct() {
    unsafe {
        if !init_done {
            return;
        }
        for i in 0..num_descriptors {
            free_descriptor(*descriptors.unwrap().offset(i as isize));
        }
        free(descriptors.unwrap());
    }
}

unsafe fn free_descriptor(ptr: *mut ladspa::Descriptor) {
    let desc: &mut ladspa::Descriptor = mem::transmute(ptr);
    free(desc.label);
    free(desc.name);
    free(desc.maker);
    free(desc.copyright);
    free(desc.port_descriptors);
    for i in 0..desc.port_count {
        free(*desc.port_names.offset(i as isize));
    }
    free(desc.port_names);
    free(desc.port_range_hints);
    let rust_desc: *mut super::PluginDescriptor = mem::transmute(desc.implementation_data);
    drop(ptr::read(rust_desc));
    free(desc.implementation_data);
    free(ptr);
}

// The handle that is given to ladspa.
struct Handle<'a> {
    descriptor: &'static super::PluginDescriptor,
    plugin: Box<super::Plugin + 'static>,
    port_map: VecMap<super::PortConnection<'a>>,
    ports: Vec<&'a super::PortConnection<'a>>,
}

extern "C" fn instantiate(descriptor: *const ladspa::Descriptor, sample_rate: u64) -> ladspa::Handle {
    unsafe {
        let desc: &mut ladspa::Descriptor = mem::transmute(descriptor);

        let rust_desc: &super::PluginDescriptor = mem::transmute(desc.implementation_data);
        let rust_plugin = (rust_desc.new)(rust_desc, sample_rate);
        let port_map: VecMap<super::PortConnection> = VecMap::new();
        let ports: Vec<&super::PortConnection> = Vec::new();

        let heap_handle: *mut Handle = alloc::<Handle>(1);
        ptr::write(mem::transmute(&(*heap_handle).descriptor), rust_desc);
        ptr::write(mem::transmute(&(*heap_handle).plugin), rust_plugin);
        ptr::write(mem::transmute(&(*heap_handle).port_map), port_map);
        ptr::write(mem::transmute(&(*heap_handle).ports), ports);
        mem::transmute(heap_handle)
    }
}

extern "C" fn connect_port(instance: ladspa::Handle, port_num: u64, data_location: *mut ladspa::Data) {
    unsafe {
        let handle: &mut Handle = mem::transmute(instance);

        let port = handle.descriptor.ports[port_num as usize];

        // Create appropriate pointers to port data. Mutable locations are wrapped in refcells.
        let data = match port.desc {
            super::PortDescriptor::AudioInput => {
                super::PortData::AudioInput( // Initially create a size 0 slice because we don't know how big
                    slice::from_raw_parts(mem::transmute(data_location), 0)) // it will be yet.
            },
            super::PortDescriptor::AudioOutput => {
                super::PortData::AudioOutput(RefCell::new( // Same here.
                    slice::from_raw_parts_mut(mem::transmute(data_location), 0)))
            },
            super::PortDescriptor::ControlInput => {
                super::PortData::ControlInput(mem::transmute(data_location))
            },
            super::PortDescriptor::ControlOutput => {
                super::PortData::ControlOutput(RefCell::new(mem::transmute(data_location)))
            },
            super::PortDescriptor::Invalid => panic!("Invalid port descriptor!"),
        };

        let conn = super::PortConnection {
            port: port,
            data: data,
        };
        handle.port_map.insert(port_num as usize, conn);

        // Depends on the assumption that ports will be recreated whenever port_map changes
        let handle_ptr: *mut Handle = mem::transmute(instance);
        if handle.port_map.len() == handle.descriptor.ports.len() {
            (*handle_ptr).ports = (0..handle.port_map.len()).map(|i| &handle.port_map[i]).collect();
        }
    }
}

extern "C" fn run(instance: ladspa::Handle, sample_count: u64) {
    unsafe {
        let handle: &mut Handle = mem::transmute(instance);
        for (_, port) in handle.port_map.iter_mut() {
            match port.data {
                super::PortData::AudioOutput(ref mut data) => {
                    let ptr = mem::transmute(data.borrow().as_ptr());
                    *data.borrow_mut() = slice::from_raw_parts_mut(ptr, sample_count as usize);
                },
                super::PortData::AudioInput(ref mut data) => {
                    let ptr = mem::transmute(data.as_ptr());
                    *data = slice::from_raw_parts(ptr, sample_count as usize);
                },
                _ => { }
            }
        }
        handle.plugin.run(sample_count as usize, handle.ports.as_slice());
    }
}

extern "C" fn activate(instance: ladspa::Handle) {
    unsafe{
        let handle: &mut Handle = mem::transmute(instance);
        handle.plugin.activate();
    }
}
extern "C" fn deactivate(instance: ladspa::Handle) {
    unsafe {
        let handle: &mut Handle = mem::transmute(instance);
        handle.plugin.deactivate();
    }
}

/*
extern "C" fn run_adding(instance: ladspa::Handle, sample_count: u64) {
}
extern "C" fn set_run_adding_gain(instance: ladspa::Handle, gain: ladspa::Data) {
}
*/

extern "C" fn cleanup(instance: ladspa::Handle) {
    unsafe {
        let handle: *mut Handle = mem::transmute(instance);
        drop(ptr::read(handle));
        free(instance);
    }
}

<commit_msg>Remove some unnecessary transmutes<commit_after>use std::{mem, ptr};
use libc::{self, c_char};
use std::slice;
use std::cell::RefCell;
use std::collections::VecMap;

use super::get_ladspa_descriptor;

// essentially ladspa.h API translated to rust.
mod ladspa {
    use libc::{c_void, c_char};

    pub type Data = f32;
    pub type Properties = i32;
    pub type PortDescriptor = i32;
    pub type PortRangeHintDescriptor = i32;

    pub type Handle = *mut c_void;

    #[repr(C)]
    #[derive(Copy)]
    pub struct PortRangeHint {
        pub hint_descriptor: PortRangeHintDescriptor,
        pub lower_bound: Data,
        pub upper_bound: Data,
    }

    #[repr(C)]
    #[allow(missing_copy_implementations)] // Remove this for a fun warning/suggestion cycle!
    pub struct Descriptor {
        pub unique_id: u64,
        pub label: *const c_char,
        pub properties: Properties,
        pub name: *const c_char,
        pub maker: *const c_char,
        pub copyright: *const c_char,
        pub port_count: u64,
        pub port_descriptors: *mut PortDescriptor,
        pub port_names: *mut *const c_char,
        pub port_range_hints: *mut PortRangeHint,
        pub implementation_data: *mut c_void,
        pub instantiate: extern "C" fn(descriptor: *const Descriptor, sample_rate: u64) -> Handle,
        pub connect_port: extern "C" fn(instance: Handle, port: u64, data_location: *mut Data),
        pub activate: extern "C" fn(instance: Handle),
        pub run: extern "C" fn(instance: Handle, sample_count: u64),
        pub run_adding: extern "C" fn(instance: Handle, sample_count: u64),
        pub set_run_adding_gain: extern "C" fn(instance: Handle, gain: Data),
        pub deactivate: extern "C" fn(instance: Handle),
        pub cleanup: extern "C" fn(instance: Handle),
    }
}

unsafe fn alloc<T>(num: u64) -> *mut T {
    let ptr: *mut T = mem::transmute(libc::malloc(num * mem::size_of::<T>() as u64));
    if ptr == ptr::null_mut() {
        panic!("malloc returned null!");
    }
    ptr
}

unsafe fn free<T>(x: *const T) {
    libc::free(mem::transmute(x));
}

unsafe fn make_c_str(s: &'static str) -> *const c_char {
    let c_str: *mut c_char = alloc::<c_char>(s.len() as u64 + 1);
    ptr::copy_memory(c_str, mem::transmute(s.as_ptr()), s.len());
    slice::from_raw_parts_mut(c_str, s.len() + 1)[s.len()] = 0; // add the null terminator
    c_str
}

static mut init_done: bool = false;
static mut num_descriptors: u64 = 0;
static mut descriptors: Option<*mut *mut ladspa::Descriptor> = None;
static MAX_DESCRIPTORS: u64 = 32;

// It seems that ladspa_descriptor is deleted during link time optimization unless we
// call it from somewhere.
#[allow(dead_code)]
unsafe fn _lto_workaround() {
    ladspa_descriptor(0);
}

#[no_mangle]
/// This is exported so that your plugin is recognised by LADSPA hosts. Don't worry about it.
pub unsafe extern "C" fn ladspa_descriptor(index: u64) -> *mut ladspa::Descriptor {
    if !init_done {
        libc::atexit(global_destruct);
        descriptors = Some(alloc(MAX_DESCRIPTORS));
        init_done = true;
    }

    // If it's already been generated, return the cached copy.
    if index < num_descriptors {
        return *descriptors.unwrap().offset(index as isize);
    }

    match get_ladspa_descriptor(index) {
        Some(plugin) => {
            let desc: &mut ladspa::Descriptor = mem::transmute(alloc::<ladspa::Descriptor>(1));

            // the following is ok because none of the fields in the descriptor have
            // destructors. if they did rust would try to drop null pointers on write.

            // copy data fields
            desc.unique_id = plugin.unique_id;
            desc.label = make_c_str(plugin.label);
            desc.properties = plugin.properties.bits();
            desc.name = make_c_str(plugin.name);
            desc.maker = make_c_str(plugin.maker);
            desc.copyright = make_c_str(plugin.copyright);
            desc.port_count = plugin.ports.len() as u64;
            desc.port_descriptors = alloc::<ladspa::PortDescriptor>(desc.port_count);
            desc.port_names = alloc::<*const c_char>(desc.port_count);
            desc.port_range_hints = alloc::<ladspa::PortRangeHint>(desc.port_count);
            for i in 0..desc.port_count as usize {
                *desc.port_descriptors.offset(i as isize)
                    = plugin.ports[i].desc as i32;

                *desc.port_names.offset(i as isize)
                    = make_c_str(plugin.ports[i].name);

                let port = &plugin.ports[i];
                *desc.port_range_hints.offset(i as isize)
                    = ladspa::PortRangeHint {
                        hint_descriptor: port.hint.map(|x| x.bits()).unwrap_or(0) |
                            port.default.map(|x| x as i32).unwrap_or(0) |
                            port.lower_bound.map(|_| 1).unwrap_or(0) |
                            port.upper_bound.map(|_| 2).unwrap_or(0),
                        lower_bound: port.lower_bound.unwrap_or(0_f32),
                        upper_bound: port.upper_bound.unwrap_or(0_f32),
                    };
            }

            // implementation_data holds the original rustic descriptor
            desc.implementation_data = mem::transmute(alloc::<super::PluginDescriptor>(1));
            ptr::write(mem::transmute::<_, *mut super::PluginDescriptor>
                    (desc.implementation_data), plugin);

            // attach functions
            desc.instantiate = instantiate;
            desc.connect_port = connect_port;
            desc.run = run;
            desc.cleanup = cleanup;
            // u8 is arbitrary, just need some type here
            desc.run_adding = mem::transmute(ptr::null::<*const u8>());
            desc.set_run_adding_gain = mem::transmute(ptr::null::<*const u8>());
            desc.activate = activate;
            desc.deactivate = deactivate;

            // store in global descriptor table
            let ptr = mem::transmute(desc);
            *descriptors.unwrap().offset(num_descriptors as isize) = ptr;
            num_descriptors += 1;
            if num_descriptors >= MAX_DESCRIPTORS {
                panic!("The program tried to define more than the max supported number of descriptors currently supported - this usually means you forgot to return None at some point in get_ladspa_descriptor.");
            }

            ptr
        }
        None => ptr::null_mut()
    }
}

// these next two should free everything allocated in ladspa_descriptor - checked with valgrind.
extern "C" fn global_destruct() {
    unsafe {
        if !init_done {
            return;
        }
        for i in 0..num_descriptors {
            free_descriptor(*descriptors.unwrap().offset(i as isize));
        }
        free(descriptors.unwrap());
    }
}

unsafe fn free_descriptor(ptr: *mut ladspa::Descriptor) {
    let desc: &mut ladspa::Descriptor = mem::transmute(ptr);
    free(desc.label);
    free(desc.name);
    free(desc.maker);
    free(desc.copyright);
    free(desc.port_descriptors);
    for i in 0..desc.port_count {
        free(*desc.port_names.offset(i as isize));
    }
    free(desc.port_names);
    free(desc.port_range_hints);
    let rust_desc: *mut super::PluginDescriptor = mem::transmute(desc.implementation_data);
    drop(ptr::read(rust_desc));
    free(desc.implementation_data);
    free(ptr);
}

// The handle that is given to ladspa.
struct Handle<'a> {
    descriptor: &'static super::PluginDescriptor,
    plugin: Box<super::Plugin + 'static>,
    port_map: VecMap<super::PortConnection<'a>>,
    ports: Vec<&'a super::PortConnection<'a>>,
}

extern "C" fn instantiate(descriptor: *const ladspa::Descriptor, sample_rate: u64) -> ladspa::Handle {
    unsafe {
        let desc: &mut ladspa::Descriptor = mem::transmute(descriptor);

        let rust_desc: &super::PluginDescriptor = mem::transmute(desc.implementation_data);
        let rust_plugin = (rust_desc.new)(rust_desc, sample_rate);
        let port_map: VecMap<super::PortConnection> = VecMap::new();
        let ports: Vec<&super::PortConnection> = Vec::new();

        let heap_handle: *mut Handle = alloc::<Handle>(1);
        ptr::write(mem::transmute(&(*heap_handle).descriptor), rust_desc);
        ptr::write(mem::transmute(&(*heap_handle).plugin), rust_plugin);
        ptr::write(mem::transmute(&(*heap_handle).port_map), port_map);
        ptr::write(mem::transmute(&(*heap_handle).ports), ports);
        mem::transmute(heap_handle)
    }
}

extern "C" fn connect_port(instance: ladspa::Handle, port_num: u64, data_location: *mut ladspa::Data) {
    unsafe {
        let handle: &mut Handle = mem::transmute(instance);

        let port = handle.descriptor.ports[port_num as usize];

        // Create appropriate pointers to port data. Mutable locations are wrapped in refcells.
        let data = match port.desc {
            super::PortDescriptor::AudioInput => {
                super::PortData::AudioInput( // Initially create a size 0 slice because we don't know how big
                    slice::from_raw_parts(data_location, 0)) // it will be yet.
            },
            super::PortDescriptor::AudioOutput => {
                super::PortData::AudioOutput(RefCell::new( // Same here.
                    slice::from_raw_parts_mut(data_location, 0)))
            },
            super::PortDescriptor::ControlInput => {
                super::PortData::ControlInput(mem::transmute(data_location))
            },
            super::PortDescriptor::ControlOutput => {
                super::PortData::ControlOutput(RefCell::new(mem::transmute(data_location)))
            },
            super::PortDescriptor::Invalid => panic!("Invalid port descriptor!"),
        };

        let conn = super::PortConnection {
            port: port,
            data: data,
        };
        handle.port_map.insert(port_num as usize, conn);

        // Depends on the assumption that ports will be recreated whenever port_map changes
        let handle_ptr: *mut Handle = mem::transmute(instance);
        if handle.port_map.len() == handle.descriptor.ports.len() {
            (*handle_ptr).ports = (0..handle.port_map.len()).map(|i| &handle.port_map[i]).collect();
        }
    }
}

extern "C" fn run(instance: ladspa::Handle, sample_count: u64) {
    unsafe {
        let handle: &mut Handle = mem::transmute(instance);
        for (_, port) in handle.port_map.iter_mut() {
            match port.data {
                super::PortData::AudioOutput(ref mut data) => {
                    let ptr = data.borrow_mut().as_mut_ptr();
                    *data.borrow_mut() = slice::from_raw_parts_mut(ptr, sample_count as usize);
                },
                super::PortData::AudioInput(ref mut data) => {
                    let ptr = data.as_ptr();
                    *data = slice::from_raw_parts(ptr, sample_count as usize);
                },
                _ => { }
            }
        }
        handle.plugin.run(sample_count as usize, handle.ports.as_slice());
    }
}

extern "C" fn activate(instance: ladspa::Handle) {
    unsafe{
        let handle: &mut Handle = mem::transmute(instance);
        handle.plugin.activate();
    }
}
extern "C" fn deactivate(instance: ladspa::Handle) {
    unsafe {
        let handle: &mut Handle = mem::transmute(instance);
        handle.plugin.deactivate();
    }
}

/*
extern "C" fn run_adding(instance: ladspa::Handle, sample_count: u64) {
}
extern "C" fn set_run_adding_gain(instance: ladspa::Handle, gain: ladspa::Data) {
}
*/

extern "C" fn cleanup(instance: ladspa::Handle) {
    unsafe {
        let handle: *mut Handle = mem::transmute(instance);
        drop(ptr::read(handle));
        free(instance);
    }
}

<|endoftext|>


<commit_before>#![crate_name = "posix"]
#![crate_type = "lib"]
#![allow(non_camel_case_types)]
#![allow(raw_pointer_deriving)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![feature(macro_rules)]

pub use os::arch::{char_t, schar_t, uchar_t, short_t, ushort_t, int_t, uint_t, long_t};
pub use os::arch::{ulong_t, longlong_t, ulonglong_t, float_t, double_t, size_t, ssize_t};

mod macros {
    #![macro_escape]

    #[macro_escape]
    macro_rules! new {
        ($name:ident) => {
            impl $name {
                pub fn new() -> $name {
                    unsafe { ::std::mem::zeroed() }
                }
            }
        }
    }
}

pub mod aio;
pub mod arpa;
pub mod cpio;
pub mod ctype;
pub mod dirent;
pub mod dlfcn;
pub mod errno;
pub mod fcntl;
pub mod fenv;
pub mod float;
pub mod fmtmsg;
pub mod fnmatch;
pub mod ftw;
pub mod glob;
pub mod grp;
pub mod iconv;
pub mod inttypes;
pub mod langinfo;
pub mod libgen;
pub mod limits;
pub mod locale;
pub mod monetary;
pub mod mqueue;
pub mod ndbm;
pub mod net;
pub mod netdb;
pub mod netinet;
pub mod nl_types;
pub mod poll;
pub mod pthread;
pub mod pwd;
pub mod regex;
pub mod sched;
pub mod search;
pub mod semaphore;
pub mod setjmp;
pub mod spawn;
pub mod stddef;
pub mod stdint;
pub mod stdio;
pub mod stdlib;
pub mod string;
pub mod strings;
pub mod stropts;
pub mod signal;
pub mod sys;
pub mod syslog;
pub mod tar;
pub mod termios;
pub mod time;
pub mod ulimit;
pub mod unistd;
pub mod utime;
pub mod utmpx;
pub mod wchar;
pub mod wctype;
pub mod wordexp;

#[repr(u8)]
#[derive(Copy)]
pub enum void_t {
    __variant1,
    __variant2,
}

#[cfg(target_os = "linux")]
mod os {
    #[cfg(target_arch = "x86_64")]
    pub mod arch {
        pub type bool_t       = i8;
        pub type char_t       = i8;
        pub type schar_t      = i8;
        pub type uchar_t      = u8;
        pub type short_t      = i16;
        pub type ushort_t     = u16;
        pub type int_t        = i32;
        pub type uint_t       = u32;
        pub type long_t       = i64;
        pub type ulong_t      = u64;
        pub type longlong_t   = i64;
        pub type ulonglong_t  = u64;
        pub type float_t      = f32;
        pub type double_t     = f64;
        pub type size_t       = u64;
        pub type ssize_t      = i64;
    }

    #[cfg(target_arch = "x86")]
    pub mod arch {
        pub type bool_t       = i8;
        pub type char_t       = i8;
        pub type schar_t      = i8;
        pub type uchar_t      = u8;
        pub type short_t      = i16;
        pub type ushort_t     = u16;
        pub type int_t        = i32;
        pub type uint_t       = u32;
        pub type long_t       = i32;
        pub type ulong_t      = u32;
        pub type longlong_t   = i64;
        pub type ulonglong_t  = u64;
        pub type float_t      = f32;
        pub type double_t     = f64;
        pub type size_t       = u32;
        pub type ssize_t      = i32;
    }
}

pub trait NTStr {
    fn as_ptr(&self) -> *const char_t;
}

pub struct NTStrBorrowed<'a> {
    data: &'a [u8],
}

pub struct NTStrOwned {
    vec: Vec<u8>,
}

impl<'a> NTStr for NTStrBorrowed<'a> {
    fn as_ptr(&self) -> *const char_t {
        self.data.as_ptr() as *const _
    }
}

impl NTStr for NTStrOwned {
    fn as_ptr(&self) -> *const char_t {
        self.vec.as_ptr() as *const _
    }
}

pub trait ToNTStr {
    fn to_nt_str(&self) -> NTStrOwned;
}

impl<'a> ToNTStr for &'a [u8] {
    fn to_nt_str(&self) -> NTStrOwned {
        let mut vec = self.to_vec();
        vec.push(0);
        NTStrOwned { vec: vec }
    }
}

impl ToNTStr for Path {
    fn to_nt_str(&self) -> NTStrOwned {
        use std::path::{BytesContainer};
        self.container_as_bytes().to_nt_str()
    }
}

impl<'a> ToNTStr for &'a str {
    fn to_nt_str(&self) -> NTStrOwned {
        self.as_bytes().to_nt_str()
    }
}

pub trait AsNTStr<'a> {
    fn as_nt_str(&'a self) -> NTStrBorrowed<'a>;
}

impl<'a> AsNTStr<'a> for &'a [u8] {
    fn as_nt_str(&'a self) -> NTStrBorrowed<'a> {
        NTStrBorrowed { data: *self }
    }
}

pub trait AsSlice: Sized {
    fn as_slice(&self) -> &[u8] {
        unsafe {
            ::std::mem::transmute(::std::raw::Slice {
                data: self as *const _ as *const u8,
                len: ::std::mem::size_of_val(self),
            })
        }
    }
}

pub trait AsMutSlice: Sized {
    fn as_mut_slice(&mut self) -> &mut [u8] {
        unsafe {
            ::std::mem::transmute(::std::raw::Slice {
                data: self as *mut _ as *const u8,
                len: ::std::mem::size_of_val(self),
            })
        }
    }
}
<commit_msg>update rust<commit_after>#![crate_name = "posix"]
#![crate_type = "lib"]
#![allow(non_camel_case_types)]
#![allow(raw_pointer_derive)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]

pub use os::arch::{char_t, schar_t, uchar_t, short_t, ushort_t, int_t, uint_t, long_t};
pub use os::arch::{ulong_t, longlong_t, ulonglong_t, float_t, double_t, size_t, ssize_t};

#[macro_use]
mod macros {
    macro_rules! new {
        ($name:ident) => {
            impl $name {
                pub fn new() -> $name {
                    unsafe { ::std::mem::zeroed() }
                }
            }
        }
    }
}

pub mod aio;
pub mod arpa;
pub mod cpio;
pub mod ctype;
pub mod dirent;
pub mod dlfcn;
pub mod errno;
pub mod fcntl;
pub mod fenv;
pub mod float;
pub mod fmtmsg;
pub mod fnmatch;
pub mod ftw;
pub mod glob;
pub mod grp;
pub mod iconv;
pub mod inttypes;
pub mod langinfo;
pub mod libgen;
pub mod limits;
pub mod locale;
pub mod monetary;
pub mod mqueue;
pub mod ndbm;
pub mod net;
pub mod netdb;
pub mod netinet;
pub mod nl_types;
pub mod poll;
pub mod pthread;
pub mod pwd;
pub mod regex;
pub mod sched;
pub mod search;
pub mod semaphore;
pub mod setjmp;
pub mod spawn;
pub mod stddef;
pub mod stdint;
pub mod stdio;
pub mod stdlib;
pub mod string;
pub mod strings;
pub mod stropts;
pub mod signal;
pub mod sys;
pub mod syslog;
pub mod tar;
pub mod termios;
pub mod time;
pub mod ulimit;
pub mod unistd;
pub mod utime;
pub mod utmpx;
pub mod wchar;
pub mod wctype;
pub mod wordexp;

#[repr(u8)]
#[derive(Copy)]
pub enum void_t {
    __variant1,
    __variant2,
}

#[cfg(target_os = "linux")]
mod os {
    #[cfg(target_arch = "x86_64")]
    pub mod arch {
        pub type bool_t       = i8;
        pub type char_t       = i8;
        pub type schar_t      = i8;
        pub type uchar_t      = u8;
        pub type short_t      = i16;
        pub type ushort_t     = u16;
        pub type int_t        = i32;
        pub type uint_t       = u32;
        pub type long_t       = i64;
        pub type ulong_t      = u64;
        pub type longlong_t   = i64;
        pub type ulonglong_t  = u64;
        pub type float_t      = f32;
        pub type double_t     = f64;
        pub type size_t       = u64;
        pub type ssize_t      = i64;
    }

    #[cfg(target_arch = "x86")]
    pub mod arch {
        pub type bool_t       = i8;
        pub type char_t       = i8;
        pub type schar_t      = i8;
        pub type uchar_t      = u8;
        pub type short_t      = i16;
        pub type ushort_t     = u16;
        pub type int_t        = i32;
        pub type uint_t       = u32;
        pub type long_t       = i32;
        pub type ulong_t      = u32;
        pub type longlong_t   = i64;
        pub type ulonglong_t  = u64;
        pub type float_t      = f32;
        pub type double_t     = f64;
        pub type size_t       = u32;
        pub type ssize_t      = i32;
    }
}

pub trait NTStr {
    fn as_ptr(&self) -> *const char_t;
}

pub struct NTStrBorrowed<'a> {
    data: &'a [u8],
}

pub struct NTStrOwned {
    vec: Vec<u8>,
}

impl<'a> NTStr for NTStrBorrowed<'a> {
    fn as_ptr(&self) -> *const char_t {
        self.data.as_ptr() as *const _
    }
}

impl NTStr for NTStrOwned {
    fn as_ptr(&self) -> *const char_t {
        self.vec.as_ptr() as *const _
    }
}

pub trait ToNTStr {
    fn to_nt_str(&self) -> NTStrOwned;
}

impl<'a> ToNTStr for &'a [u8] {
    fn to_nt_str(&self) -> NTStrOwned {
        let mut vec = self.to_vec();
        vec.push(0);
        NTStrOwned { vec: vec }
    }
}

impl ToNTStr for Path {
    fn to_nt_str(&self) -> NTStrOwned {
        use std::path::{BytesContainer};
        self.container_as_bytes().to_nt_str()
    }
}

impl<'a> ToNTStr for &'a str {
    fn to_nt_str(&self) -> NTStrOwned {
        self.as_bytes().to_nt_str()
    }
}

pub trait AsNTStr<'a> {
    fn as_nt_str(&'a self) -> NTStrBorrowed<'a>;
}

impl<'a> AsNTStr<'a> for &'a [u8] {
    fn as_nt_str(&'a self) -> NTStrBorrowed<'a> {
        NTStrBorrowed { data: *self }
    }
}

pub trait AsSlice: Sized {
    fn as_slice(&self) -> &[u8] {
        unsafe {
            ::std::mem::transmute(::std::raw::Slice {
                data: self as *const _ as *const u8,
                len: ::std::mem::size_of_val(self),
            })
        }
    }
}

pub trait AsMutSlice: Sized {
    fn as_mut_slice(&mut self) -> &mut [u8] {
        unsafe {
            ::std::mem::transmute(::std::raw::Slice {
                data: self as *mut _ as *const u8,
                len: ::std::mem::size_of_val(self),
            })
        }
    }
}
<|endoftext|>


<commit_before>#![feature(unsafe_destructor)]
pub use  self::matrix::{Mat, MatI64, MatF64};

mod matrix;
<commit_msg>addition of discrete module.<commit_after>#![feature(unsafe_destructor)]
pub use  self::matrix::{Mat, MatI64, MatF64};
mod discrete;
mod matrix;
<|endoftext|>


<commit_before>//! This crate provides x86_64 specific functions and data structures,
//! and access to various system registers.

#![feature(const_fn)]
#![feature(asm)]
#![feature(abi_x86_interrupt)]
#![feature(try_from)]
#![no_std]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![cfg_attr(feature = "deny-warnings", deny(missing_docs))]
#![cfg_attr(not(feature = "deny-warnings"), warn(missing_docs))]

#[cfg(test)]
#[macro_use]
extern crate std;

#[macro_use]
extern crate bitflags;
extern crate bit_field;
extern crate os_bootinfo;
extern crate usize_conversions;

/// Provides the non-standard-width integer types `u2`–`u63`.
///
/// We use these integer types in various APIs, for example `u9` for page tables indices.
pub extern crate ux;

pub use addr::{align_down, align_up, PhysAddr, VirtAddr};

pub mod instructions;
pub mod registers;
pub mod structures;

mod addr;

/// Represents a protection ring level.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    /// Privilege-level 0 (most privilege): This level is used by critical system-software
    /// components that require direct access to, and control over, all processor and system
    /// resources. This can include BIOS, memory-management functions, and interrupt handlers.
    Ring0 = 0,

    /// Privilege-level 1 (moderate privilege): This level is used by less-critical system-
    /// software services that can access and control a limited scope of processor and system
    /// resources. Software running at these privilege levels might include some device drivers
    /// and library routines. The actual privileges of this level are defined by the
    /// operating system.
    Ring1 = 1,

    /// Privilege-level 2 (moderate privilege): Like level 1, this level is used by
    /// less-critical system-software services that can access and control a limited scope of
    /// processor and system resources. The actual privileges of this level are defined by the
    /// operating system.
    Ring2 = 2,

    /// Privilege-level 3 (least privilege): This level is used by application software.
    /// Software running at privilege-level 3 is normally prevented from directly accessing
    /// most processor and system resources. Instead, applications request access to the
    /// protected processor and system resources by calling more-privileged service routines
    /// to perform the accesses.
    Ring3 = 3,
}

impl PrivilegeLevel {
    /// Creates a `PrivilegeLevel` from a numeric value. The value must be in the range 0..4.
    ///
    /// This function panics if the passed value is >3.
    pub fn from_u16(value: u16) -> PrivilegeLevel {
        match value {
            0 => PrivilegeLevel::Ring0,
            1 => PrivilegeLevel::Ring1,
            2 => PrivilegeLevel::Ring2,
            3 => PrivilegeLevel::Ring3,
            i => panic!("{} is not a valid privilege level", i),
        }
    }
}
<commit_msg>Re-enable repr_transparent feature again because docs.rs uses an old nightly<commit_after>//! This crate provides x86_64 specific functions and data structures,
//! and access to various system registers.

#![feature(const_fn)]
#![feature(asm)]
#![feature(abi_x86_interrupt)]
#![feature(try_from)]
#![feature(repr_transparent)]
#![no_std]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![cfg_attr(feature = "deny-warnings", deny(missing_docs))]
#![cfg_attr(not(feature = "deny-warnings"), warn(missing_docs))]

#[cfg(test)]
#[macro_use]
extern crate std;

#[macro_use]
extern crate bitflags;
extern crate bit_field;
extern crate os_bootinfo;
extern crate usize_conversions;

/// Provides the non-standard-width integer types `u2`–`u63`.
///
/// We use these integer types in various APIs, for example `u9` for page tables indices.
pub extern crate ux;

pub use addr::{align_down, align_up, PhysAddr, VirtAddr};

pub mod instructions;
pub mod registers;
pub mod structures;

mod addr;

/// Represents a protection ring level.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum PrivilegeLevel {
    /// Privilege-level 0 (most privilege): This level is used by critical system-software
    /// components that require direct access to, and control over, all processor and system
    /// resources. This can include BIOS, memory-management functions, and interrupt handlers.
    Ring0 = 0,

    /// Privilege-level 1 (moderate privilege): This level is used by less-critical system-
    /// software services that can access and control a limited scope of processor and system
    /// resources. Software running at these privilege levels might include some device drivers
    /// and library routines. The actual privileges of this level are defined by the
    /// operating system.
    Ring1 = 1,

    /// Privilege-level 2 (moderate privilege): Like level 1, this level is used by
    /// less-critical system-software services that can access and control a limited scope of
    /// processor and system resources. The actual privileges of this level are defined by the
    /// operating system.
    Ring2 = 2,

    /// Privilege-level 3 (least privilege): This level is used by application software.
    /// Software running at privilege-level 3 is normally prevented from directly accessing
    /// most processor and system resources. Instead, applications request access to the
    /// protected processor and system resources by calling more-privileged service routines
    /// to perform the accesses.
    Ring3 = 3,
}

impl PrivilegeLevel {
    /// Creates a `PrivilegeLevel` from a numeric value. The value must be in the range 0..4.
    ///
    /// This function panics if the passed value is >3.
    pub fn from_u16(value: u16) -> PrivilegeLevel {
        match value {
            0 => PrivilegeLevel::Ring0,
            1 => PrivilegeLevel::Ring1,
            2 => PrivilegeLevel::Ring2,
            3 => PrivilegeLevel::Ring3,
            i => panic!("{} is not a valid privilege level", i),
        }
    }
}
<|endoftext|>


<commit_before>//! A data structure for tracking source positions in language implementations, inspired by the
//! [CodeMap type in rustc's libsyntax](https://github.com/rust-lang/rust/blob/master/src/libsyntax/codemap.rs).
//!
//! The `CodeMap` tracks all source files and maps positions within them to linear indexes as if all
//! source files were concatenated. This allows a source position to be represented by a small
//! 32-bit `Pos` indexing into the `CodeMap`, under the assumption that the total amount of parsed
//! source code will not exceed 4GiB. The `CodeMap` can look up the source file, line, and column
//! of a `Pos` or `Span`, as well as provide source code snippets for error reporting.
//!
//! # Example
//! ```
//! use codemap::CodeMap;
//! let mut codemap = CodeMap::new();
//! let file = codemap.add_file("test.rs".to_string(), "fn test(){\n    println!(\"Hello\");\n}\n".to_string());
//! let string_literal_span = file.span.subspan(24, 31);
//!
//! let location = codemap.look_up_span(string_literal_span);
//! assert_eq!(location.file.name(), "test.rs");
//! assert_eq!(location.begin.line, 1);
//! assert_eq!(location.begin.column, 13);
//! assert_eq!(location.end.line, 1);
//! assert_eq!(location.end.column, 20);
//! ```

use std::cmp::{self, Ordering};
use std::ops::{Add, Sub, Deref};
use std::fmt;
use std::sync::Arc;
use std::hash::{Hash, Hasher};

/// A small, `Copy`, value representing a position in a `CodeMap`'s file.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct Pos(u32);

impl Add<u64> for Pos {
    type Output = Pos;
    fn add(self, other: u64) -> Pos {
        Pos(self.0 + other as u32)
    }
}

impl Sub<Pos> for Pos {
    type Output = u64;
    fn sub(self, other: Pos) -> u64 {
        (self.0 - other.0) as u64
    }
}

/// A range of text within a CodeMap.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct Span {
    /// The position in the codemap representing the first byte of the span.
    low: Pos,

    /// The position after the last byte of the span.
    high: Pos,
}

impl Span {
    /// Makes a span from offsets relative to the start of this span.
    ///
    /// # Panics
    ///   * If `end < begin`
    ///   * If `end` is beyond the length of the span
    pub fn subspan(&self, begin: u64, end: u64) -> Span {
        assert!(end >= begin);
        assert!(self.low + end <= self.high);
        Span {
            low: self.low + begin,
            high: self.low + end,
        }
    }

    /// Checks if a span is contained within this span.
    pub fn contains(&self, other: Span) -> bool {
        self.low <= other.low && self.high >= other.high
    }

    /// The position in the codemap representing the first byte of the span.
    pub fn low(&self) -> Pos {
        self.low
    }

    /// The position after the last byte of the span.
    pub fn high(&self) -> Pos {
        self.high
    }

    /// The length in bytes of the text of the span
    pub fn len(&self) -> u64 {
        self.high - self.low
    }

    /// Create a span that encloses both `self` and `other`.
    pub fn merge(&self, other: Span) -> Span {
        Span {
            low: cmp::min(self.low, other.low),
            high: cmp::max(self.high, other.high),
        }
    }
}

/// Associate a Span with a value of arbitrary type (e.g. an AST node).
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
pub struct Spanned<T> {
    pub node: T,
    pub span: Span,
}

impl<T> Deref for Spanned<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.node
    }
}

/// A data structure recording source code files for position lookup.
pub struct CodeMap {
    files: Vec<Arc<File>>,
    _allow_priv: ()
}

impl CodeMap {
    /// Creates an empty `CodeMap`.
    pub fn new() -> CodeMap {
        CodeMap {
            files: vec![],
            _allow_priv: ()
        }
    }

    /// Adds a file with the given name and contents.
    ///
    /// Use the returned `File` and its `.span` property to create `Spans`
    /// representing substrings of the file.
    pub fn add_file(&mut self, name: String, source: String) -> Arc<File> {
        let low = self.end_pos() + 1;
        let high = low + source.len() as u64;
        let mut lines = vec![low];
        lines.extend(source.match_indices('\n').map(|(p, _)| { low + (p + 1) as u64 }));

        let file = Arc::new(File {
            span: Span { low: low, high: high },
            name: name,
            source: source,
            lines: lines,
        });

        self.files.push(file.clone());
        file
    }

    fn end_pos(&self) -> Pos {
        self.files.last().map(|x| x.span.high).unwrap_or(Pos(0))
    }

    /// Looks up the `File` that contains the specified position.
    pub fn find_file(&self, pos: Pos) -> &Arc<File> {
        self.files.binary_search_by(|file| {
            if file.span.high < pos {
                Ordering::Less
            } else if file.span.low > pos {
                Ordering::Greater
            } else {
                Ordering::Equal
            }
        }).ok().map(|i| &self.files[i]).expect("Mapping unknown source location")
    }

    /// Gets the file, line, and column represented by a `Pos`.
    pub fn look_up_pos(&self, pos: Pos) -> Loc {
        let file = self.find_file(pos);
        let position = file.find_line_col(pos);
        Loc { file: file.clone(), position }
    }

    /// Gets the file and its line and column ranges represented by a `Span`.
    pub fn look_up_span(&self, span: Span) -> SpanLoc {
        let file = self.find_file(span.low);
        let begin = file.find_line_col(span.low);
        let end = file.find_line_col(span.high);
        SpanLoc { file: file.clone(), begin, end }
    }
}

/// A `CodeMap`'s record of a source file.
pub struct File {
    /// The span representing the entire file.
    pub span: Span,

    /// The filename as it would be displayed in an error message.
    name: String,

    /// Contents of the file.
    source: String,

    /// Byte positions of line beginnings.
    lines: Vec<Pos>,
}

impl File {
    /// Gets the name of the file
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Gets the line number of a Pos.
    ///
    /// The lines are 0-indexed (first line is numbered 0)
    ///
    /// # Panics
    ///
    ///  * If `pos` is not within this file's span
    pub fn find_line(&self, pos: Pos) -> usize {
        assert!(pos >= self.span.low);
        assert!(pos <= self.span.high);
        (match self.lines.binary_search(&pos) {
            Ok(i) => i,
            Err(i) => i - 1,
        })
    }

    /// Gets the line and column of a Pos.
    ///
    /// # Panics
    ///
    /// * If `pos` is not with this file's span
    /// * If `pos` points to a byte in the middle of a UTF-8 character
    pub fn find_line_col(&self, pos: Pos) -> LineCol {
        let line = self.find_line(pos);
        let line_span = self.line_span(line);
        let byte_col = pos - line_span.low;
        let col = self.source_slice(line_span)[..byte_col as usize].chars().count();

        LineCol{ line: line, column: col }
    }

    /// Gets the full source text of the file
    pub fn source(&self) -> &str {
        &self.source
    }

    /// Gets the source text of a Span.
    ///
    /// # Panics
    ///
    ///   * If `span` is not entirely within this file.
    pub fn source_slice(&self, span: Span) -> &str {
        assert!(self.span.contains(span));
        &self.source[((span.low - self.span.low) as usize)..((span.high - self.span.low) as usize)]
    }

    /// Gets the span representing a line by line number.
    ///
    /// The line number is 0-indexed (first line is numbered 0). The returned span includes the
    /// line terminator.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn line_span(&self, line: usize) -> Span {
        assert!(line < self.lines.len());
        Span {
            low: self.lines[line],
            high: *self.lines.get(line + 1).unwrap_or(&self.span.high)
        }
    }

    /// Gets the source text of a line.
    ///
    /// The string returned does not include the terminating \r or \n characters.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn source_line(&self, line: usize) -> &str {
        self.source_slice(self.line_span(line)).trim_right_matches(&['\n', '\r'][..])
    }

    /// Gets the number of lines in the file
    pub fn num_lines(&self) -> usize {
        self.lines.len()
    }
}

impl fmt::Debug for File {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "File({:?})", self.name)
    }
}

impl PartialEq for File {
    /// Compares by identity
    fn eq(&self, other: &File) -> bool {
        self as *const _ == other as *const _
    }
}

impl Eq for File {}

impl Hash for File {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.span.hash(hasher);
    }
}

/// A line and column.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct LineCol {
    /// The line number within the file (0-indexed).
    pub line: usize,

    /// The column within the line (0-indexed).
    pub column: usize,
}

/// A file, and a line and column within it.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Loc {
    pub file: Arc<File>,
    pub position: LineCol,
}

impl fmt::Display for Loc {
    /// Formats the location as `filename:line:column`, with a 1-indexed
    /// line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}:{}:{}", self.file.name, self.position.line+1, self.position.column+1)
    }
}

/// A file, and a line and column range within it.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct SpanLoc {
    pub file: Arc<File>,
    pub begin: LineCol,
    pub end: LineCol,
}

impl fmt::Display for SpanLoc {
    /// Formats the span as `filename:start_line:start_column: end_line:end_column`,
    /// or if the span is zero-length, `filename:line:column`, with a 1-indexed line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.begin == self.end {
            write!(f, "{}:{}:{}", self.file.name, self.begin.line+1, self.begin.column+1)
        } else {
            write!(f, "{}:{}:{}: {}:{}", self.file.name, self.begin.line+1, self.begin.column+1, self.end.line+1, self.end.column+1)
        }
    }
}

#[test]
fn test_codemap() {
    let mut codemap = CodeMap::new();
    let f1 = codemap.add_file("test1.rs".to_string(), "abcd\nefghij\nqwerty".to_string());
    let f2 = codemap.add_file("test2.rs".to_string(), "foo\nbar".to_string());

    assert_eq!(codemap.find_file(f1.span.low()).name(), "test1.rs");
    assert_eq!(codemap.find_file(f1.span.high()).name(), "test1.rs");
    assert_eq!(codemap.find_file(f2.span.low()).name(), "test2.rs");
    assert_eq!(codemap.find_file(f2.span.high()).name(), "test2.rs");

    let x = f1.span.subspan(5, 10);
    let f = codemap.find_file(x.low);
    assert_eq!(f.name, "test1.rs");
    assert_eq!(f.find_line_col(f.span.low()), LineCol { line: 0, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 4), LineCol { line: 0, column: 4 });
    assert_eq!(f.find_line_col(f.span.low() + 5), LineCol { line: 1, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 16), LineCol { line: 2, column: 4 });

    let x = f2.span.subspan(4, 7);
    assert_eq!(codemap.find_file(x.low()).name(), "test2.rs");
    assert_eq!(codemap.find_file(x.high()).name(), "test2.rs");
}

#[test]
fn test_issue2() {
    let mut codemap = CodeMap::new();
    let content = "a \nxyz\r\n";
    let file = codemap.add_file("<test>".to_owned(), content.to_owned());

    let span = file.span.subspan(2, 3);
    assert_eq!(codemap.look_up_pos(span.low()), Loc { file: file.clone(), position: LineCol { line: 0, column: 2 }});
    assert_eq!(codemap.look_up_pos(span.high()), Loc { file: file.clone(), position: LineCol { line: 1, column: 0 }});

    assert_eq!(file.source_line(0), "a ");
    assert_eq!(file.source_line(1), "xyz");
    assert_eq!(file.source_line(2), "");
}
<commit_msg>Add tests for multibyte characters<commit_after>//! A data structure for tracking source positions in language implementations, inspired by the
//! [CodeMap type in rustc's libsyntax](https://github.com/rust-lang/rust/blob/master/src/libsyntax/codemap.rs).
//!
//! The `CodeMap` tracks all source files and maps positions within them to linear indexes as if all
//! source files were concatenated. This allows a source position to be represented by a small
//! 32-bit `Pos` indexing into the `CodeMap`, under the assumption that the total amount of parsed
//! source code will not exceed 4GiB. The `CodeMap` can look up the source file, line, and column
//! of a `Pos` or `Span`, as well as provide source code snippets for error reporting.
//!
//! # Example
//! ```
//! use codemap::CodeMap;
//! let mut codemap = CodeMap::new();
//! let file = codemap.add_file("test.rs".to_string(), "fn test(){\n    println!(\"Hello\");\n}\n".to_string());
//! let string_literal_span = file.span.subspan(24, 31);
//!
//! let location = codemap.look_up_span(string_literal_span);
//! assert_eq!(location.file.name(), "test.rs");
//! assert_eq!(location.begin.line, 1);
//! assert_eq!(location.begin.column, 13);
//! assert_eq!(location.end.line, 1);
//! assert_eq!(location.end.column, 20);
//! ```

use std::cmp::{self, Ordering};
use std::ops::{Add, Sub, Deref};
use std::fmt;
use std::sync::Arc;
use std::hash::{Hash, Hasher};

/// A small, `Copy`, value representing a position in a `CodeMap`'s file.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct Pos(u32);

impl Add<u64> for Pos {
    type Output = Pos;
    fn add(self, other: u64) -> Pos {
        Pos(self.0 + other as u32)
    }
}

impl Sub<Pos> for Pos {
    type Output = u64;
    fn sub(self, other: Pos) -> u64 {
        (self.0 - other.0) as u64
    }
}

/// A range of text within a CodeMap.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct Span {
    /// The position in the codemap representing the first byte of the span.
    low: Pos,

    /// The position after the last byte of the span.
    high: Pos,
}

impl Span {
    /// Makes a span from offsets relative to the start of this span.
    ///
    /// # Panics
    ///   * If `end < begin`
    ///   * If `end` is beyond the length of the span
    pub fn subspan(&self, begin: u64, end: u64) -> Span {
        assert!(end >= begin);
        assert!(self.low + end <= self.high);
        Span {
            low: self.low + begin,
            high: self.low + end,
        }
    }

    /// Checks if a span is contained within this span.
    pub fn contains(&self, other: Span) -> bool {
        self.low <= other.low && self.high >= other.high
    }

    /// The position in the codemap representing the first byte of the span.
    pub fn low(&self) -> Pos {
        self.low
    }

    /// The position after the last byte of the span.
    pub fn high(&self) -> Pos {
        self.high
    }

    /// The length in bytes of the text of the span
    pub fn len(&self) -> u64 {
        self.high - self.low
    }

    /// Create a span that encloses both `self` and `other`.
    pub fn merge(&self, other: Span) -> Span {
        Span {
            low: cmp::min(self.low, other.low),
            high: cmp::max(self.high, other.high),
        }
    }
}

/// Associate a Span with a value of arbitrary type (e.g. an AST node).
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
pub struct Spanned<T> {
    pub node: T,
    pub span: Span,
}

impl<T> Deref for Spanned<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.node
    }
}

/// A data structure recording source code files for position lookup.
pub struct CodeMap {
    files: Vec<Arc<File>>,
    _allow_priv: ()
}

impl CodeMap {
    /// Creates an empty `CodeMap`.
    pub fn new() -> CodeMap {
        CodeMap {
            files: vec![],
            _allow_priv: ()
        }
    }

    /// Adds a file with the given name and contents.
    ///
    /// Use the returned `File` and its `.span` property to create `Spans`
    /// representing substrings of the file.
    pub fn add_file(&mut self, name: String, source: String) -> Arc<File> {
        let low = self.end_pos() + 1;
        let high = low + source.len() as u64;
        let mut lines = vec![low];
        lines.extend(source.match_indices('\n').map(|(p, _)| { low + (p + 1) as u64 }));

        let file = Arc::new(File {
            span: Span { low: low, high: high },
            name: name,
            source: source,
            lines: lines,
        });

        self.files.push(file.clone());
        file
    }

    fn end_pos(&self) -> Pos {
        self.files.last().map(|x| x.span.high).unwrap_or(Pos(0))
    }

    /// Looks up the `File` that contains the specified position.
    pub fn find_file(&self, pos: Pos) -> &Arc<File> {
        self.files.binary_search_by(|file| {
            if file.span.high < pos {
                Ordering::Less
            } else if file.span.low > pos {
                Ordering::Greater
            } else {
                Ordering::Equal
            }
        }).ok().map(|i| &self.files[i]).expect("Mapping unknown source location")
    }

    /// Gets the file, line, and column represented by a `Pos`.
    pub fn look_up_pos(&self, pos: Pos) -> Loc {
        let file = self.find_file(pos);
        let position = file.find_line_col(pos);
        Loc { file: file.clone(), position }
    }

    /// Gets the file and its line and column ranges represented by a `Span`.
    pub fn look_up_span(&self, span: Span) -> SpanLoc {
        let file = self.find_file(span.low);
        let begin = file.find_line_col(span.low);
        let end = file.find_line_col(span.high);
        SpanLoc { file: file.clone(), begin, end }
    }
}

/// A `CodeMap`'s record of a source file.
pub struct File {
    /// The span representing the entire file.
    pub span: Span,

    /// The filename as it would be displayed in an error message.
    name: String,

    /// Contents of the file.
    source: String,

    /// Byte positions of line beginnings.
    lines: Vec<Pos>,
}

impl File {
    /// Gets the name of the file
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Gets the line number of a Pos.
    ///
    /// The lines are 0-indexed (first line is numbered 0)
    ///
    /// # Panics
    ///
    ///  * If `pos` is not within this file's span
    pub fn find_line(&self, pos: Pos) -> usize {
        assert!(pos >= self.span.low);
        assert!(pos <= self.span.high);
        (match self.lines.binary_search(&pos) {
            Ok(i) => i,
            Err(i) => i - 1,
        })
    }

    /// Gets the line and column of a Pos.
    ///
    /// # Panics
    ///
    /// * If `pos` is not with this file's span
    /// * If `pos` points to a byte in the middle of a UTF-8 character
    pub fn find_line_col(&self, pos: Pos) -> LineCol {
        let line = self.find_line(pos);
        let line_span = self.line_span(line);
        let byte_col = pos - line_span.low;
        let col = self.source_slice(line_span)[..byte_col as usize].chars().count();

        LineCol{ line: line, column: col }
    }

    /// Gets the full source text of the file
    pub fn source(&self) -> &str {
        &self.source
    }

    /// Gets the source text of a Span.
    ///
    /// # Panics
    ///
    ///   * If `span` is not entirely within this file.
    pub fn source_slice(&self, span: Span) -> &str {
        assert!(self.span.contains(span));
        &self.source[((span.low - self.span.low) as usize)..((span.high - self.span.low) as usize)]
    }

    /// Gets the span representing a line by line number.
    ///
    /// The line number is 0-indexed (first line is numbered 0). The returned span includes the
    /// line terminator.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn line_span(&self, line: usize) -> Span {
        assert!(line < self.lines.len());
        Span {
            low: self.lines[line],
            high: *self.lines.get(line + 1).unwrap_or(&self.span.high)
        }
    }

    /// Gets the source text of a line.
    ///
    /// The string returned does not include the terminating \r or \n characters.
    ///
    /// # Panics
    ///
    ///  * If the line number is out of range
    pub fn source_line(&self, line: usize) -> &str {
        self.source_slice(self.line_span(line)).trim_right_matches(&['\n', '\r'][..])
    }

    /// Gets the number of lines in the file
    pub fn num_lines(&self) -> usize {
        self.lines.len()
    }
}

impl fmt::Debug for File {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "File({:?})", self.name)
    }
}

impl PartialEq for File {
    /// Compares by identity
    fn eq(&self, other: &File) -> bool {
        self as *const _ == other as *const _
    }
}

impl Eq for File {}

impl Hash for File {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.span.hash(hasher);
    }
}

/// A line and column.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct LineCol {
    /// The line number within the file (0-indexed).
    pub line: usize,

    /// The column within the line (0-indexed).
    pub column: usize,
}

/// A file, and a line and column within it.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Loc {
    pub file: Arc<File>,
    pub position: LineCol,
}

impl fmt::Display for Loc {
    /// Formats the location as `filename:line:column`, with a 1-indexed
    /// line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}:{}:{}", self.file.name, self.position.line+1, self.position.column+1)
    }
}

/// A file, and a line and column range within it.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct SpanLoc {
    pub file: Arc<File>,
    pub begin: LineCol,
    pub end: LineCol,
}

impl fmt::Display for SpanLoc {
    /// Formats the span as `filename:start_line:start_column: end_line:end_column`,
    /// or if the span is zero-length, `filename:line:column`, with a 1-indexed line and column.
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.begin == self.end {
            write!(f, "{}:{}:{}", self.file.name, self.begin.line+1, self.begin.column+1)
        } else {
            write!(f, "{}:{}:{}: {}:{}", self.file.name, self.begin.line+1, self.begin.column+1, self.end.line+1, self.end.column+1)
        }
    }
}

#[test]
fn test_codemap() {
    let mut codemap = CodeMap::new();
    let f1 = codemap.add_file("test1.rs".to_string(), "abcd\nefghij\nqwerty".to_string());
    let f2 = codemap.add_file("test2.rs".to_string(), "foo\nbar".to_string());

    assert_eq!(codemap.find_file(f1.span.low()).name(), "test1.rs");
    assert_eq!(codemap.find_file(f1.span.high()).name(), "test1.rs");
    assert_eq!(codemap.find_file(f2.span.low()).name(), "test2.rs");
    assert_eq!(codemap.find_file(f2.span.high()).name(), "test2.rs");

    let x = f1.span.subspan(5, 10);
    let f = codemap.find_file(x.low);
    assert_eq!(f.name, "test1.rs");
    assert_eq!(f.find_line_col(f.span.low()), LineCol { line: 0, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 4), LineCol { line: 0, column: 4 });
    assert_eq!(f.find_line_col(f.span.low() + 5), LineCol { line: 1, column: 0 });
    assert_eq!(f.find_line_col(f.span.low() + 16), LineCol { line: 2, column: 4 });

    let x = f2.span.subspan(4, 7);
    assert_eq!(codemap.find_file(x.low()).name(), "test2.rs");
    assert_eq!(codemap.find_file(x.high()).name(), "test2.rs");
}

#[test]
fn test_issue2() {
    let mut codemap = CodeMap::new();
    let content = "a \nxyz\r\n";
    let file = codemap.add_file("<test>".to_owned(), content.to_owned());

    let span = file.span.subspan(2, 3);
    assert_eq!(codemap.look_up_span(span), SpanLoc {
        file: file.clone(),
        begin: LineCol { line: 0, column: 2 },
        end: LineCol { line: 1, column: 0 }
    });

    assert_eq!(file.source_line(0), "a ");
    assert_eq!(file.source_line(1), "xyz");
    assert_eq!(file.source_line(2), "");
}

#[test]
fn test_multibyte() {
    let mut codemap = CodeMap::new();
    let content = "65°00′N 18°00′W 汉语\n🔬";
    let file = codemap.add_file("<test>".to_owned(), content.to_owned());

    assert_eq!(codemap.look_up_pos(file.span.low() + 21), Loc { file: file.clone(), position: LineCol { line: 0, column: 15 } });
    assert_eq!(codemap.look_up_pos(file.span.low() + 28), Loc { file: file.clone(), position: LineCol { line: 0, column: 18 } });
    assert_eq!(codemap.look_up_pos(file.span.low() + 33), Loc { file: file.clone(), position: LineCol { line: 1, column: 1 } });
}
<|endoftext|>


<commit_before>extern crate base64;
extern crate crypto;
extern crate hyper;
extern crate hyper_native_tls;
extern crate rand;
extern crate serde_json;
extern crate time;
extern crate url;

use std::io::Read;
use std::collections::{HashMap, BTreeMap};

use crypto::sha1::Sha1;
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use hyper::header::{Headers, Authorization, ContentType};
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use rand::Rng;
use url::Url;
use url::percent_encoding::{EncodeSet, percent_encode};

#[derive(Copy, Clone)]
struct StrictEncodeSet;

impl EncodeSet for StrictEncodeSet {
    fn contains(&self, byte: u8) -> bool {
        !((byte >= "0".as_bytes()[0] && byte <= "9".as_bytes()[0]) ||
            (byte >= "a".as_bytes()[0] && byte <= "z".as_bytes()[0]) ||
            (byte >= "A".as_bytes()[0] && byte <= "Z".as_bytes()[0]) ||
            (byte == "-".as_bytes()[0]) ||
            (byte == ".".as_bytes()[0]) ||
            (byte == "_".as_bytes()[0]) ||
            (byte == "~".as_bytes()[0])
        )
    }
}

#[derive(Clone, Debug)]
pub struct Client {
    pub consumer_key: Option<String>,
    pub consumer_secret: Option<String>,
    pub access_token: Option<String>,
    pub access_token_secret: Option<String>
}

impl Client {
    pub fn new(ck: Option<String>, cs: Option<String>, at: Option<String>, ats: Option<String>) -> Client {
        Client {
            consumer_key: ck,
            consumer_secret: cs,
            access_token: at,
            access_token_secret: ats
        }
    }

    pub fn get_request_url(&mut self) -> String {
        let (request_token, request_token_secret) = get_request_token(&self).unwrap();
        let mut request_url = Url::parse("http://api.twitter.com/oauth/authorize").unwrap();
        request_url.query_pairs_mut().append_pair("oauth_token", &request_token);
        request_url.query_pairs_mut().append_pair("oauth_token_secret", &request_token_secret);

        self.access_token = Some(request_token);
        self.access_token_secret = Some(request_token_secret);
        request_url.to_string()
    }

    pub fn set_access_token(&mut self, verifier: &str) {
        let url = "https://api.twitter.com/oauth/access_token";

        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut params: BTreeMap<&str, &str> = BTreeMap::new();
        params.insert("oauth_token", &token);
        params.insert("oauth_verifier", verifier);
        let (header, _) = build_request(&self, "POST", url, params, &token_secret);

        let (oauth_token, oauth_token_secret) = get_oauth_token(get_token(url, &header)).unwrap();
        self.access_token = Some(oauth_token);
        self.access_token_secret = Some(oauth_token_secret);
    }

    pub fn post(&self, endpoint: &str, param: BTreeMap<&str, &str>) -> serde_json::Value {
        let url = format!("https://api.twitter.com/1.1/{}", endpoint);
        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut param = param;
        param.insert("oauth_token", &token);

        let (header, body) = build_request(&self, "POST", &url, param, &token_secret);

        let mut headers = Headers::new();
        headers.set(Authorization(header));
        headers.set(ContentType(Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, vec![(Attr::Charset, Value::Utf8)])));
        let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
        let mut res = client.post(&url)
            .headers(headers)
            .body(&body)
            .send()
            .unwrap();
        let mut response_body = String::new();
        res.read_to_string(&mut response_body).unwrap();

        match serde_json::from_str::<serde_json::Value>(&response_body) {
            Ok(json) => json,
            Err(..) => panic!("Err"),
        }
    }

    pub fn get(&self, endpoint: &str, param: BTreeMap<&str, &str>) -> serde_json::Value {
        let url = format!("https://api.twitter.com/1.1/{}", endpoint);
        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut param = param;
        param.insert("oauth_token", &token);

        let (header, _) = build_request(&self, "GET", &url, param, &token_secret);

        let mut headers = Headers::new();
        headers.set(Authorization(header));
        let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
        let mut res = client.get(&url)
            .headers(headers)
            .send()
            .unwrap();
        let mut response_body = String::new();
        res.read_to_string(&mut response_body).unwrap();

        match serde_json::from_str::<serde_json::Value>(&response_body) {
            Ok(json) => json,
            Err(..) => panic!("Err"),
        }
    }
}

fn encode(s: &str) -> String {
    percent_encode(s.as_bytes(), StrictEncodeSet).collect::<String>()
}

fn build_request(
    oauth: &Client,
    method: &str,
    url: &str,
    append_params: BTreeMap<&str, &str>,
    oauth_token_secret: &str
) -> (String, String) {
    let nonce = rand::thread_rng().gen_ascii_chars().take(32).collect::<String>();
    let now_time = time::now().to_timespec().sec.to_string();
    let key = oauth.consumer_key.clone().unwrap();
    let key_secret = oauth.consumer_secret.clone().unwrap();

    let mut params: BTreeMap<&str, &str> = BTreeMap::new();
    params.insert("oauth_consumer_key", &key);
    params.insert("oauth_nonce", &nonce);
    params.insert("oauth_signature_method", "HMAC-SHA1");
    params.insert("oauth_timestamp", &now_time);
    params.insert("oauth_version", "1.0a");

    for (k, v) in append_params {
        params.insert(k, v);
    }

    let param = params
        .iter()
        .map(|(k, v)| format!("{}={}", k, encode(v)))
        .collect::<Vec<_>>()
        .join("&");

    let oauth_signature = {
        let signature_param = format!("{}&{}&{}", encode(method.to_uppercase().as_str()), encode(url), encode(&param));
        let key = format!("{}&{}", encode(&key_secret), encode(oauth_token_secret));
        let mut hmac = Hmac::new(Sha1::new(), key.as_bytes());
        hmac.input(signature_param.as_bytes());
        base64::encode(hmac.result().code())
    };

    let mut values = params;
    values.insert("oauth_signature", &oauth_signature);

    (build_header(&values), build_body(&values))
}

fn build_header(params: &BTreeMap<&str, &str>) -> String {
    let header = params
        .iter()
        .filter(|&(k, _)| k.starts_with("oauth_"))
        .map(|(k, v)| format!("{}=\"{}\"", k, encode(v)))
        .collect::<Vec<_>>()
        .join(", ");
    format!("OAuth {}", header)
}

fn build_body(params: &BTreeMap<&str, &str>) -> String {
    params
        .iter()
        .filter(|&(k, _)| !k.starts_with("oauth_"))
        .map(|(k, v)| format!("{}={}", k, encode(v)))
        .collect::<Vec<_>>()
        .join("&")
}

fn get_token(url: &str, header_value: &str) -> String {
    let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
    let mut headers = Headers::new();
    headers.set(Authorization(header_value.to_string()));
    let mut res = client
        .post(url)
        .headers(headers)
        .send()
        .unwrap();

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();

    body
}

fn get_request_token(oauth: &Client) -> Result<(String, String), String> {
    let url = "https://api.twitter.com/oauth/request_token";

    let mut params = BTreeMap::new();
    params.insert("oauth_callback", "oob");
    let (header, _) = build_request(&oauth, "POST", url, params, "");

    get_oauth_token(get_token(url, &header))
}

fn get_oauth_token(body: String) -> Result<(String, String), String> {
    let query = match serde_json::from_str::<serde_json::Value>(&body) {
        Ok(json) => return Err(json["errors"][0]["message"].to_string()),
        Err(..) => body,
    };

    let mut parsed_url = Url::parse("http://example.com").unwrap();
    parsed_url.set_query(Some(&query));
    let hash_query: HashMap<_, _> = parsed_url.query_pairs().into_owned().collect();

    Ok((hash_query["oauth_token"].to_string(), hash_query["oauth_token_secret"].to_string()))
}
<commit_msg>エンドポイントに.jsonをつけない<commit_after>extern crate base64;
extern crate crypto;
extern crate hyper;
extern crate hyper_native_tls;
extern crate rand;
extern crate serde_json;
extern crate time;
extern crate url;

use std::io::Read;
use std::collections::{HashMap, BTreeMap};

use crypto::sha1::Sha1;
use crypto::hmac::Hmac;
use crypto::mac::Mac;
use hyper::header::{Headers, Authorization, ContentType};
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use rand::Rng;
use url::Url;
use url::percent_encoding::{EncodeSet, percent_encode};

#[derive(Copy, Clone)]
struct StrictEncodeSet;

impl EncodeSet for StrictEncodeSet {
    fn contains(&self, byte: u8) -> bool {
        !((byte >= "0".as_bytes()[0] && byte <= "9".as_bytes()[0]) ||
            (byte >= "a".as_bytes()[0] && byte <= "z".as_bytes()[0]) ||
            (byte >= "A".as_bytes()[0] && byte <= "Z".as_bytes()[0]) ||
            (byte == "-".as_bytes()[0]) ||
            (byte == ".".as_bytes()[0]) ||
            (byte == "_".as_bytes()[0]) ||
            (byte == "~".as_bytes()[0])
        )
    }
}

#[derive(Clone, Debug)]
pub struct Client {
    pub consumer_key: Option<String>,
    pub consumer_secret: Option<String>,
    pub access_token: Option<String>,
    pub access_token_secret: Option<String>
}

impl Client {
    pub fn new(ck: Option<String>, cs: Option<String>, at: Option<String>, ats: Option<String>) -> Client {
        Client {
            consumer_key: ck,
            consumer_secret: cs,
            access_token: at,
            access_token_secret: ats
        }
    }

    pub fn get_request_url(&mut self) -> String {
        let (request_token, request_token_secret) = get_request_token(&self).unwrap();
        let mut request_url = Url::parse("http://api.twitter.com/oauth/authorize").unwrap();
        request_url.query_pairs_mut().append_pair("oauth_token", &request_token);
        request_url.query_pairs_mut().append_pair("oauth_token_secret", &request_token_secret);

        self.access_token = Some(request_token);
        self.access_token_secret = Some(request_token_secret);
        request_url.to_string()
    }

    pub fn set_access_token(&mut self, verifier: &str) {
        let url = "https://api.twitter.com/oauth/access_token";

        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut params: BTreeMap<&str, &str> = BTreeMap::new();
        params.insert("oauth_token", &token);
        params.insert("oauth_verifier", verifier);
        let (header, _) = build_request(&self, "POST", url, params, &token_secret);

        let (oauth_token, oauth_token_secret) = get_oauth_token(get_token(url, &header)).unwrap();
        self.access_token = Some(oauth_token);
        self.access_token_secret = Some(oauth_token_secret);
    }

    pub fn post(&self, endpoint: &str, param: BTreeMap<&str, &str>) -> serde_json::Value {
        let url = format!("https://api.twitter.com/1.1/{}.json", endpoint);
        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut param = param;
        param.insert("oauth_token", &token);

        let (header, body) = build_request(&self, "POST", &url, param, &token_secret);

        let mut headers = Headers::new();
        headers.set(Authorization(header));
        headers.set(ContentType(Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, vec![(Attr::Charset, Value::Utf8)])));
        let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
        let mut res = client.post(&url)
            .headers(headers)
            .body(&body)
            .send()
            .unwrap();
        let mut response_body = String::new();
        res.read_to_string(&mut response_body).unwrap();

        match serde_json::from_str::<serde_json::Value>(&response_body) {
            Ok(json) => json,
            Err(..) => panic!("Err"),
        }
    }

    pub fn get(&self, endpoint: &str, param: BTreeMap<&str, &str>) -> serde_json::Value {
        let url = format!("https://api.twitter.com/1.1/{}", endpoint);
        let token = self.access_token.clone().unwrap();
        let token_secret = self.access_token_secret.clone().unwrap();

        let mut param = param;
        param.insert("oauth_token", &token);

        let (header, _) = build_request(&self, "GET", &url, param, &token_secret);

        let mut headers = Headers::new();
        headers.set(Authorization(header));
        let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
        let mut res = client.get(&url)
            .headers(headers)
            .send()
            .unwrap();
        let mut response_body = String::new();
        res.read_to_string(&mut response_body).unwrap();

        match serde_json::from_str::<serde_json::Value>(&response_body) {
            Ok(json) => json,
            Err(..) => panic!("Err"),
        }
    }
}

fn encode(s: &str) -> String {
    percent_encode(s.as_bytes(), StrictEncodeSet).collect::<String>()
}

fn build_request(
    oauth: &Client,
    method: &str,
    url: &str,
    append_params: BTreeMap<&str, &str>,
    oauth_token_secret: &str
) -> (String, String) {
    let nonce = rand::thread_rng().gen_ascii_chars().take(32).collect::<String>();
    let now_time = time::now().to_timespec().sec.to_string();
    let key = oauth.consumer_key.clone().unwrap();
    let key_secret = oauth.consumer_secret.clone().unwrap();

    let mut params: BTreeMap<&str, &str> = BTreeMap::new();
    params.insert("oauth_consumer_key", &key);
    params.insert("oauth_nonce", &nonce);
    params.insert("oauth_signature_method", "HMAC-SHA1");
    params.insert("oauth_timestamp", &now_time);
    params.insert("oauth_version", "1.0a");

    for (k, v) in append_params {
        params.insert(k, v);
    }

    let param = params
        .iter()
        .map(|(k, v)| format!("{}={}", k, encode(v)))
        .collect::<Vec<_>>()
        .join("&");

    let oauth_signature = {
        let signature_param = format!("{}&{}&{}", encode(method.to_uppercase().as_str()), encode(url), encode(&param));
        let key = format!("{}&{}", encode(&key_secret), encode(oauth_token_secret));
        let mut hmac = Hmac::new(Sha1::new(), key.as_bytes());
        hmac.input(signature_param.as_bytes());
        base64::encode(hmac.result().code())
    };

    let mut values = params;
    values.insert("oauth_signature", &oauth_signature);

    (build_header(&values), build_body(&values))
}

fn build_header(params: &BTreeMap<&str, &str>) -> String {
    let header = params
        .iter()
        .filter(|&(k, _)| k.starts_with("oauth_"))
        .map(|(k, v)| format!("{}=\"{}\"", k, encode(v)))
        .collect::<Vec<_>>()
        .join(", ");
    format!("OAuth {}", header)
}

fn build_body(params: &BTreeMap<&str, &str>) -> String {
    params
        .iter()
        .filter(|&(k, _)| !k.starts_with("oauth_"))
        .map(|(k, v)| format!("{}={}", k, encode(v)))
        .collect::<Vec<_>>()
        .join("&")
}

fn get_token(url: &str, header_value: &str) -> String {
    let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
    let mut headers = Headers::new();
    headers.set(Authorization(header_value.to_string()));
    let mut res = client
        .post(url)
        .headers(headers)
        .send()
        .unwrap();

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();

    body
}

fn get_request_token(oauth: &Client) -> Result<(String, String), String> {
    let url = "https://api.twitter.com/oauth/request_token";

    let mut params = BTreeMap::new();
    params.insert("oauth_callback", "oob");
    let (header, _) = build_request(&oauth, "POST", url, params, "");

    get_oauth_token(get_token(url, &header))
}

fn get_oauth_token(body: String) -> Result<(String, String), String> {
    let query = match serde_json::from_str::<serde_json::Value>(&body) {
        Ok(json) => return Err(json["errors"][0]["message"].to_string()),
        Err(..) => body,
    };

    let mut parsed_url = Url::parse("http://example.com").unwrap();
    parsed_url.set_query(Some(&query));
    let hash_query: HashMap<_, _> = parsed_url.query_pairs().into_owned().collect();

    Ok((hash_query["oauth_token"].to_string(), hash_query["oauth_token_secret"].to_string()))
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A bare-metal library supplying functions rustc may lower code to
//!
//! This library is not intended for general use, and is superseded by a system
//! libc if one is available. In a freestanding context, however, common
//! functions such as memset, memcpy, etc are not implemented. This library
//! provides an implementation of these functions which are either required by
//! libcore or called by rustc implicitly.
//!
//! This library is never included by default, and must be manually included if
//! necessary. It is an error to include this library when also linking with
//! the system libc library.

#![feature(phase)]
#![no_std]

// This library defines the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]

extern crate core;

#[phase(plugin, link)]
#[cfg(test)] extern crate std;
#[cfg(test)] extern crate native;

use core::ptr::RawPtr;

#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as int) = *src.offset(i as int);
        i += 1;
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             n: uint) -> *mut u8 {
    if src < dest as *const u8 { // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as int) = *src.offset(i as int);
        }
    } else { // copy from beginning
        let mut i = 0;
        while i < n {
            *dest.offset(i as int) = *src.offset(i as int);
            i += 1;
        }
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memset(s: *mut u8, c: i32, n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as int) = c as u8;
        i += 1;
    }
    return s;
}

#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: uint) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.offset(i as int);
        let b = *s2.offset(i as int);
        if a != b {
            return a as i32 - b as i32
        }
        i += 1;
    }
    return 0;
}

#[cfg(test)]
mod test {
    use core::str::StrSlice;
    use core::slice::{MutableSlice, ImmutableSlice};

    use super::{memcmp, memset, memcpy, memmove};

    #[test]
    fn memcmp_single_byte_pointers() {
        unsafe {
            assert_eq!(memcmp(&0xFAu8, &0xFAu8, 1), 0x00);
            assert!(memcmp(&0xEFu8, &0xFEu8, 1) < 0x00);
        }
    }

    #[test]
    fn memcmp_strings() {
        {
            let (x, z) = ("Hello!", "Good Bye.");
            let l = x.len();
            unsafe {
                assert_eq!(memcmp(x.as_ptr(), x.as_ptr(), l), 0);
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) > 0);
                assert!(memcmp(z.as_ptr(), x.as_ptr(), l) < 0);
            }
        }
        {
            let (x, z) = ("hey!", "hey.");
            let l = x.len();
            unsafe {
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) < 0);
            }
        }
    }

    #[test]
    fn memset_single_byte_pointers() {
        let mut x: u8 = 0xFF;
        unsafe {
            memset(&mut x, 0xAA, 1);
            assert_eq!(x, 0xAA);
            memset(&mut x, 0x00, 1);
            assert_eq!(x, 0x00);
            x = 0x01;
            memset(&mut x, 0x12, 0);
            assert_eq!(x, 0x01);
        }
    }

    #[test]
    fn memset_array() {
        let mut buffer = [b'X', .. 100];
        unsafe {
            memset(buffer.as_mut_ptr(), b'#' as i32, buffer.len());
        }
        for byte in buffer.iter() { assert_eq!(*byte, b'#'); }
    }

    #[test]
    fn memcpy_and_memcmp_arrays() {
        let (src, mut dst) = ([b'X', .. 100], [b'Y', .. 100]);
        unsafe {
            assert!(memcmp(src.as_ptr(), dst.as_ptr(), 100) != 0);
            let _ = memcpy(dst.as_mut_ptr(), src.as_ptr(), 100);
            assert_eq!(memcmp(src.as_ptr(), dst.as_ptr(), 100), 0);
        }
    }

    #[test]
    fn memmove_overlapping() {
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[4], &buffer[0], 6);
                let mut i = 0;
                for byte in b"0123012345".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[0], &buffer[4], 6);
                let mut i = 0;
                for byte in b"4567896789".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
    }
}
<commit_msg>RawPtr has been renamed to PtrExt<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A bare-metal library supplying functions rustc may lower code to
//!
//! This library is not intended for general use, and is superseded by a system
//! libc if one is available. In a freestanding context, however, common
//! functions such as memset, memcpy, etc are not implemented. This library
//! provides an implementation of these functions which are either required by
//! libcore or called by rustc implicitly.
//!
//! This library is never included by default, and must be manually included if
//! necessary. It is an error to include this library when also linking with
//! the system libc library.

#![feature(phase)]
#![no_std]

// This library defines the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]

extern crate core;

#[phase(plugin, link)]
#[cfg(test)] extern crate std;
#[cfg(test)] extern crate native;

use core::ptr::PtrExt;

#[no_mangle]
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
                            n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *dest.offset(i as int) = *src.offset(i as int);
        i += 1;
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
                             n: uint) -> *mut u8 {
    if src < dest as *const u8 { // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *dest.offset(i as int) = *src.offset(i as int);
        }
    } else { // copy from beginning
        let mut i = 0;
        while i < n {
            *dest.offset(i as int) = *src.offset(i as int);
            i += 1;
        }
    }
    return dest;
}

#[no_mangle]
pub unsafe extern fn memset(s: *mut u8, c: i32, n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as int) = c as u8;
        i += 1;
    }
    return s;
}

#[no_mangle]
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: uint) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *s1.offset(i as int);
        let b = *s2.offset(i as int);
        if a != b {
            return a as i32 - b as i32
        }
        i += 1;
    }
    return 0;
}

#[cfg(test)]
mod test {
    use core::str::StrSlice;
    use core::slice::{MutableSlice, ImmutableSlice};

    use super::{memcmp, memset, memcpy, memmove};

    #[test]
    fn memcmp_single_byte_pointers() {
        unsafe {
            assert_eq!(memcmp(&0xFAu8, &0xFAu8, 1), 0x00);
            assert!(memcmp(&0xEFu8, &0xFEu8, 1) < 0x00);
        }
    }

    #[test]
    fn memcmp_strings() {
        {
            let (x, z) = ("Hello!", "Good Bye.");
            let l = x.len();
            unsafe {
                assert_eq!(memcmp(x.as_ptr(), x.as_ptr(), l), 0);
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) > 0);
                assert!(memcmp(z.as_ptr(), x.as_ptr(), l) < 0);
            }
        }
        {
            let (x, z) = ("hey!", "hey.");
            let l = x.len();
            unsafe {
                assert!(memcmp(x.as_ptr(), z.as_ptr(), l) < 0);
            }
        }
    }

    #[test]
    fn memset_single_byte_pointers() {
        let mut x: u8 = 0xFF;
        unsafe {
            memset(&mut x, 0xAA, 1);
            assert_eq!(x, 0xAA);
            memset(&mut x, 0x00, 1);
            assert_eq!(x, 0x00);
            x = 0x01;
            memset(&mut x, 0x12, 0);
            assert_eq!(x, 0x01);
        }
    }

    #[test]
    fn memset_array() {
        let mut buffer = [b'X', .. 100];
        unsafe {
            memset(buffer.as_mut_ptr(), b'#' as i32, buffer.len());
        }
        for byte in buffer.iter() { assert_eq!(*byte, b'#'); }
    }

    #[test]
    fn memcpy_and_memcmp_arrays() {
        let (src, mut dst) = ([b'X', .. 100], [b'Y', .. 100]);
        unsafe {
            assert!(memcmp(src.as_ptr(), dst.as_ptr(), 100) != 0);
            let _ = memcpy(dst.as_mut_ptr(), src.as_ptr(), 100);
            assert_eq!(memcmp(src.as_ptr(), dst.as_ptr(), 100), 0);
        }
    }

    #[test]
    fn memmove_overlapping() {
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[4], &buffer[0], 6);
                let mut i = 0;
                for byte in b"0123012345".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
        {
            let mut buffer = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9' ];
            unsafe {
                memmove(&mut buffer[0], &buffer[4], 6);
                let mut i = 0;
                for byte in b"4567896789".iter() {
                    assert_eq!(buffer[i], *byte);
                    i += 1;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>match_any! implementation<commit_after>
macro_rules! match_any {
    ($a:ident => $($x:ident: $t:ty => $b:block),+) => {
        {
            $(
                if let Some($x) = $a.downcast_ref::<$t>() {
                    $b
                };
            )+
        }
    }
}
<|endoftext|>