<commit_before>#![deny(warnings)]

extern crate heatmap;
extern crate hsl;
extern crate png;
extern crate rusttype;

use heatmap::Heatmap;
use hsl::HSL;
use png::HasParameters;
use rusttype::{FontCollection, PixelsXY, PositionedGlyph, point};
use std::fs::File;
use std::io::BufWriter;
use std::path::Path;

#[allow(dead_code)]
pub struct Waterfall {
    config: Config,
}

pub struct Config {}

impl Default for Config {
    fn default() -> Config {
        Config {}
    }
}

impl Config {
    pub fn new() -> Config {
        Default::default()
    }

    pub fn build(self) -> Waterfall {
        Waterfall::configured(self)
    }
}

struct Label {
    value: u64,
    text: String,
}

impl Default for Waterfall {
    fn default() -> Waterfall {
        Waterfall::configured(Config::default())
    }
}

impl Waterfall {
    pub fn new() -> Waterfall {
        Default::default()
    }

    pub fn configure() -> Config {
        Config::default()
    }

    fn configured(config: Config) -> Waterfall {
        Waterfall { config: config }
    }

    pub fn render_png(&mut self, heatmap: &Heatmap, file: String) {
        let height = heatmap.num_slices() as usize;
        let width = heatmap.histogram_buckets() as usize;

        // build buffer from data
        let mut buffer = ImageBuffer::<ColorRgb>::new(width, height);
        let max = find_max(heatmap);
        let mut x;
        let mut y = 0;

        // loop to color the pixels
        for slice in heatmap {
            x = 0;
            for bucket in &slice.histogram() {
                let value = (bucket.count() as f64) / (bucket.width() as f64);
                let pixel = color_from_value(value, max);
                buffer.set_pixel(x, y, pixel);
                x += 1;
            }
            y += 1;
        }

        // latency annotations
        let labels: Vec<Label> = vec![
            Label {
                value: 200,
                text: "200nS".to_string(),
            },
            Label {
                value: 500,
                text: "500nS".to_string(),
            },
            Label {
                value: 1000,
                text: "1uS".to_string(),
            },
            Label {
                value: 2000,
                text: "2uS".to_string(),
            },
            Label {
                value: 5000,
                text: "5uS".to_string(),
            },
            Label {
                value: 10000,
                text: "10uS".to_string(),
            },
            Label {
                value: 20000,
                text: "20uS".to_string(),
            },
            Label {
                value: 50000,
                text: "50uS".to_string(),
            },
            Label {
                value: 100000,
                text: "100uS".to_string(),
            },
            Label {
                value: 200000,
                text: "200uS".to_string(),
            },
            Label {
                value: 500000,
                text: "500uS".to_string(),
            },
            Label {
                value: 1000000,
                text: "1mS".to_string(),
            },
            Label {
                value: 2000000,
                text: "2mS".to_string(),
            },
            Label {
                value: 5000000,
                text: "5mS".to_string(),
            },
            Label {
                value: 10000000,
                text: "10mS".to_string(),
            },
            Label {
                value: 20000000,
                text: "20mS".to_string(),
            },
            Label {
                value: 50000000,
                text: "50mS".to_string(),
            },
            Label {
                value: 100000000,
                text: "100mS".to_string(),
            },
            Label {
                value: 200000000,
                text: "200mS".to_string(),
            },
            Label {
                value: 500000000,
                text: "500mS".to_string(),
            },
        ];

        let mut l = 0;
        y = 0;

        for slice in heatmap {
            x = 0;
            for bucket in &slice.histogram() {
                if (y % 60) == 0 {
                    if x == 0 {
                        let hour = y / 3600;
                        let minute = y / 60;
                        let time = format!("{:02}:{:02}", hour, minute);
                        let overlay = string_buffer(&time, 25.0);
                        buffer.overlay(&overlay, x, y);
                        buffer.horizontal_line(y, ColorRgb { r: 0, g: 0, b: 0 });
                    }
                    let v = bucket.value();
                    if (l < labels.len()) && (v >= labels[l].value) {
                        let overlay = string_buffer(&labels[l].text, 25.0);
                        buffer.overlay(&overlay, x, y);
                        buffer.vertical_line(x, ColorRgb { r: 0, g: 0, b: 0 });
                        l += 1;
                    }
                }
                x += 1;
            }
            y += 1;
        }

        let _ = buffer.write_png(file.clone());
    }
}

fn find_max(heatmap: &Heatmap) -> f64 {
    let mut max = 0.0;

    for slice in heatmap {
        for bucket in &slice.histogram() {
            let value = (bucket.count() as f64) / (bucket.width() as f64);
            if value > max {
                max = value;
            }
        }
    }
    max
}

fn string_buffer(string: &str, size: f32) -> ImageBuffer<ColorRgb> {
    // load font
    let font_data = include_bytes!("../assets/ubuntumono/UbuntuMono-Regular.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap();

    // size and scaling
    let height: f32 = size;
    let pixel_height = height.ceil() as usize;
    let scale = PixelsXY(height * 1.0, height);

    let v_metrics = font.v_metrics(scale);
    let offset = point(0.0, v_metrics.ascent);

    let glyphs: Vec<PositionedGlyph> = font.layout(string, scale, offset).collect();

    let width = glyphs
        .iter()
        .map(|g| g.h_metrics().advance_width)
        .fold(0.0, |x, y| x + y)
        .ceil() as usize;

    let mut overlay = ImageBuffer::<ColorRgb>::new(width, pixel_height);

    for g in glyphs {
        if let Some(bb) = g.pixel_bounding_box() {
            g.draw(|x, y, v| {
                let x = (x as i32 + bb.min.x) as usize;
                let y = (y as i32 + bb.min.y) as usize;
                if v > 0.25 {
                    overlay.set_pixel(
                        x,
                        y,
                        ColorRgb {
                            r: 255,
                            g: 255,
                            b: 255,
                        },
                    );
                }
            })
        }
    }

    overlay
}

fn color_from_value(value: f64, max: f64) -> ColorRgb {
    let value = value / max;

    let knee = 0.10_f64;

    let hsl = if value < knee {
        let l = 0.25_f64 + 0.25_f64 * value / knee;
        HSL {
            h: 236_f64,
            s: 1_f64,
            l: l,
        }
    } else {
        let h_per_deg: f64 = 236_f64 / (1.0_f64 - knee);
        let deg = (value - knee) * h_per_deg;

        HSL {
            h: (236_f64 - deg),
            s: 1_f64,
            l: 0.50_f64,
        }
    };

    let (r, g, b) = hsl.to_rgb();

    ColorRgb { r: r, g: g, b: b }
}

#[derive(Clone, Copy, Debug, PartialEq)]
struct ColorRgb {
    r: u8,
    g: u8,
    b: u8,
}

struct ImageBuffer<T> {
    buffer: Vec<Vec<T>>,
    height: usize,
    width: usize,
}

impl ImageBuffer<ColorRgb> {
    pub fn new(width: usize, height: usize) -> ImageBuffer<ColorRgb> {
        let background = ColorRgb { r: 0, g: 0, b: 0 };
        let mut row = Vec::<ColorRgb>::with_capacity(width);
        for _ in 0..width {
            row.push(background);
        }
        let mut buffer = Vec::<Vec<ColorRgb>>::with_capacity(height);
        for _ in 0..height {
            buffer.push(row.clone());
        }
        ImageBuffer {
            buffer: buffer,
            height: height,
            width: width,
        }
    }

    pub fn write_png(self, file: String) -> Result<(), &'static str> {
        let mut buffer = Vec::<u8>::with_capacity(self.height * self.width);
        for row in 0..self.height {
            for col in 0..self.width {
                let pixel = self.buffer[row][col];
                buffer.push(pixel.r);
                buffer.push(pixel.g);
                buffer.push(pixel.b);
            }
        }
        let path = &Path::new(&file);
        if let Ok(file) = File::create(path) {
            let w = BufWriter::new(file);
            let mut encoder = png::Encoder::new(w, self.width as u32, self.height as u32);
            encoder.set(png::ColorType::RGB).set(png::BitDepth::Eight);
            if let Ok(mut writer) = encoder.write_header() {
                if writer.write_image_data(&buffer).is_ok() {
                    Ok(())
                } else {
                    Err("Error writing PNG data")
                }
            } else {
                Err("Error writing PNG header")
            }
        } else {
            Err("Error creating file")
        }
    }

    pub fn set_pixel(&mut self, x: usize, y: usize, value: ColorRgb) {
        if x < self.width && y < self.height {
            self.buffer[y][x] = value;
        }
    }

    pub fn overlay(&mut self, other: &ImageBuffer<ColorRgb>, x: usize, y: usize) {
        let ignore = ColorRgb { r: 0, g: 0, b: 0 };
        for sx in 0..other.width {
            for sy in 0..other.height {
                if (other.buffer[sy][sx] != ignore) &&
                    (((sy + y) < self.height) && ((sx + x) < self.width))
                {
                    self.buffer[(sy + y)][(sx + x)] = other.buffer[sy][sx];
                }
            }
        }
    }

    pub fn horizontal_line(&mut self, y: usize, color: ColorRgb) {
        for x in 0..self.width {
            self.buffer[y][x] = color;
        }
    }

    pub fn vertical_line(&mut self, x: usize, color: ColorRgb) {
        for y in 0..self.height {
            self.buffer[y][x] = color;
        }
    }
}
<commit_msg>cleanup: fix new clippy lints (#19)<commit_after>#![deny(warnings)]

extern crate heatmap;
extern crate hsl;
extern crate png;
extern crate rusttype;

use heatmap::Heatmap;
use hsl::HSL;
use png::HasParameters;
use rusttype::{FontCollection, PixelsXY, PositionedGlyph, point};
use std::fs::File;
use std::io::BufWriter;
use std::path::Path;

const US: u64 = 1_000;
const MS: u64 = 1_000 * US;

#[allow(dead_code)]
pub struct Waterfall {
    config: Config,
}

pub struct Config {}

impl Default for Config {
    fn default() -> Config {
        Config {}
    }
}

impl Config {
    pub fn new() -> Config {
        Default::default()
    }

    pub fn build(self) -> Waterfall {
        Waterfall::configured(self)
    }
}

struct Label {
    value: u64,
    text: String,
}

impl Default for Waterfall {
    fn default() -> Waterfall {
        Waterfall::configured(Config::default())
    }
}

impl Waterfall {
    pub fn new() -> Waterfall {
        Default::default()
    }

    pub fn configure() -> Config {
        Config::default()
    }

    fn configured(config: Config) -> Waterfall {
        Waterfall { config: config }
    }

    pub fn render_png(&mut self, heatmap: &Heatmap, file: String) {
        let height = heatmap.num_slices() as usize;
        let width = heatmap.histogram_buckets() as usize;

        // build buffer from data
        let mut buffer = ImageBuffer::<ColorRgb>::new(width, height);
        let max = find_max(heatmap);
        let mut x;
        let mut y = 0;

        // loop to color the pixels
        for slice in heatmap {
            x = 0;
            for bucket in &slice.histogram() {
                let value = (bucket.count() as f64) / (bucket.width() as f64);
                let pixel = color_from_value(value, max);
                buffer.set_pixel(x, y, pixel);
                x += 1;
            }
            y += 1;
        }

        // latency annotations
        let labels: Vec<Label> = vec![
            Label {
                value: 200,
                text: "200nS".to_string(),
            },
            Label {
                value: 500,
                text: "500nS".to_string(),
            },
            Label {
                value: US,
                text: "1uS".to_string(),
            },
            Label {
                value: 2 * US,
                text: "2uS".to_string(),
            },
            Label {
                value: 5 * US,
                text: "5uS".to_string(),
            },
            Label {
                value: 10 * US,
                text: "10uS".to_string(),
            },
            Label {
                value: 20 * US,
                text: "20uS".to_string(),
            },
            Label {
                value: 50 * US,
                text: "50uS".to_string(),
            },
            Label {
                value: 100 * US,
                text: "100uS".to_string(),
            },
            Label {
                value: 200 * US,
                text: "200uS".to_string(),
            },
            Label {
                value: 500 * US,
                text: "500uS".to_string(),
            },
            Label {
                value: MS,
                text: "1mS".to_string(),
            },
            Label {
                value: 2 * MS,
                text: "2mS".to_string(),
            },
            Label {
                value: 5 * MS,
                text: "5mS".to_string(),
            },
            Label {
                value: 10 * MS,
                text: "10mS".to_string(),
            },
            Label {
                value: 20 * MS,
                text: "20mS".to_string(),
            },
            Label {
                value: 50 * MS,
                text: "50mS".to_string(),
            },
            Label {
                value: 100 * MS,
                text: "100mS".to_string(),
            },
            Label {
                value: 200 * MS,
                text: "200mS".to_string(),
            },
            Label {
                value: 500 * MS,
                text: "500mS".to_string(),
            },
        ];

        let mut l = 0;
        y = 0;

        for slice in heatmap {
            x = 0;
            for bucket in &slice.histogram() {
                if (y % 60) == 0 {
                    if x == 0 {
                        let hour = y / 3600;
                        let minute = y / 60;
                        let time = format!("{:02}:{:02}", hour, minute);
                        let overlay = string_buffer(&time, 25.0);
                        buffer.overlay(&overlay, x, y);
                        buffer.horizontal_line(y, ColorRgb { r: 0, g: 0, b: 0 });
                    }
                    let v = bucket.value();
                    if (l < labels.len()) && (v >= labels[l].value) {
                        let overlay = string_buffer(&labels[l].text, 25.0);
                        buffer.overlay(&overlay, x, y);
                        buffer.vertical_line(x, ColorRgb { r: 0, g: 0, b: 0 });
                        l += 1;
                    }
                }
                x += 1;
            }
            y += 1;
        }

        let _ = buffer.write_png(file.clone());
    }
}

fn find_max(heatmap: &Heatmap) -> f64 {
    let mut max = 0.0;

    for slice in heatmap {
        for bucket in &slice.histogram() {
            let value = (bucket.count() as f64) / (bucket.width() as f64);
            if value > max {
                max = value;
            }
        }
    }
    max
}

fn string_buffer(string: &str, size: f32) -> ImageBuffer<ColorRgb> {
    // load font
    let font_data = include_bytes!("../assets/ubuntumono/UbuntuMono-Regular.ttf");
    let collection = FontCollection::from_bytes(font_data as &[u8]);
    let font = collection.into_font().unwrap();

    // size and scaling
    let height: f32 = size;
    let pixel_height = height.ceil() as usize;
    let scale = PixelsXY(height * 1.0, height);

    let v_metrics = font.v_metrics(scale);
    let offset = point(0.0, v_metrics.ascent);

    let glyphs: Vec<PositionedGlyph> = font.layout(string, scale, offset).collect();

    let width = glyphs
        .iter()
        .map(|g| g.h_metrics().advance_width)
        .fold(0.0, |x, y| x + y)
        .ceil() as usize;

    let mut overlay = ImageBuffer::<ColorRgb>::new(width, pixel_height);

    for g in glyphs {
        if let Some(bb) = g.pixel_bounding_box() {
            g.draw(|x, y, v| {
                let x = (x as i32 + bb.min.x) as usize;
                let y = (y as i32 + bb.min.y) as usize;
                if v > 0.25 {
                    overlay.set_pixel(
                        x,
                        y,
                        ColorRgb {
                            r: 255,
                            g: 255,
                            b: 255,
                        },
                    );
                }
            })
        }
    }

    overlay
}

fn color_from_value(value: f64, max: f64) -> ColorRgb {
    let value = value / max;

    let knee = 0.10_f64;

    let hsl = if value < knee {
        let l = 0.25_f64 + 0.25_f64 * value / knee;
        HSL {
            h: 236_f64,
            s: 1_f64,
            l: l,
        }
    } else {
        let h_per_deg: f64 = 236_f64 / (1.0_f64 - knee);
        let deg = (value - knee) * h_per_deg;

        HSL {
            h: (236_f64 - deg),
            s: 1_f64,
            l: 0.50_f64,
        }
    };

    let (r, g, b) = hsl.to_rgb();

    ColorRgb { r: r, g: g, b: b }
}

#[derive(Clone, Copy, Debug, PartialEq)]
struct ColorRgb {
    r: u8,
    g: u8,
    b: u8,
}

struct ImageBuffer<T> {
    buffer: Vec<Vec<T>>,
    height: usize,
    width: usize,
}

impl ImageBuffer<ColorRgb> {
    pub fn new(width: usize, height: usize) -> ImageBuffer<ColorRgb> {
        let background = ColorRgb { r: 0, g: 0, b: 0 };
        let mut row = Vec::<ColorRgb>::with_capacity(width);
        for _ in 0..width {
            row.push(background);
        }
        let mut buffer = Vec::<Vec<ColorRgb>>::with_capacity(height);
        for _ in 0..height {
            buffer.push(row.clone());
        }
        ImageBuffer {
            buffer: buffer,
            height: height,
            width: width,
        }
    }

    pub fn write_png(self, file: String) -> Result<(), &'static str> {
        let mut buffer = Vec::<u8>::with_capacity(self.height * self.width);
        for row in 0..self.height {
            for col in 0..self.width {
                let pixel = self.buffer[row][col];
                buffer.push(pixel.r);
                buffer.push(pixel.g);
                buffer.push(pixel.b);
            }
        }
        let path = &Path::new(&file);
        if let Ok(file) = File::create(path) {
            let w = BufWriter::new(file);
            let mut encoder = png::Encoder::new(w, self.width as u32, self.height as u32);
            encoder.set(png::ColorType::RGB).set(png::BitDepth::Eight);
            if let Ok(mut writer) = encoder.write_header() {
                if writer.write_image_data(&buffer).is_ok() {
                    Ok(())
                } else {
                    Err("Error writing PNG data")
                }
            } else {
                Err("Error writing PNG header")
            }
        } else {
            Err("Error creating file")
        }
    }

    pub fn set_pixel(&mut self, x: usize, y: usize, value: ColorRgb) {
        if x < self.width && y < self.height {
            self.buffer[y][x] = value;
        }
    }

    pub fn overlay(&mut self, other: &ImageBuffer<ColorRgb>, x: usize, y: usize) {
        let ignore = ColorRgb { r: 0, g: 0, b: 0 };
        for sx in 0..other.width {
            for sy in 0..other.height {
                if (other.buffer[sy][sx] != ignore) &&
                    (((sy + y) < self.height) && ((sx + x) < self.width))
                {
                    self.buffer[(sy + y)][(sx + x)] = other.buffer[sy][sx];
                }
            }
        }
    }

    pub fn horizontal_line(&mut self, y: usize, color: ColorRgb) {
        for x in 0..self.width {
            self.buffer[y][x] = color;
        }
    }

    pub fn vertical_line(&mut self, x: usize, color: ColorRgb) {
        for y in 0..self.height {
            self.buffer[y][x] = color;
        }
    }
}
<|endoftext|>


<commit_before>#![feature(collections, std_misc, core)]

#![feature(libc)]
extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;

#[macro_use]
pub mod macros;

#[allow(non_camel_case_types, non_snake_case, raw_pointer_derive, dead_code)]
pub mod ffi;

pub mod error;

pub mod sync {
    pub fn h5sync<T, F>(func: F) -> T where F: FnOnce() -> T,
    {
        use std::sync::{StaticMutex, MUTEX_INIT};
        static LOCK: StaticMutex = MUTEX_INIT;
        let _guard = LOCK.lock();
        func()
    }
}
<commit_msg>Update to the latest rustc (temporarily suppress "hash" warnings in bitflags)<commit_after>#![feature(collections, std_misc, core)]

#![feature(hash)] // temporarily, because of warnings in bitflags

#![feature(libc)]
extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;

#[macro_use]
pub mod macros;

#[allow(non_camel_case_types, non_snake_case, raw_pointer_derive, dead_code)]
pub mod ffi;

pub mod error;

pub mod sync {
    pub fn h5sync<T, F>(func: F) -> T where F: FnOnce() -> T,
    {
        use std::sync::{StaticMutex, MUTEX_INIT};
        static LOCK: StaticMutex = MUTEX_INIT;
        let _guard = LOCK.lock();
        func()
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::*;
use std::slice;
use std::convert::{From, Into};
use std::mem::transmute;
use std::iter::repeat;
use std::ffi::CString;

#[macro_export]
macro_rules! mex_entry {
    ( $func: ident ) => {
        use std::slice;

        #[no_mangle]
        #[allow(non_snake_case)]
        pub fn mexFunction(nlhs: i32, lhs: *mut Array,
                           nrhs: i32, rhs: *const Array) -> () {
            let lhs_slice = unsafe { slice::from_raw_parts_mut(lhs, nlhs as usize) };
            let rhs_slice = unsafe { slice::from_raw_parts(rhs, nrhs as usize) };
            $func(lhs_slice, rhs_slice);
        }
    }
}

pub struct Array {
    ptr: *mut c_void,
}

impl Array {
    pub fn new(dims: Vec<usize>, class: MxClassID, complex: bool) -> Array {
        let ndims_mwsize = dims.len() as MwSize;
        let dims_mwsize: Vec<MwSize> = dims.iter().map(|&x| x as MwSize).collect();
        Array{
            ptr: unsafe { mxCreateNumericArray(ndims_mwsize,
                                               dims_mwsize.as_ptr(),
                                               class.into(),
                                               if complex { 1i32 } else { 0i32 }) }
        }
    }

    pub fn get_class(self: &Self) -> MxClassID {
        MxClassID::from(unsafe { mxGetClassID(self.ptr) })
    }

    pub fn get_dimensions(self: &Self) -> Vec<usize> {
        let num_dims = unsafe { mxGetNumberOfDimensions(self.ptr) } as usize;
        let dims = unsafe { mxGetDimensions(self.ptr) };
        let dims_slice = unsafe {
            slice::from_raw_parts(dims, num_dims)
        };
        dims_slice.iter().map(|&x| x as usize).collect()
    }

    pub fn set_dimensions(self: &mut Self, dims: Vec<usize>) -> () {
        let ndims_mwsize = dims.len() as MwSize;
        let dims_mwsize: Vec<MwSize> = dims.iter().map(|&x| x as MwSize).collect();
        unsafe { mxSetDimensions(self.ptr, dims_mwsize.as_ptr(),
                                           ndims_mwsize); }
    }

    pub fn real_data(self: &Self) -> Data {
        let ptr = unsafe { mxGetData(self.ptr) };
        let dims = self.get_dimensions();
        let numel = dims.iter().fold(1usize, |l,r| l*r);
        match self.get_class() {
            MxClassID::Bool => Data::Bool(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::F64 => Data::F64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::F32 => Data::F32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I8 => Data::I8(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U8 => Data::U8(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I16 => Data::I16(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U16 => Data::U16(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I32 => Data::I32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U32 => Data::U32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I64 => Data::I64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U64 => Data::U64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            _ => Data::NotNumeric
        }
    }

    pub fn imag_data(self: &Self) -> Data {
        let ptr = unsafe { mxGetImagData(self.ptr) };
        let dims = self.get_dimensions();
        let numel = dims.iter().fold(1usize, |l,r| l*r);
        match self.get_class() {
            MxClassID::Bool => Data::Bool(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::F64 => Data::F64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::F32 => Data::F32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I8 => Data::I8(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U8 => Data::U8(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I16 => Data::I16(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U16 => Data::U16(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I32 => Data::I32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U32 => Data::U32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I64 => Data::I64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U64 => Data::U64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            _ => Data::NotNumeric
        }
    }

    pub fn real_data_mut(self: &mut Self) -> DataMut {
        let ptr = unsafe { mxGetData(self.ptr) };
        let dims = self.get_dimensions();
        let numel = dims.iter().fold(1usize, |l,r| l*r);
        match self.get_class() {
            MxClassID::Bool => DataMut::Bool(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::F64 => DataMut::F64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::F32 => DataMut::F32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I8 => DataMut::I8(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U8 => DataMut::U8(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I16 => DataMut::I16(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U16 => DataMut::U16(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I32 => DataMut::I32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U32 => DataMut::U32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I64 => DataMut::I64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U64 => DataMut::U64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            _ => DataMut::NotNumeric
        }
    }

    pub fn imag_data_mut(self: &mut Self) -> DataMut {
        let ptr = unsafe { mxGetImagData(self.ptr) };
        let dims = self.get_dimensions();
        let numel = dims.iter().fold(1usize, |l,r| l*r);
        match self.get_class() {
            MxClassID::Bool => DataMut::Bool(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::F64 => DataMut::F64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::F32 => DataMut::F32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I8 => DataMut::I8(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U8 => DataMut::U8(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I16 => DataMut::I16(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U16 => DataMut::U16(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I32 => DataMut::I32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U32 => DataMut::U32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I64 => DataMut::I64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U64 => DataMut::U64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            _ => DataMut::NotNumeric
        }
    }

    pub fn as_string(self: &Self) -> String {
        let dims = self.get_dimensions();
        let numel = dims.iter().fold(1usize, |l,r| l*r);
        let mut buf: Vec<u8> = repeat(0u8).take(numel+1).collect();
        unsafe {
            mxGetString(self.ptr,
                        transmute(buf.as_mut_ptr()),
                        numel as MwSize + 1);
        }
        buf.pop(); // remove trailing \0
        String::from_utf8(buf).ok().unwrap()
    }
}

pub enum DataMut<'a> {
    NotNumeric,

    Bool(&'a mut [bool]),

    F64(&'a mut [f64]),
    F32(&'a mut [f32]),

    I8(&'a mut [i8]),
    U8(&'a mut [u8]),

    I16(&'a mut [i16]),
    U16(&'a mut [u16]),

    I32(&'a mut [i32]),
    U32(&'a mut [u32]),

    I64(&'a mut [i64]),
    U64(&'a mut [u64]),
}

pub enum Data<'a> {
    NotNumeric,

    Bool(&'a [bool]),

    F64(&'a [f64]),
    F32(&'a [f32]),

    I8(&'a [i8]),
    U8(&'a [u8]),

    I16(&'a [i16]),
    U16(&'a [u16]),

    I32(&'a [i32]),
    U32(&'a [u32]),

    I64(&'a [i64]),
    U64(&'a [u64]),
}

#[cfg(octave)]
pub type MwSize = u32;

#[cfg(matlab)]
pub type MwSize = usize;

#[derive(Debug, Copy, Clone)]
pub enum MxClassID {
    Unknown,
    Cell,
    Struct,
    Bool,
    Char,
    Unused,
    F64,
    F32,
    I8,
    U8,
    I16,
    U16,
    I32,
    U32,
    I64,
    U64,
    Function
}

impl From<i32> for MxClassID {
    fn from(id: i32) -> MxClassID {
        use MxClassID::*;
        match id {
            0 => Unknown,
            1 => Cell,
            2 => Struct,
            3 => Bool,
            4 => Char,
            5 => Unused,
            6 => F64,
            7 => F32,
            8 => I8,
            9 => U8,
            10 => I16,
            11 => U16,
            12 => I32,
            13 => U32,
            14 => I64,
            15 => U64,
            16 => Function,
            _ => Unknown // or error?
        }
    }
}

impl Into<i32> for MxClassID {
    fn into(self: Self) -> i32 {
        use MxClassID::*;
        match self {
            Unknown => 0,
            Cell => 1,
            Struct => 2,
            Bool => 3,
            Char => 4,
            Unused => 5,
            F64 => 6,
            F32 => 7,
            I8 => 8,
            U8 => 9,
            I16 => 10,
            U16 => 11,
            I32 => 12,
            U32 => 13,
            I64 => 14,
            U64 => 15,
            Function => 16
        }
    }
}

#[cfg(octave)]
#[link(name = "octave")]
#[link(name = "octinterp")]
extern { }

#[cfg(matlab)]
#[link(name = "mex")]
#[link(name = "mat")]
extern { }

pub fn mex_println<T: Into<Vec<u8>>>(s: T) -> () {
    let first_arg = CString::new("%s").unwrap();
    let message = CString::new(s).unwrap();
    unsafe {
        mexPrintf(first_arg.as_ptr(), message.as_ptr());
    }
}

extern {
    // type checks
    fn mxGetClassID(ptr: *const c_void) -> i32;

    // creation
    fn mxCreateNumericArray(ndim: MwSize, dims: *const MwSize,
                            class: i32, complex: i32) -> *mut c_void;

    // dimension interrogation
    fn mxGetDimensions(ptr: *const c_void) -> *const MwSize;
    fn mxGetNumberOfDimensions(ptr: *const c_void) -> MwSize;

    // dimension setting
    fn mxSetDimensions(ptr: *mut c_void, dims: *const MwSize, ndims: MwSize) -> ();

    // data extractors
    fn mxGetData(ptr: *const c_void) -> *mut c_void;
    fn mxGetImagData(ptr: *const c_void) -> *mut c_void;
    fn mxGetString(ptr: *const c_void, s: *mut char, strlen: MwSize) -> i32;

    // matlab text output
    fn mexPrintf(msg: *const c_char, ...);
}

<commit_msg>breaking change: as_string returns Option<String><commit_after>extern crate libc;

use libc::*;
use std::slice;
use std::convert::{From, Into};
use std::mem::transmute;
use std::iter::repeat;
use std::ffi::CString;

#[macro_export]
macro_rules! mex_entry {
    ( $func: ident ) => {
        use std::slice;

        #[no_mangle]
        #[allow(non_snake_case)]
        pub fn mexFunction(nlhs: i32, lhs: *mut Array,
                           nrhs: i32, rhs: *const Array) -> () {
            let lhs_slice = unsafe { slice::from_raw_parts_mut(lhs, nlhs as usize) };
            let rhs_slice = unsafe { slice::from_raw_parts(rhs, nrhs as usize) };
            $func(lhs_slice, rhs_slice);
        }
    }
}

pub struct Array {
    ptr: *mut c_void,
}

impl Array {
    pub fn new(dims: Vec<usize>, class: MxClassID, complex: bool) -> Array {
        let ndims_mwsize = dims.len() as MwSize;
        let dims_mwsize: Vec<MwSize> = dims.iter().map(|&x| x as MwSize).collect();
        Array{
            ptr: unsafe { mxCreateNumericArray(ndims_mwsize,
                                               dims_mwsize.as_ptr(),
                                               class.into(),
                                               if complex { 1i32 } else { 0i32 }) }
        }
    }

    pub fn get_class(self: &Self) -> MxClassID {
        MxClassID::from(unsafe { mxGetClassID(self.ptr) })
    }

    pub fn get_dimensions(self: &Self) -> Vec<usize> {
        let num_dims = unsafe { mxGetNumberOfDimensions(self.ptr) } as usize;
        let dims = unsafe { mxGetDimensions(self.ptr) };
        let dims_slice = unsafe {
            slice::from_raw_parts(dims, num_dims)
        };
        dims_slice.iter().map(|&x| x as usize).collect()
    }

    pub fn set_dimensions(self: &mut Self, dims: Vec<usize>) -> () {
        let ndims_mwsize = dims.len() as MwSize;
        let dims_mwsize: Vec<MwSize> = dims.iter().map(|&x| x as MwSize).collect();
        unsafe { mxSetDimensions(self.ptr, dims_mwsize.as_ptr(),
                                           ndims_mwsize); }
    }

    pub fn real_data(self: &Self) -> Data {
        let ptr = unsafe { mxGetData(self.ptr) };
        let dims = self.get_dimensions();
        let numel = dims.iter().fold(1usize, |l,r| l*r);
        match self.get_class() {
            MxClassID::Bool => Data::Bool(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::F64 => Data::F64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::F32 => Data::F32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I8 => Data::I8(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U8 => Data::U8(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I16 => Data::I16(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U16 => Data::U16(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I32 => Data::I32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U32 => Data::U32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I64 => Data::I64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U64 => Data::U64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            _ => Data::NotNumeric
        }
    }

    pub fn imag_data(self: &Self) -> Data {
        let ptr = unsafe { mxGetImagData(self.ptr) };
        let dims = self.get_dimensions();
        let numel = dims.iter().fold(1usize, |l,r| l*r);
        match self.get_class() {
            MxClassID::Bool => Data::Bool(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::F64 => Data::F64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::F32 => Data::F32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I8 => Data::I8(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U8 => Data::U8(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I16 => Data::I16(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U16 => Data::U16(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I32 => Data::I32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U32 => Data::U32(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            MxClassID::I64 => Data::I64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),
            MxClassID::U64 => Data::U64(unsafe { slice::from_raw_parts(transmute(ptr), numel) }),

            _ => Data::NotNumeric
        }
    }

    pub fn real_data_mut(self: &mut Self) -> DataMut {
        let ptr = unsafe { mxGetData(self.ptr) };
        let dims = self.get_dimensions();
        let numel = dims.iter().fold(1usize, |l,r| l*r);
        match self.get_class() {
            MxClassID::Bool => DataMut::Bool(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::F64 => DataMut::F64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::F32 => DataMut::F32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I8 => DataMut::I8(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U8 => DataMut::U8(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I16 => DataMut::I16(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U16 => DataMut::U16(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I32 => DataMut::I32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U32 => DataMut::U32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I64 => DataMut::I64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U64 => DataMut::U64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            _ => DataMut::NotNumeric
        }
    }

    pub fn imag_data_mut(self: &mut Self) -> DataMut {
        let ptr = unsafe { mxGetImagData(self.ptr) };
        let dims = self.get_dimensions();
        let numel = dims.iter().fold(1usize, |l,r| l*r);
        match self.get_class() {
            MxClassID::Bool => DataMut::Bool(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::F64 => DataMut::F64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::F32 => DataMut::F32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I8 => DataMut::I8(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U8 => DataMut::U8(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I16 => DataMut::I16(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U16 => DataMut::U16(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I32 => DataMut::I32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U32 => DataMut::U32(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            MxClassID::I64 => DataMut::I64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),
            MxClassID::U64 => DataMut::U64(unsafe { slice::from_raw_parts_mut(transmute(ptr), numel) }),

            _ => DataMut::NotNumeric
        }
    }

    pub fn as_string(self: &Self) -> Option<String> {
        if let MxClassID::Char = self.get_class() {
            let dims = self.get_dimensions();
            let numel = dims.iter().fold(1usize, |l,r| l*r);
            let mut buf: Vec<u8> = repeat(0u8).take(numel+1).collect();
            unsafe {
                mxGetString(self.ptr,
                            transmute(buf.as_mut_ptr()),
                            numel as MwSize + 1);
            }
            buf.pop(); // remove trailing \0
            Some(String::from_utf8(buf).ok().unwrap())
        } else {
            None
        }
    }
}

pub enum DataMut<'a> {
    NotNumeric,

    Bool(&'a mut [bool]),

    F64(&'a mut [f64]),
    F32(&'a mut [f32]),

    I8(&'a mut [i8]),
    U8(&'a mut [u8]),

    I16(&'a mut [i16]),
    U16(&'a mut [u16]),

    I32(&'a mut [i32]),
    U32(&'a mut [u32]),

    I64(&'a mut [i64]),
    U64(&'a mut [u64]),
}

pub enum Data<'a> {
    NotNumeric,

    Bool(&'a [bool]),

    F64(&'a [f64]),
    F32(&'a [f32]),

    I8(&'a [i8]),
    U8(&'a [u8]),

    I16(&'a [i16]),
    U16(&'a [u16]),

    I32(&'a [i32]),
    U32(&'a [u32]),

    I64(&'a [i64]),
    U64(&'a [u64]),
}

#[cfg(octave)]
pub type MwSize = u32;

#[cfg(matlab)]
pub type MwSize = usize;

#[derive(Debug, Copy, Clone)]
pub enum MxClassID {
    Unknown,
    Cell,
    Struct,
    Bool,
    Char,
    Unused,
    F64,
    F32,
    I8,
    U8,
    I16,
    U16,
    I32,
    U32,
    I64,
    U64,
    Function
}

impl From<i32> for MxClassID {
    fn from(id: i32) -> MxClassID {
        use MxClassID::*;
        match id {
            0 => Unknown,
            1 => Cell,
            2 => Struct,
            3 => Bool,
            4 => Char,
            5 => Unused,
            6 => F64,
            7 => F32,
            8 => I8,
            9 => U8,
            10 => I16,
            11 => U16,
            12 => I32,
            13 => U32,
            14 => I64,
            15 => U64,
            16 => Function,
            _ => Unknown // or error?
        }
    }
}

impl Into<i32> for MxClassID {
    fn into(self: Self) -> i32 {
        use MxClassID::*;
        match self {
            Unknown => 0,
            Cell => 1,
            Struct => 2,
            Bool => 3,
            Char => 4,
            Unused => 5,
            F64 => 6,
            F32 => 7,
            I8 => 8,
            U8 => 9,
            I16 => 10,
            U16 => 11,
            I32 => 12,
            U32 => 13,
            I64 => 14,
            U64 => 15,
            Function => 16
        }
    }
}

#[cfg(octave)]
#[link(name = "octave")]
#[link(name = "octinterp")]
extern { }

#[cfg(matlab)]
#[link(name = "mex")]
#[link(name = "mat")]
extern { }

pub fn mex_println<T: Into<Vec<u8>>>(s: T) -> () {
    let first_arg = CString::new("%s").unwrap();
    let message = CString::new(s).unwrap();
    unsafe {
        mexPrintf(first_arg.as_ptr(), message.as_ptr());
    }
}

extern {
    // type checks
    fn mxGetClassID(ptr: *const c_void) -> i32;

    // creation
    fn mxCreateNumericArray(ndim: MwSize, dims: *const MwSize,
                            class: i32, complex: i32) -> *mut c_void;

    // dimension interrogation
    fn mxGetDimensions(ptr: *const c_void) -> *const MwSize;
    fn mxGetNumberOfDimensions(ptr: *const c_void) -> MwSize;

    // dimension setting
    fn mxSetDimensions(ptr: *mut c_void, dims: *const MwSize, ndims: MwSize) -> ();

    // data extractors
    fn mxGetData(ptr: *const c_void) -> *mut c_void;
    fn mxGetImagData(ptr: *const c_void) -> *mut c_void;
    fn mxGetString(ptr: *const c_void, s: *mut char, strlen: MwSize) -> i32;

    // matlab text output
    fn mexPrintf(msg: *const c_char, ...);
}

<|endoftext|>


<commit_before>#![crate_name="arcsec"]
#![feature(struct_variant)]
#![feature(overloaded_calls, unboxed_closures)]
#![feature(globs)]
#![allow(dead_code)]
//#![deny(warnings)]
extern crate core;

pub mod input;
pub mod ibuffer;
pub mod parser;
pub mod result;
pub mod boxed_closure;
<commit_msg>Fully remove traces of Input<commit_after>#![crate_name="arcsec"]
#![feature(struct_variant)]
#![feature(overloaded_calls, unboxed_closures)]
#![feature(globs)]
#![allow(dead_code)]
//#![deny(warnings)]
extern crate core;

pub mod ibuffer;
pub mod parser;
pub mod result;
pub mod boxed_closure;
<|endoftext|>


<commit_before>extern crate iron;
extern crate router;
extern crate bodyparser;
extern crate racer;
extern crate crypto;

#[derive(Debug)]
pub struct Config {
    pub port: usize,
    pub secret_file: String
}

#[allow(unused_variables)]
pub fn serve(config: Config) {
    println!("{:?}", config);
    unimplemented!();
}

#[test]
fn it_works() {
}
<commit_msg>Start Iron server with handler stubs<commit_after>extern crate iron;
#[macro_use]
extern crate router;
extern crate bodyparser;
extern crate racer;
extern crate crypto;

use iron::{Iron, Chain};

#[derive(Debug)]
pub struct Config {
    pub port: usize,
    pub secret_file: String
}

pub fn serve(config: Config) {
    // For debugging. Torn about `log` crate since there's potentially a lot of noise from our
    // dependencies.
    println!("{:?}", config);

    let chain = Chain::new(router!(
        post "/parse_file"  => handle::parse_file,
        post "/completions" => handle::completions,
        post "/definition"  => handle::definition,
        post "/declaration" => handle::declaration,
        get  "/ping"        => handle::ping));

    let host = format!("localhost:{}", config.port);
    Iron::new(chain).http(&host[..]).unwrap();
}

#[allow(unused_variables)]
mod handle {
    use iron::prelude::*;
    use iron::status;

    /// Parse a file and return a list of issues (warnings, errors) encountered
    pub fn parse_file(req: &mut Request) -> IronResult<Response> {
        unimplemented!();
    }

    /// Given a location, return a list of possible completions
    pub fn completions(req: &mut Request) -> IronResult<Response> {
        unimplemented!();
    }

    /// Given a location, return where the identifier is defined
    pub fn definition(req: &mut Request) -> IronResult<Response> {
        unimplemented!();
    }

    /// Given a location, return a location where the identifier is declared
    pub fn declaration(req: &mut Request) -> IronResult<Response> {
        unimplemented!();
    }

    /// Check if the server is accepting requests
    pub fn ping(req: &mut Request) -> IronResult<Response> {
        Ok(Response::with((status::Ok, "{\"pong\": true}")))
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/reqwest/0.8.1")]

//! # reqwest
//!
//! The `reqwest` crate provides a convenient, higher-level HTTP Client.
//!
//! It handles many of the things that most people just expect an HTTP client
//! to do for them.
//!
//! - Uses system-native TLS
//! - Plain bodies, JSON, urlencoded, multipart
//! - Customizable redirect policy
//! - Proxies
//! - Cookies (only rudimentary support, full support is TODO)
//!
//! The rudimentary cookie support means that the cookies need to be manually
//! configured for every single request. In other words, there's no cookie jar
//! support as of now. The tracking issue for this feature is available
//! [on GitHub][cookiejar_issue].
//!
//! The `reqwest::Client` is synchronous, making it a great fit for
//! applications that only require a few HTTP requests, and wish to handle
//! them synchronously.
//!
//! ## Making a GET request
//!
//! For a single request, you can use the [`get`][get] shortcut method.
//!
//! ```rust
//! use std::io::Read;
//! # use reqwest::{Error, Response};
//!
//! # fn run() -> Result<Response, Error> {
//! let mut resp = reqwest::get("https://www.rust-lang.org")?;
//! assert!(resp.status().is_success());
//!
//! let mut content = String::new();
//! resp.read_to_string(&mut content);
//! # Ok(resp)
//! # }
//! ```
//!
//! As you can see, reqwest's [`Response`][response] struct implements Rust's
//! `Read` trait, so many useful standard library and third party crates will
//! have convenience methods that take a `Response` anywhere `T: Read` is
//! acceptable.
//!
//! If you plan to perform multiple requests, it is best to create a [`Client`][client]
//! and reuse it, taking advantage of keep-alive connection pooling.
//!
//! ## Making POST requests (or setting request bodies)
//!
//! There are several ways you can set the body of a request. The basic one is
//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the
//! exact raw bytes of what the body should be. It accepts various types,
//! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom
//! Reader, you can use the `reqwest::Body::new()` constructor.
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # fn run() -> Result<(), Error> {
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .body("the exact body that is sent")
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! ### Forms
//!
//! It's very common to want to send form data in a request body. This can be
//! done with any type that can be serialized into form data.
//!
//! This can be an array of tuples, or a `HashMap`, or a custom type that
//! implements [`Serialize`][serde].
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # fn run() -> Result<(), Error> {
//! // This will POST a body of `foo=bar&baz=quux`
//! let params = [("foo", "bar"), ("baz", "quux")];
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .form(&params)
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! ### JSON
//!
//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in
//! a similar fashion the `form` method. It can take any value that can be
//! serialized into JSON.
//!
//! ```rust
//! # use reqwest::Error;
//! # use std::collections::HashMap;
//! #
//! # fn run() -> Result<(), Error> {
//! // This will POST a body of `{"lang":"rust","body":"json"}`
//! let mut map = HashMap::new();
//! map.insert("lang", "rust");
//! map.insert("body", "json");
//!
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .json(&map)
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! [hyper]: http://hyper.rs
//! [client]: ./struct.Client.html
//! [response]: ./struct.Response.html
//! [get]: ./fn.get.html
//! [builder]: ./struct.RequestBuilder.html
//! [serde]: http://serde.rs
//! [cookiejar_issue]: https://github.com/seanmonstar/reqwest/issues/14

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
#[macro_use]
extern crate log;
extern crate libflate;
extern crate mime_guess;
extern crate native_tls;
extern crate serde;
extern crate serde_json;
extern crate serde_urlencoded;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_tls;
extern crate url;
extern crate uuid;

pub use hyper::header;
pub use hyper::mime;
pub use hyper::Method;
pub use hyper::StatusCode;
pub use url::Url;
pub use url::ParseError as UrlError;

pub use self::client::{Client, ClientBuilder};
pub use self::error::{Error, Result};
pub use self::body::Body;
pub use self::into_url::IntoUrl;
pub use self::proxy::Proxy;
pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy};
pub use self::request::{Request, RequestBuilder};
pub use self::response::Response;
pub use self::tls::{Certificate, Identity};

// this module must be first because of the `try_` macro
#[macro_use]
mod error;

mod async_impl;
mod connect;
mod body;
mod client;
mod into_url;
mod multipart_;
mod proxy;
mod redirect;
mod request;
mod response;
mod tls;
mod wait;

pub mod multipart;

/// A set of unstable functionality.
///
/// This module is only available when the `unstable` [feature][] is enabled.
/// There is no backwards compatibility guarantee for any of the types within.
///
/// [feature]: http://doc.crates.io/specifying-dependencies.html#choosing-features
#[cfg(feature = "unstable")]
pub mod unstable {
    /// An 'async' implementation of the reqwest `Client`.
    ///
    /// Relies on the `futures` crate, which is unstable, hence this module
    /// is **unstable**.
    pub mod async {
        pub use ::async_impl::{
            Body,
            Chunk,
            Decoder,
            Client,
            ClientBuilder,
            Request,
            RequestBuilder,
            Response,
        };
    }
}

/// Shortcut method to quickly make a `GET` request.
///
/// See also the methods on the [`reqwest::Response`](./struct.Response.html)
/// type.
///
/// # Examples
///
/// ```rust
/// use std::io::Read;
///
/// # fn run() -> Result<(), Box<::std::error::Error>> {
/// let mut result = String::new();
/// reqwest::get("https://www.rust-lang.org")?
///     .read_to_string(&mut result)?;
/// # Ok(())
/// # }
/// # fn main() { }
/// ```
///
/// # Errors
///
/// This function fails if:
///
/// - native TLS backend cannot be initialized
/// - supplied `Url` cannot be parsed
/// - there was an error while sending request
/// - redirect loop was detected
/// - redirect limit was exhausted
pub fn get<T: IntoUrl>(url: T) -> ::Result<Response> {
    Client::new()
        .get(url)
        .send()
}

fn _assert_impls() {
    fn assert_send<T: Send>() {}
    fn assert_sync<T: Sync>() {}
    fn assert_clone<T: Clone>() {}

    assert_send::<Client>();
    assert_sync::<Client>();
    assert_clone::<Client>();

    assert_send::<Request>();
    assert_send::<RequestBuilder>();

    assert_send::<Response>();

    assert_send::<Error>();
    assert_sync::<Error>();
}
<commit_msg>update docs around ::get() and Response::text()<commit_after>#![deny(warnings)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/reqwest/0.8.1")]

//! # reqwest
//!
//! The `reqwest` crate provides a convenient, higher-level HTTP Client.
//!
//! It handles many of the things that most people just expect an HTTP client
//! to do for them.
//!
//! - Uses system-native TLS
//! - Plain bodies, JSON, urlencoded, multipart
//! - Customizable redirect policy
//! - Proxies
//! - Cookies (only rudimentary support, full support is TODO)
//!
//! The rudimentary cookie support means that the cookies need to be manually
//! configured for every single request. In other words, there's no cookie jar
//! support as of now. The tracking issue for this feature is available
//! [on GitHub][cookiejar_issue].
//!
//! The `reqwest::Client` is synchronous, making it a great fit for
//! applications that only require a few HTTP requests, and wish to handle
//! them synchronously.
//!
//! ## Making a GET request
//!
//! For a single request, you can use the [`get`][get] shortcut method.
//!
//! ```rust
//! use std::io::Read;
//! # use reqwest::{Error, Response};
//!
//! # fn run() -> Result<(), Error> {
//! let mut resp = reqwest::get("https://www.rust-lang.org")?;
//!
//! assert!(resp.status().is_success());
//!
//! let body = resp.text()?;
//!
//! println!("body = {:?}", body);
//! # Ok(())
//! # }
//! ```
//!
//! As you can see, reqwest's [`Response`][response] struct implements Rust's
//! `Read` trait, so many useful standard library and third party crates will
//! have convenience methods that take a `Response` anywhere `T: Read` is
//! acceptable.
//!
//! **NOTE**: If you plan to perform multiple requests, it is best to create a
//! [`Client`][client] and reuse it, taking advantage of keep-alive connection
//! pooling.
//!
//! ## Making POST requests (or setting request bodies)
//!
//! There are several ways you can set the body of a request. The basic one is
//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the
//! exact raw bytes of what the body should be. It accepts various types,
//! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom
//! Reader, you can use the `reqwest::Body::new()` constructor.
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # fn run() -> Result<(), Error> {
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .body("the exact body that is sent")
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! ### Forms
//!
//! It's very common to want to send form data in a request body. This can be
//! done with any type that can be serialized into form data.
//!
//! This can be an array of tuples, or a `HashMap`, or a custom type that
//! implements [`Serialize`][serde].
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # fn run() -> Result<(), Error> {
//! // This will POST a body of `foo=bar&baz=quux`
//! let params = [("foo", "bar"), ("baz", "quux")];
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .form(&params)
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! ### JSON
//!
//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in
//! a similar fashion the `form` method. It can take any value that can be
//! serialized into JSON.
//!
//! ```rust
//! # use reqwest::Error;
//! # use std::collections::HashMap;
//! #
//! # fn run() -> Result<(), Error> {
//! // This will POST a body of `{"lang":"rust","body":"json"}`
//! let mut map = HashMap::new();
//! map.insert("lang", "rust");
//! map.insert("body", "json");
//!
//! let client = reqwest::Client::new();
//! let res = client.post("http://httpbin.org/post")
//!     .json(&map)
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! [hyper]: http://hyper.rs
//! [client]: ./struct.Client.html
//! [response]: ./struct.Response.html
//! [get]: ./fn.get.html
//! [builder]: ./struct.RequestBuilder.html
//! [serde]: http://serde.rs
//! [cookiejar_issue]: https://github.com/seanmonstar/reqwest/issues/14

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
#[macro_use]
extern crate log;
extern crate libflate;
extern crate mime_guess;
extern crate native_tls;
extern crate serde;
extern crate serde_json;
extern crate serde_urlencoded;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_tls;
extern crate url;
extern crate uuid;

pub use hyper::header;
pub use hyper::mime;
pub use hyper::Method;
pub use hyper::StatusCode;
pub use url::Url;
pub use url::ParseError as UrlError;

pub use self::client::{Client, ClientBuilder};
pub use self::error::{Error, Result};
pub use self::body::Body;
pub use self::into_url::IntoUrl;
pub use self::proxy::Proxy;
pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy};
pub use self::request::{Request, RequestBuilder};
pub use self::response::Response;
pub use self::tls::{Certificate, Identity};

// this module must be first because of the `try_` macro
#[macro_use]
mod error;

mod async_impl;
mod connect;
mod body;
mod client;
mod into_url;
mod multipart_;
mod proxy;
mod redirect;
mod request;
mod response;
mod tls;
mod wait;

pub mod multipart;

/// A set of unstable functionality.
///
/// This module is only available when the `unstable` [feature][] is enabled.
/// There is no backwards compatibility guarantee for any of the types within.
///
/// [feature]: http://doc.crates.io/specifying-dependencies.html#choosing-features
#[cfg(feature = "unstable")]
pub mod unstable {
    /// An 'async' implementation of the reqwest `Client`.
    ///
    /// Relies on the `futures` crate, which is unstable, hence this module
    /// is **unstable**.
    pub mod async {
        pub use ::async_impl::{
            Body,
            Chunk,
            Decoder,
            Client,
            ClientBuilder,
            Request,
            RequestBuilder,
            Response,
        };
    }
}

/// Shortcut method to quickly make a `GET` request.
///
/// See also the methods on the [`reqwest::Response`](./struct.Response.html)
/// type.
///
/// **NOTE**: This function creates a new internal `Client` on each call,
/// and so should not be used if making many requests. Create a
/// [`Client`](./struct.Client.html) instead.
///
/// # Examples
///
/// ```rust
/// # fn run() -> Result<(), reqwest::Error> {
/// let body = reqwest::get("https://www.rust-lang.org")?
///     .text()?;
/// # Ok(())
/// # }
/// # fn main() { }
/// ```
///
/// # Errors
///
/// This function fails if:
///
/// - native TLS backend cannot be initialized
/// - supplied `Url` cannot be parsed
/// - there was an error while sending request
/// - redirect loop was detected
/// - redirect limit was exhausted
pub fn get<T: IntoUrl>(url: T) -> ::Result<Response> {
    Client::new()
        .get(url)
        .send()
}

fn _assert_impls() {
    fn assert_send<T: Send>() {}
    fn assert_sync<T: Sync>() {}
    fn assert_clone<T: Clone>() {}

    assert_send::<Client>();
    assert_sync::<Client>();
    assert_clone::<Client>();

    assert_send::<Request>();
    assert_send::<RequestBuilder>();

    assert_send::<Response>();

    assert_send::<Error>();
    assert_sync::<Error>();
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate libc;
extern crate time;
extern crate simple_slab;
#[macro_use] extern crate bitflags;

use std::ops::Add;
use std::io::{self, Error};
use std::os::unix::io::{RawFd, AsRawFd};

use time::{Duration, PreciseTime};
use simple_slab::Slab;
pub use interest::Interest;

mod interest;

bitflags! {
    flags ControlOptions: i32 {
        const EPOLL_CTL_ADD = libc::EPOLL_CTL_ADD,
        const EPOLL_CTL_MOD = libc::EPOLL_CTL_MOD,
        const EPOLL_CTL_DEL = libc::EPOLL_CTL_DEL
    }
}

bitflags! {
    pub flags Events: u32 {
        /// Sets the Edge Triggered behavior for the associated file descriptor.
        ///
        /// The default behavior for epoll is Level Triggered.
        const EPOLLET      = libc::EPOLLET as u32,
        /// The associated file is available for read operations.
        const EPOLLIN      = libc::EPOLLIN as u32,
        /// Error condition happened on the associated file descriptor.
        ///
        /// `wait` will always wait for this event; is not necessary to set it in events.
        const EPOLLERR     = libc::EPOLLERR as u32,
        /// Hang up happened on the associated file descriptor.
        ///
        /// `wait` will always wait for this event; it is not necessary to set it in events.
        /// Note that when reading from a channel such as a pipe or a stream socket, this event
        /// merely indicates that the peer closed its end of the channel. Subsequent reads from
        /// the channel will return 0 (end of file) only after all outstanding data in the
        /// channel has been consumed.
        const EPOLLHUP     = libc::EPOLLHUP as u32,
        /// The associated file is available for write operations.
        const EPOLLOUT     = libc::EPOLLOUT as u32,
        /// There is urgent data available for read operations.
        const EPOLLPRI     = libc::EPOLLPRI as u32,
        /// Stream socket peer closed connection, or shut down writing half of connection.
        ///
        /// This flag is especially useful for writing simple code to detect peer shutdown when
        /// using Edge Triggered monitoring.
        const EPOLLRDHUP   = libc::EPOLLRDHUP as u32,
        /// If `EPOLLONESHOT` and `EPOLLET` are clear and the process has the `CAP_BLOCK_SUSPEND`
        /// capability, ensure that the system does not enter "suspend" or "hibernate" while this
        /// event is pending or being processed.
        ///
        /// The event is considered as being "processed" from the time when it is returned by
        /// a call to `wait` until the next call to `wait` on the same `EpollInstance`
        /// descriptor, the closure of that file descriptor, the removal of the event file
        /// descriptor with `EPOLL_CTL_DEL`, or the clearing of `EPOLLWAKEUP` for the event file
        /// descriptor with `EPOLL_CTL_MOD`.
        const EPOLLWAKEUP  = libc::EPOLLWAKEUP as u32,
        /// Sets the one-shot behavior for the associated file descriptor.
        ///
        /// This means that after an event is pulled out with `wait` the associated file
        /// descriptor is internally disabled and no other events will be reported by the epoll
        /// interface.  The user must call `ctl` with `EPOLL_CTL_MOD` to rearm the file
        /// descriptor with a new event mask.
        const EPOLLONESHOT = libc::EPOLLONESHOT as u32
    }
}

pub struct EpollInstance {
    fd: libc::c_int,
    interest_list: Slab<Interest>,
    events: u64,
    wait: Duration
}

impl EpollInstance {

    /// Creates a new `EpollInstance`
    pub fn new() -> io::Result<EpollInstance> {
        let epfd = unsafe {
            let fd = try!(cvt(libc::epoll_create(1)));
            let mut flags = try!(cvt(libc::fcntl(fd, libc::F_GETFD)));
            flags |= libc::FD_CLOEXEC;
            try!(cvt(libc::fcntl(fd, libc::F_SETFD, flags)));
            fd
        };

        Ok(EpollInstance {
            fd: epfd,
            interest_list: Slab::<Interest>::new(),
            events: 0,
            wait: Duration::zero()
        })
    }

    /// Register an initial `Interest` with this instance.
    pub fn add_interest(&mut self, interest: &mut Interest) -> io::Result<()> {
        let mut event_mask = libc::epoll_event {
            events: interest.events().bits() as u32,
            u64: interest.data()
        };
        try!(ctl(self.fd,
                 EPOLL_CTL_ADD.bits(),
                 interest.as_raw_fd(),
                 &mut event_mask as *mut libc::epoll_event));
        self.interest_list.insert(interest.clone());
        Ok(())
    }

    /// Modify the original `Interest`, identified by its `RawFd`, to the passed
    /// interest's events and data fields.
    pub fn mod_interest(&mut self, interest: &mut Interest) -> io::Result<()> {
        let mut event_mask = libc::epoll_event {
            events: interest.events().bits() as u32,
            u64: interest.data()
        };
        try!(ctl(self.fd,
                 EPOLL_CTL_MOD.bits(),
                 interest.as_raw_fd(),
                 &mut event_mask as *mut libc::epoll_event));

        for ref mut _interest in self.interest_list.iter_mut() {
            if _interest.as_raw_fd() == interest.as_raw_fd() {
                _interest.set_events(interest.events());
                _interest.set_data(interest.data());
                break;
            }
        }

        Ok(())
    }

    /// Remove the passed `Interest`, identified by its `RawFd`, from this instance.
    pub fn del_interest(&mut self, interest: &Interest) -> io::Result<()> {
        // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required a non-null
        // pointer in event, even though this argument is ignored.
        let mut event_mask = libc::epoll_event {
            events: 0u32,
            u64: 0u64
        };
        try!(ctl(self.fd,
                 EPOLL_CTL_DEL.bits(),
                 interest.as_raw_fd(),
                 &mut event_mask as *mut libc::epoll_event));

        let mut offset: usize = 0;
        for ref mut _interest in self.interest_list.iter() {
            if _interest.as_raw_fd() == interest.as_raw_fd() {
                break;
            }
            offset += 1
        }
        self.interest_list.remove(offset);

        Ok(())
    }

    /// Waits for events on this instance for at most `timeout` milliseconds and returns at most
    /// `max_returned` `Interests`.
    ///
    /// ## Notes
    ///
    /// * If `timeout` is negative, it will block until an event is received.
    /// * `max_returned` must be greater than zero.
    pub fn wait(&mut self, timeout: i32, max_returned: usize) -> io::Result<Vec<Interest>> {
        let timeout = if timeout < -1 { -1 } else { timeout };
        let mut ret_buf = Vec::<Interest>::with_capacity(max_returned);
        let mut buf = Vec::<libc::epoll_event>::with_capacity(max_returned);

        let (start, end) = unsafe {
            let start = PreciseTime::now();
            let num_events = try!(cvt(libc::epoll_wait(self.fd,
                                                       buf.as_mut_ptr(),
                                                       max_returned as i32,
                                                       timeout))) as usize;
            let end = PreciseTime::now();
            buf.set_len(num_events);
            (start, end)
        };

        self.events += buf.len() as u64;
        self.wait.add(start.to(end));

        for ref event in buf.iter() {
            for ref mut interest in self.interest_list.iter_mut() {
                if interest.data() == event.u64 {
                    (*interest.events_mut()) = Events::from_bits(event.events).unwrap();
                    ret_buf.push(interest.clone());
                    break;
                }
            }
        }

        Ok((ret_buf))
    }

    /// Returns the total number of events reported.
    pub fn events(&self) -> u64 {
        self.events
    }

    /// Returns the total time spent in a blocked, waiting state.
    pub fn wait_time(&self) -> std::time::Duration {
        self.wait.to_std().unwrap()
    }
}

impl AsRawFd for EpollInstance {
    fn as_raw_fd(&self) -> RawFd { self.fd }
}

fn ctl(epfd: libc::c_int,
       op: libc::c_int,
       fd: libc::c_int,
       event: *mut libc::epoll_event)
       -> io::Result<()>
{
    unsafe { try!(cvt(libc::epoll_ctl(epfd, op, fd, event))) };
    Ok(())
}

fn cvt(result: libc::c_int) -> io::Result<libc::c_int> {
    if result < 0 {
        Err(Error::last_os_error())
    } else {
        Ok(result)
    }
}
<commit_msg>Moar docs.<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate libc;
extern crate time;
extern crate simple_slab;
#[macro_use] extern crate bitflags;

use std::ops::Add;
use std::io::{self, Error};
use std::os::unix::io::{RawFd, AsRawFd};

use time::{Duration, PreciseTime};
use simple_slab::Slab;
pub use interest::Interest;

mod interest;

bitflags! {
    flags ControlOptions: i32 {
        const EPOLL_CTL_ADD = libc::EPOLL_CTL_ADD,
        const EPOLL_CTL_MOD = libc::EPOLL_CTL_MOD,
        const EPOLL_CTL_DEL = libc::EPOLL_CTL_DEL
    }
}

bitflags! {
    pub flags Events: u32 {
        /// Sets the Edge Triggered behavior for the associated file descriptor.
        ///
        /// The default behavior for epoll is Level Triggered.
        const EPOLLET      = libc::EPOLLET as u32,
        /// The associated file is available for read operations.
        const EPOLLIN      = libc::EPOLLIN as u32,
        /// Error condition happened on the associated file descriptor.
        ///
        /// `wait` will always wait for this event; is not necessary to set it in events.
        const EPOLLERR     = libc::EPOLLERR as u32,
        /// Hang up happened on the associated file descriptor.
        ///
        /// `wait` will always wait for this event; it is not necessary to set it in events.
        /// Note that when reading from a channel such as a pipe or a stream socket, this event
        /// merely indicates that the peer closed its end of the channel. Subsequent reads from
        /// the channel will return 0 (end of file) only after all outstanding data in the
        /// channel has been consumed.
        const EPOLLHUP     = libc::EPOLLHUP as u32,
        /// The associated file is available for write operations.
        const EPOLLOUT     = libc::EPOLLOUT as u32,
        /// There is urgent data available for read operations.
        const EPOLLPRI     = libc::EPOLLPRI as u32,
        /// Stream socket peer closed connection, or shut down writing half of connection.
        ///
        /// This flag is especially useful for writing simple code to detect peer shutdown when
        /// using Edge Triggered monitoring.
        const EPOLLRDHUP   = libc::EPOLLRDHUP as u32,
        /// If `EPOLLONESHOT` and `EPOLLET` are clear and the process has the `CAP_BLOCK_SUSPEND`
        /// capability, ensure that the system does not enter "suspend" or "hibernate" while this
        /// event is pending or being processed.
        ///
        /// The event is considered as being "processed" from the time when it is returned by
        /// a call to `wait` until the next call to `wait` on the same `EpollInstance`
        /// descriptor, the closure of that file descriptor, the removal of the event file
        /// descriptor with `EPOLL_CTL_DEL`, or the clearing of `EPOLLWAKEUP` for the event file
        /// descriptor with `EPOLL_CTL_MOD`.
        const EPOLLWAKEUP  = libc::EPOLLWAKEUP as u32,
        /// Sets the one-shot behavior for the associated file descriptor.
        ///
        /// This means that after an event is pulled out with `wait` the associated file
        /// descriptor is internally disabled and no other events will be reported by the epoll
        /// interface.  The user must call `ctl` with `EPOLL_CTL_MOD` to rearm the file
        /// descriptor with a new event mask.
        const EPOLLONESHOT = libc::EPOLLONESHOT as u32
    }
}

pub struct EpollInstance {
    fd: libc::c_int,
    interest_list: Slab<Interest>,
    events: u64,
    wait: Duration
}

impl EpollInstance {

    /// Creates a new `EpollInstance`.
    ///
    /// ## Notes
    /// * `FD_CLOEXEC` flag is set on the underlying fd returned.
    pub fn new() -> io::Result<EpollInstance> {
        let epfd = unsafe {
            let fd = try!(cvt(libc::epoll_create(1)));
            let mut flags = try!(cvt(libc::fcntl(fd, libc::F_GETFD)));
            flags |= libc::FD_CLOEXEC;
            try!(cvt(libc::fcntl(fd, libc::F_SETFD, flags)));
            fd
        };

        Ok(EpollInstance {
            fd: epfd,
            interest_list: Slab::<Interest>::new(),
            events: 0,
            wait: Duration::zero()
        })
    }

    /// Register an initial `Interest` with this instance.
    pub fn add_interest(&mut self, interest: &mut Interest) -> io::Result<()> {
        let mut event_mask = libc::epoll_event {
            events: interest.events().bits() as u32,
            u64: interest.data()
        };
        try!(ctl(self.fd,
                 EPOLL_CTL_ADD.bits(),
                 interest.as_raw_fd(),
                 &mut event_mask as *mut libc::epoll_event));
        self.interest_list.insert(interest.clone());
        Ok(())
    }

    /// Modify the original `Interest`, identified by its `RawFd`, to the passed
    /// interest's events and data fields.
    pub fn mod_interest(&mut self, interest: &mut Interest) -> io::Result<()> {
        let mut event_mask = libc::epoll_event {
            events: interest.events().bits() as u32,
            u64: interest.data()
        };
        try!(ctl(self.fd,
                 EPOLL_CTL_MOD.bits(),
                 interest.as_raw_fd(),
                 &mut event_mask as *mut libc::epoll_event));

        for ref mut _interest in self.interest_list.iter_mut() {
            if _interest.as_raw_fd() == interest.as_raw_fd() {
                _interest.set_events(interest.events());
                _interest.set_data(interest.data());
                break;
            }
        }

        Ok(())
    }

    /// Remove the passed `Interest`, identified by its `RawFd`, from this instance.
    pub fn del_interest(&mut self, interest: &Interest) -> io::Result<()> {
        // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required a non-null
        // pointer in event, even though this argument is ignored.
        let mut event_mask = libc::epoll_event {
            events: 0u32,
            u64: 0u64
        };
        try!(ctl(self.fd,
                 EPOLL_CTL_DEL.bits(),
                 interest.as_raw_fd(),
                 &mut event_mask as *mut libc::epoll_event));

        let mut offset: usize = 0;
        for ref mut _interest in self.interest_list.iter() {
            if _interest.as_raw_fd() == interest.as_raw_fd() {
                break;
            }
            offset += 1
        }
        self.interest_list.remove(offset);

        Ok(())
    }

    /// Waits for events on this instance for at most `timeout` milliseconds and returns at most
    /// `max_returned` `Interests`.
    ///
    /// ## Notes
    ///
    /// * If `timeout` is negative, it will block until an event is received.
    /// * `max_returned` must be greater than zero.
    pub fn wait(&mut self, timeout: i32, max_returned: usize) -> io::Result<Vec<Interest>> {
        let timeout = if timeout < -1 { -1 } else { timeout };
        let mut ret_buf = Vec::<Interest>::with_capacity(max_returned);
        let mut buf = Vec::<libc::epoll_event>::with_capacity(max_returned);

        let (start, end) = unsafe {
            let start = PreciseTime::now();
            let num_events = try!(cvt(libc::epoll_wait(self.fd,
                                                       buf.as_mut_ptr(),
                                                       max_returned as i32,
                                                       timeout))) as usize;
            let end = PreciseTime::now();
            buf.set_len(num_events);
            (start, end)
        };

        self.events += buf.len() as u64;
        self.wait.add(start.to(end));

        for ref event in buf.iter() {
            for ref mut interest in self.interest_list.iter_mut() {
                if interest.data() == event.u64 {
                    (*interest.events_mut()) = Events::from_bits(event.events).unwrap();
                    ret_buf.push(interest.clone());
                    break;
                }
            }
        }

        Ok((ret_buf))
    }

    /// Returns the total number of events reported.
    pub fn events(&self) -> u64 {
        self.events
    }

    /// Returns the total time spent in a blocked, waiting state.
    pub fn wait_time(&self) -> std::time::Duration {
        self.wait.to_std().unwrap()
    }
}

impl AsRawFd for EpollInstance {
    fn as_raw_fd(&self) -> RawFd { self.fd }
}

fn ctl(epfd: libc::c_int,
       op: libc::c_int,
       fd: libc::c_int,
       event: *mut libc::epoll_event)
       -> io::Result<()>
{
    unsafe { try!(cvt(libc::epoll_ctl(epfd, op, fd, event))) };
    Ok(())
}

fn cvt(result: libc::c_int) -> io::Result<libc::c_int> {
    if result < 0 {
        Err(Error::last_os_error())
    } else {
        Ok(result)
    }
}
<|endoftext|>


<commit_before>#![allow(unused_features)]
#![feature(raw)]
#![feature(heap_api)]
#![feature(ptr_as_ref)]

//! A generics based scientific computing library for Rust
//!
//!
//! # Introduction
//!
//! This library aims to provide scientific computing functionality in Rust.
//! Current focus is to provide a comprehensive API with simple straight-forward
//! implementations. Different modules cover functionality
//! covering matrices, linear algebra, signal processing and statistics.
//!
//!
//!
//! # Implementation
//!
//! The implementation's aim to take the best advantage
//! of language features in Rust, yet avoid getting too much into
//! heavy degree of performance optimization. We do take
//! advantage of Rust features like generic programming,
//! immutable by default approach, type traits, iterators,
//! amongst others. This is a pure Rust implementation.
//! There is no integration planned at the moment with
//! C libraries like BLAS or LAPACK.
//!
//!
//! # Examples
//!
//! Constructing a simple matrix:
//!
//!     use scirust::api::*;
//!     let a = matrix_cw_f64(2,2, &[1., 4., 2., 8.]);
//!     println!("{}", a);
//!
//!
//! Solving a linear system of equations using Gaussian elimination method
//!
//! ```
//! # /// Import scirust library components
//! # use scirust::api::*;
//! /// Construct a 2x2 matrix
//! let a = matrix_cw_f64(2,2, &[1., 4., 2., 5.]);
//! /// Print the contents of the matrix
//! println!("{}", a);
//! /// A 2x1 vector.
//! let b = vector_f64(&[3.0, 6.0]);
//! /// Solve the linear equation A x = b.
//! let x = GaussElimination::new(&a, &b).solve().unwrap();
//! /// Print the solution vector.
//! println!("{}", x);
//! /// Verify the solution
//! assert_eq!(x, vector_f64(&[-1., 2.]));
//! /// Alternatively use the linear system validation algorithm.
//! let lsv = LinearSystemValidator::new(&a, &x, &b);
//! assert!(lsv.is_max_abs_val_below_threshold(1e-6));
//! ```

#![feature(core)]
#![feature(alloc)]
#![feature(step_by)]
#![feature(convert)]
#![feature(test)]
#![feature(associated_type_defaults)]

#[macro_use(plugin, link)]
#[macro_use]
extern crate log;
extern crate rand;
extern crate num;

// Common modules
pub mod error;
pub mod algebra;

// Main libraries
pub mod external;
pub mod discrete;
pub mod matrix;
pub mod linalg;
pub mod signal;
pub mod dx;
pub mod stat;
pub mod alg;
// // pub mod opt;
// pub mod image {
// #![doc="Image processing
// "]
// }

// pub mod audio {
// #![doc="Audio signal processing
// "]
// }

// // for internal use only
pub mod util;
mod testdata;

// // Overall API of SciRust
pub mod api;
<commit_msg>bug fix in doc test.<commit_after>#![allow(unused_features)]
#![feature(raw)]
#![feature(heap_api)]
#![feature(ptr_as_ref)]

//! A generics based scientific computing library for Rust
//!
//!
//! # Introduction
//!
//! This library aims to provide scientific computing functionality in Rust.
//! Current focus is to provide a comprehensive API with simple straight-forward
//! implementations. Different modules cover functionality
//! covering matrices, linear algebra, signal processing and statistics.
//!
//!
//!
//! # Implementation
//!
//! The implementation's aim to take the best advantage
//! of language features in Rust, yet avoid getting too much into
//! heavy degree of performance optimization. We do take
//! advantage of Rust features like generic programming,
//! immutable by default approach, type traits, iterators,
//! amongst others. This is a pure Rust implementation.
//! There is no integration planned at the moment with
//! C libraries like BLAS or LAPACK.
//!
//!
//! # Examples
//!
//! Constructing a simple matrix:
//!
//!     use scirust::api::*;
//!     let a = matrix_cw_f64(2,2, &[1., 4., 2., 8.]);
//!     println!("{}", a);
//!
//!
//! Solving a linear system of equations using Gaussian elimination method
//!
//! ```
//! # // Import scirust library components
//! # use scirust::api::*;
//! // Construct a 2x2 matrix
//! let a = matrix_cw_f64(2,2, &[1., 4., 2., 5.]);
//! // Print the contents of the matrix
//! println!("{}", a);
//! // A 2x1 vector.
//! let b = vector_f64(&[3.0, 6.0]);
//! // Solve the linear equation A x = b.
//! let x = GaussElimination::new(&a, &b).solve().unwrap();
//! // Print the solution vector.
//! println!("{}", x);
//! // Verify the solution
//! assert_eq!(x, vector_f64(&[-1., 2.]));
//! // Alternatively use the linear system validation algorithm.
//! let lsv = LinearSystemValidator::new(&a, &x, &b);
//! assert!(lsv.is_max_abs_val_below_threshold(1e-6));
//! ```

#![feature(core)]
#![feature(alloc)]
#![feature(step_by)]
#![feature(convert)]
#![feature(test)]
#![feature(associated_type_defaults)]

#[macro_use(plugin, link)]
#[macro_use]
extern crate log;
extern crate rand;
extern crate num;

// Common modules
pub mod error;
pub mod algebra;

// Main libraries
pub mod external;
pub mod discrete;
pub mod matrix;
pub mod linalg;
pub mod signal;
pub mod dx;
pub mod stat;
pub mod alg;
// // pub mod opt;
// pub mod image {
// #![doc="Image processing
// "]
// }

// pub mod audio {
// #![doc="Audio signal processing
// "]
// }

// // for internal use only
pub mod util;
mod testdata;

// // Overall API of SciRust
pub mod api;
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_imports)]

#[macro_use]
extern crate nom;

extern crate crc;

use nom::{HexDisplay,Needed,IResult,ErrorKind,le_i32,le_u32,le_u8,le_u16,length_value,FileProducer};
use nom::Err;
use nom::IResult::*;

struct A {
  a: u8,
  b: u8
}

named!(length_encoded,
    chain!(
        size: le_u32 ~
        crc: le_u32 ~
        data: take!(size),
        || {data}
    )
);

named!(f<&[u8],A>,
    chain!(
        header_size:  le_i32 ~
        header_crc:   le_i32 ~
        header:       take!(header_size) ~
        content_size: le_i32 ~
        content_crc:  le_i32 ~
        content:      take!(content_size),
        || {A {a: 0, b: 0}}
    )
);

#[cfg(test)]
mod tests {
    use nom::IResult::{Done, Error, Incomplete};
    use nom::Needed::Size;

    #[test]
    fn it_works() {
        let data = include_bytes!("../assets/missing-header-data.replay");
        let r = super::length_encoded(data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Incomplete(Size(3534)));
    }

    #[test]
    fn it_works2() {
        let data = include_bytes!("../assets/incomplete-header-data.replay");
        let r = super::length_encoded(data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Incomplete(Size(3534)));
    }

    #[test]
    fn it_works3() {
        let data : [u8; 0] = [];
        let r = super::length_encoded(&data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Incomplete(Size(4)));
    }

    #[test]
    fn it_works4() {
        let data = include_bytes!("../assets/missing-header-crc.replay");
        let r = super::length_encoded(data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Incomplete(Size(8)));
    }

    #[test]
    fn it_works5() {
        let data = [0, 0, 0, 0, 0, 0, 0, 0];
        let r = super::length_encoded(&data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Done(&[][..], &[][..]));
    }
}
<commit_msg>Add text encoded parser<commit_after>#![allow(dead_code)]
#![allow(unused_imports)]

#[macro_use]
extern crate nom;

extern crate crc;

use nom::{HexDisplay,Needed,IResult,ErrorKind,le_i32,le_u32,le_u8,le_u16,length_value,FileProducer};
use nom::Err;
use nom::IResult::*;

struct A {
  a: u8,
  b: u8
}

named!(length_encoded,
    chain!(
        size: le_u32 ~
        crc: le_u32 ~
        data: take!(size),
        || {data}
    )
);

named!(text_encoded<&[u8], &str>,
    chain!(
        size: le_u32 ~
        data: take_str!(size),
        || {data}
    )
);

named!(f<&[u8],A>,
    chain!(
        header_size:  le_i32 ~
        header_crc:   le_i32 ~
        header:       take!(header_size) ~
        content_size: le_i32 ~
        content_crc:  le_i32 ~
        content:      take!(content_size),
        || {A {a: 0, b: 0}}
    )
);

#[cfg(test)]
mod tests {
    use nom::IResult::{Done, Error, Incomplete};
    use nom::Needed::Size;

    #[test]
    fn it_works() {
        let data = include_bytes!("../assets/missing-header-data.replay");
        let r = super::length_encoded(data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Incomplete(Size(3534)));
    }

    #[test]
    fn it_works2() {
        let data = include_bytes!("../assets/incomplete-header-data.replay");
        let r = super::length_encoded(data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Incomplete(Size(3534)));
    }

    #[test]
    fn it_works3() {
        let data : [u8; 0] = [];
        let r = super::length_encoded(&data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Incomplete(Size(4)));
    }

    #[test]
    fn it_works4() {
        let data = include_bytes!("../assets/missing-header-crc.replay");
        let r = super::length_encoded(data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Incomplete(Size(8)));
    }

    #[test]
    fn it_works5() {
        let data = [0, 0, 0, 0, 0, 0, 0, 0];
        let r = super::length_encoded(&data);
        let expected : &[u8] = &data[..];
        assert_eq!(r, Done(&[][..], &[][..]));
    }
}
<|endoftext|>