<commit_before>#![deny(warnings)]
#![feature(io)]

extern crate extra;

use std::ascii::AsciiExt;
use std::env::args;
use std::io::{self, Write, Read};
use std::process::exit;

use extra::option::OptionalExt;
use extra::io::{fail, WriteExt};

static HELP: &'static str = r#"
    NAME
        mtxt - a simple tool to manipulate text from standard input.
    SYNOPSIS
        mtxt [-h | --help | -u | --to-uppercase-w | -l | --to-lowercase | -a | --strip-non-ascii]
    DESCRIPTION
        This utility will manipulate UTF-8 encoded text from the standard input. Unicode is supported. The flags are composable, unless otherwise stated.
    OPTIONS
        -h
        --help
            Print this manual page.
        -u
        --to-uppercase
            Convert the input to UPPERCASE. Works correctly with Unicode. Incompatible with '-l'.
        -l
        --lowercase
            Convert the input to lowercase. Works correctly with Unicode.
        -a
        --strip-non-ascii
            Strip the input for non-ASCII bytes, outputting a valid ASCII string.
    EXAMPLES
        $ echo Δ | mtxt -l
        > δ
        $ echo we got deltas Δ right | mtxt -a
        > we got deltas  right
        $ echo Japanese scripts do not have case thus 山will stay unchanged | mtxt -u
        > JAPANESE SCRIPTS DO NOT HAVE CASE THUS 山WILL STAY UNCHANGED
    AUTHOR
        This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 Ticki

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        Do you actually read the license? wat?
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

fn main() {
    let stdin = io::stdin();
    let stdin = stdin.lock();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    // These are the options.
    let mut to_uppercase = false;
    let mut to_lowercase = false;
    let mut strip_non_ascii = false;

    for arg in args().skip(1) {
        match arg.as_str() {
            "-u" | "--to-uppercase" => to_uppercase = true,
            "-l" | "--to-lowercase" => to_lowercase = true,
            "-a" | "--strip-non-ascii" => strip_non_ascii = true,
            "-h" | "--help" => {
                // The help page.
                stdout.write(HELP.as_bytes()).try(&mut stderr);
            },
            a => {
                // The argument, a, is unknown.
                stderr.write(b"error: unknown argument, ").try(&mut stderr);
                stderr.write(a.as_bytes()).try(&mut stderr);
                stderr.write(b".\n").try(&mut stderr);
                stderr.flush().try(&mut stderr);
                exit(1);
            },
        }
    }

    if to_lowercase && to_uppercase {
        // Fail, since -u and -l are incompatible.
        fail("-u and -l are incompatible. Aborting.", &mut stderr);
    }

    // My eyes bleed.
    //
    // Anyone?
    // ...
    //
    // Silence.
    //
    // If you see this, rewrite the code below. Now, you can't say no. Too late.
    // Muhahahaha.
    for i in stdin.chars() {
        let i = i.try(&mut stderr);

        // TODO handle -a more efficient

        // If -u is set, convert to uppercase
        if to_uppercase {
            for uppercase in i.to_uppercase().filter(|x| !strip_non_ascii || x.is_ascii() ) {
                stdout.write_char(uppercase).try(&mut stderr);
            }
        // If -l is set, convert to lowercase
        } else if to_lowercase {
            for lowercase in i.to_lowercase().filter(|x| !strip_non_ascii || x.is_ascii()) {
                stdout.write_char(lowercase).try(&mut stderr);
            }
        // If -a is set, strip non-ASCII.
        } else if !strip_non_ascii || strip_non_ascii && i.is_ascii() {
            stdout.write_char(i).try(&mut stderr);
        }
    }
}
<commit_msg>Fix mtxt with newest nightly rust<commit_after>#![deny(warnings)]

extern crate extra;

use std::ascii::AsciiExt;
use std::env::args;
use std::io::{self, Write, Read};
use std::process::exit;

use extra::option::OptionalExt;
use extra::io::{fail, WriteExt};

static HELP: &'static str = r#"
    NAME
        mtxt - a simple tool to manipulate text from standard input.
    SYNOPSIS
        mtxt [-h | --help | -u | --to-uppercase-w | -l | --to-lowercase | -a | --strip-non-ascii]
    DESCRIPTION
        This utility will manipulate UTF-8 encoded text from the standard input. Unicode is supported. The flags are composable, unless otherwise stated.
    OPTIONS
        -h
        --help
            Print this manual page.
        -u
        --to-uppercase
            Convert the input to UPPERCASE. Works correctly with Unicode. Incompatible with '-l'.
        -l
        --lowercase
            Convert the input to lowercase. Works correctly with Unicode.
        -a
        --strip-non-ascii
            Strip the input for non-ASCII bytes, outputting a valid ASCII string.
    EXAMPLES
        $ echo Δ | mtxt -l
        > δ
        $ echo we got deltas Δ right | mtxt -a
        > we got deltas  right
        $ echo Japanese scripts do not have case thus 山will stay unchanged | mtxt -u
        > JAPANESE SCRIPTS DO NOT HAVE CASE THUS 山WILL STAY UNCHANGED
    AUTHOR
        This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be reported in the Github repository, 'redox-os/extrautils'.
    COPYRIGHT
        Copyright (c) 2016 Ticki

        Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

        Do you actually read the license? wat?
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#;

fn main() {
    let stdin = io::stdin();
    let stdin = stdin.lock();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    // These are the options.
    let mut to_uppercase = false;
    let mut to_lowercase = false;
    let mut strip_non_ascii = false;

    for arg in args().skip(1) {
        match arg.as_str() {
            "-u" | "--to-uppercase" => to_uppercase = true,
            "-l" | "--to-lowercase" => to_lowercase = true,
            "-a" | "--strip-non-ascii" => strip_non_ascii = true,
            "-h" | "--help" => {
                // The help page.
                stdout.write(HELP.as_bytes()).try(&mut stderr);
            },
            a => {
                // The argument, a, is unknown.
                stderr.write(b"error: unknown argument, ").try(&mut stderr);
                stderr.write(a.as_bytes()).try(&mut stderr);
                stderr.write(b".\n").try(&mut stderr);
                stderr.flush().try(&mut stderr);
                exit(1);
            },
        }
    }

    if to_lowercase && to_uppercase {
        // Fail, since -u and -l are incompatible.
        fail("-u and -l are incompatible. Aborting.", &mut stderr);
    }

    // My eyes bleed.
    //
    // Anyone?
    // ...
    //
    // Silence.
    //
    // If you see this, rewrite the code below. Now, you can't say no. Too late.
    // Muhahahaha.
    for i in stdin.chars() {
        let i = i.try(&mut stderr);

        // TODO handle -a more efficient

        // If -u is set, convert to uppercase
        if to_uppercase {
            for uppercase in i.to_uppercase().filter(|x| !strip_non_ascii || x.is_ascii() ) {
                stdout.write_char(uppercase).try(&mut stderr);
            }
        // If -l is set, convert to lowercase
        } else if to_lowercase {
            for lowercase in i.to_lowercase().filter(|x| !strip_non_ascii || x.is_ascii()) {
                stdout.write_char(lowercase).try(&mut stderr);
            }
        // If -a is set, strip non-ASCII.
        } else if !strip_non_ascii || strip_non_ascii && i.is_ascii() {
            stdout.write_char(i).try(&mut stderr);
        }
    }
}
<|endoftext|>


<commit_before>//! DNS data.
//!
//! This module provides types and traits for working with DNS data as well
//! as parsing and composing wire-format DNS messages.
//!
//! # Working with DNS Data
//!
//! The module contains abstractions for two concepts used in DNS data:
//! domain names and character strings. In both cases, the supplied types
//! internally contain the binary data and work directly on it. Similar
//! to raw bytes slices, there types for borrowed and owned domain names
//! and character strings where the owned type derefs to the borrowed one.
//! For domain names, these types are [`DNameSlice`] and [`DNameBuf`];
//! for character strings [`CharStr`] and [`CharStrBuf`].
//!
//! For domain names there is a third variant, [`ParsedDName`]. This type is
//! necessary to represent compressed names where the remainder of a name is
//! to be found elsewhere in the message. It avoids allocations when access
//! to the entire name isn’t necessary.
//!
//! Traits are used when constructing composite types to allow them to work
//! on borrowed and owned data as well as on parsed domain names. For
//! character strings and raw bytes data, `AsRef<CharStr>` and `AsRef<[u8]>`
//! are being used. For domain names, there is a separate trait, [`DName`]
//! with the same purpose. However, its functionality is limited to the
//! what parsed domain names can provide.
//!
//! A number of composite types are already defined: [`Question`] for
//! the questions of a query, [`Record`] for resource records.
//!
//! Instead of having one big enum, the data of resource records is kept
//! generic through two traits: [`RecordData`] provides functions common to
//! all variants of record data types while [`ParsedRecordData`] adds
//! the ability to construct a value from a wire-format message for those
//! variants that can use borrowed data and parsed domain names. The actual
//! types implementing these traits can by found in the crate’s [rdata]
//! module.
//!
//! # Parsing and Composing Messages
//!
//! In order to easily distinguish the process of creating and disecting
//! wire-format messages from working with master files, we use the term
//! *parsing* and *composing* for reading from and writing to wire-format
//! data.
//!
//! Both parsing and composing happen on bytes buffers. This seems to be a
//! reasonably choice given the relatively small size of DNS messages and
//! the complexities introduced by name compression. The details are
//! explained in the [parse] and [compose] sub-modules. Unless you are
//! implementing your own resource record types, you are unlikely to ever
//! having to deal with parsing and composing directly.
//!
//! Instead, the types [`Message`] and [`MessageBuilder`] are there to make
//! parsing and constructing DNS messages easy. A [`Message`] takes the
//! binary data of a DNS message and allows iterating over its four
//! sections to look at the questions and resource records. Similarly,
//! a [`MessageBuilder`] takes a bytes vector (or creates one for you) and
//! has functionality to build the sections of the message step-by-step.
//!
//! [rdata]: ../rdata/index.html
//! [compose]: compose/index.html
//! [parse]: parse/index.html
//! [`CharStr`]: charstr/struct.CharStr.html
//! [`CharStrBuf`]: charstr/struct.CharStrBuf.html
//! [`DName`]: name/trait.DName.html
//! [`DNameBuf`]: name/struct.DNameBuf.html
//! [`DNameSlice`]: name/struct.DNameSlice.html
//! [`Message`]: message/struct.Message.html
//! [`MessageBuilder`]: message_builder/struct.MessageBuilder.html
//! [`ParsedDName`]: name/struct.ParsedDName.html
//! [`ParsedRecordData`]: rdata/trait.ParsedRecordData.html
//! [`Question`]: question/struct.Question.html
//! [`Record`]: record/struct.Record.html
//! [`RecordData`]: rdata/trait.RecordData.html

//--- Re-exports

pub use self::charstr::{CharStr, CharStrBuf};
pub use self::compose::{Composable, Composer, ComposeError, ComposeMode,
                        ComposeResult, ComposeSnapshot};
pub use self::header::{Header, HeaderCounts, HeaderSection};
pub use self::message::{Message, MessageBuf};
pub use self::message_builder::{MessageBuilder, AnswerBuilder,
                                AuthorityBuilder, AdditionalBuilder};
pub use self::name::{DName, DNameBuf, DNameSlice, ParsedDName};
pub use self::parse::{Parser, ParseError, ParseResult};
pub use self::question::Question;
pub use self::rdata::{GenericRecordData, ParsedRecordData, RecordData};
pub use self::record::{GenericRecord, Record};

//--- Modules

pub mod charstr;
pub mod compose;
pub mod header;
pub mod message;
pub mod message_builder;
pub mod name;
pub mod net;
pub mod parse;
pub mod question;
pub mod rdata;
pub mod record;

<commit_msg>Fix another typo<commit_after>//! DNS data.
//!
//! This module provides types and traits for working with DNS data as well
//! as parsing and composing wire-format DNS messages.
//!
//! # Working with DNS Data
//!
//! The module contains abstractions for two concepts used in DNS data:
//! domain names and character strings. In both cases, the supplied types
//! internally contain the binary data and work directly on it. Similar
//! to raw bytes slices, there types for borrowed and owned domain names
//! and character strings where the owned type derefs to the borrowed one.
//! For domain names, these types are [`DNameSlice`] and [`DNameBuf`];
//! for character strings [`CharStr`] and [`CharStrBuf`].
//!
//! For domain names there is a third variant, [`ParsedDName`]. This type is
//! necessary to represent compressed names where the remainder of a name is
//! to be found elsewhere in the message. It avoids allocations when access
//! to the entire name isn’t necessary.
//!
//! Traits are used when constructing composite types to allow them to work
//! on borrowed and owned data as well as on parsed domain names. For
//! character strings and raw bytes data, `AsRef<CharStr>` and `AsRef<[u8]>`
//! are being used. For domain names, there is a separate trait, [`DName`]
//! with the same purpose. However, its functionality is limited to the
//! what parsed domain names can provide.
//!
//! A number of composite types are already defined: [`Question`] for
//! the questions of a query, [`Record`] for resource records.
//!
//! Instead of having one big enum, the data of resource records is kept
//! generic through two traits: [`RecordData`] provides functions common to
//! all variants of record data types while [`ParsedRecordData`] adds
//! the ability to construct a value from a wire-format message for those
//! variants that can use borrowed data and parsed domain names. The actual
//! types implementing these traits can by found in the crate’s [rdata]
//! module.
//!
//! # Parsing and Composing Messages
//!
//! In order to easily distinguish the process of creating and disecting
//! wire-format messages from working with master files, we use the term
//! *parsing* and *composing* for reading from and writing to wire-format
//! data.
//!
//! Both parsing and composing happen on bytes buffers. This seems to be a
//! reasonably good choice given the relatively small size of DNS messages and
//! the complexities introduced by name compression. The details are
//! explained in the [parse] and [compose] sub-modules. Unless you are
//! implementing your own resource record types, you are unlikely to ever
//! having to deal with parsing and composing directly.
//!
//! Instead, the types [`Message`] and [`MessageBuilder`] are there to make
//! parsing and constructing DNS messages easy. A [`Message`] takes the
//! binary data of a DNS message and allows iterating over its four
//! sections to look at the questions and resource records. Similarly,
//! a [`MessageBuilder`] takes a bytes vector (or creates one for you) and
//! has functionality to build the sections of the message step-by-step.
//!
//! [rdata]: ../rdata/index.html
//! [compose]: compose/index.html
//! [parse]: parse/index.html
//! [`CharStr`]: charstr/struct.CharStr.html
//! [`CharStrBuf`]: charstr/struct.CharStrBuf.html
//! [`DName`]: name/trait.DName.html
//! [`DNameBuf`]: name/struct.DNameBuf.html
//! [`DNameSlice`]: name/struct.DNameSlice.html
//! [`Message`]: message/struct.Message.html
//! [`MessageBuilder`]: message_builder/struct.MessageBuilder.html
//! [`ParsedDName`]: name/struct.ParsedDName.html
//! [`ParsedRecordData`]: rdata/trait.ParsedRecordData.html
//! [`Question`]: question/struct.Question.html
//! [`Record`]: record/struct.Record.html
//! [`RecordData`]: rdata/trait.RecordData.html

//--- Re-exports

pub use self::charstr::{CharStr, CharStrBuf};
pub use self::compose::{Composable, Composer, ComposeError, ComposeMode,
                        ComposeResult, ComposeSnapshot};
pub use self::header::{Header, HeaderCounts, HeaderSection};
pub use self::message::{Message, MessageBuf};
pub use self::message_builder::{MessageBuilder, AnswerBuilder,
                                AuthorityBuilder, AdditionalBuilder};
pub use self::name::{DName, DNameBuf, DNameSlice, ParsedDName};
pub use self::parse::{Parser, ParseError, ParseResult};
pub use self::question::Question;
pub use self::rdata::{GenericRecordData, ParsedRecordData, RecordData};
pub use self::record::{GenericRecord, Record};

//--- Modules

pub mod charstr;
pub mod compose;
pub mod header;
pub mod message;
pub mod message_builder;
pub mod name;
pub mod net;
pub mod parse;
pub mod question;
pub mod rdata;
pub mod record;

<|endoftext|>


<commit_before>use Printer;
use vec::Vec2;
use view::{View, ViewWrapper};

/// Draws a border around a wrapped view.
pub struct Panel<V: View> {
    view: V,
}

impl<V: View> Panel<V> {
    /// Creates a new panel around the given view.
    pub fn new(view: V) -> Self {
        Panel { view: view }
    }
}

impl<V: View> ViewWrapper for Panel<V> {
    wrap_impl!(self.view: V);

    fn wrap_required_size(&mut self, req: Vec2) -> Vec2 {
        // TODO: make borders conditional?
        let req = req.saturating_sub((2, 2));

        self.view.required_size(req) + (2, 2)
    }

    fn wrap_draw(&self, printer: &Printer) {
        printer.print_box((0, 0), printer.size, true);
        self.view.draw(&printer.sub_printer(
            (1, 1),
            printer.size.saturating_sub((2, 2)),
            true,
        ));
    }

    fn wrap_layout(&mut self, size: Vec2) {
        self.view.layout(size.saturating_sub((2, 2)));
    }
}
<commit_msg>Correct event relativization in Panel<commit_after>use Printer;
use event::{Event, EventResult};
use vec::Vec2;
use view::{View, ViewWrapper};

/// Draws a border around a wrapped view.
pub struct Panel<V: View> {
    view: V,
}

impl<V: View> Panel<V> {
    /// Creates a new panel around the given view.
    pub fn new(view: V) -> Self {
        Panel { view: view }
    }
}

impl<V: View> ViewWrapper for Panel<V> {
    wrap_impl!(self.view: V);

    fn wrap_on_event(&mut self, event: Event) -> EventResult {
        self.view.on_event(event.relativized((1, 1)))
    }

    fn wrap_required_size(&mut self, req: Vec2) -> Vec2 {
        // TODO: make borders conditional?
        let req = req.saturating_sub((2, 2));

        self.view.required_size(req) + (2, 2)
    }

    fn wrap_draw(&self, printer: &Printer) {
        printer.print_box((0, 0), printer.size, true);
        self.view.draw(&printer.sub_printer(
            (1, 1),
            printer.size.saturating_sub((2, 2)),
            true,
        ));
    }

    fn wrap_layout(&mut self, size: Vec2) {
        self.view.layout(size.saturating_sub((2, 2)));
    }
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types, non_snake_case)]
extern crate winreg;

use pdcurses::*;
use libc::c_int;

use std::env;
use std::ffi::{CString, OsStr};
use std::i32;
use std::path::Path;

use self::winreg::RegKey;
use windows::winreg::enums::HKEY_CURRENT_USER;

pub mod constants;
use self::constants::*;

use input::Input;

pub fn pre_init() {
    #[cfg(any(feature = "win32a", all(not(feature = "win32"), not(feature = "win32a"))))]
    win32a_pre_init();
}

#[cfg(any(feature = "win32a", all(not(feature = "win32"), not(feature = "win32a"))))]
fn win32a_pre_init() {

    let exe_name = env::current_exe()
        .ok()
        .as_ref()
        .map(Path::new)
        .and_then(Path::file_name)
        .and_then(OsStr::to_str)
        .map(String::from)
        .map(|mut x| {
            let last_dot = x.rfind('.').unwrap_or(0);
            x.truncate(last_dot);
            x
        });

    if exe_name.is_none() {
        warn!("Could not determine name of exe");
        return;
    }
    let exe_name = exe_name.unwrap();

    // The format of the registry value is:
    // <cols>x<rows>,<font_size>,<x_loc>,<y_loc>,<menu_shown>;<min_lines>,<max_lines>,<min_cols>,<max_cols>:<font_name>
    // Example: 80x25,12,312,312,1;2,2147483647,2,2147483647:Courier New
    let hkcu = RegKey::predef(HKEY_CURRENT_USER);
    let existing_value = hkcu.open_subkey("Software\\PDCurses")
        .and_then(|reg_key| reg_key.get_value::<String, &str>(&exe_name))
        .unwrap_or("80x25,12,0,0,1;25,25,80,80:Courier New".to_string());

    let rejoined_menu: String;
    let maxi32 = format!("{}", i32::MAX);
    let mut split: Vec<&str> = existing_value.split(',').collect();

    // The value at index 4 will be <menu_shown>;<min_lines> because we split on ,
    let mut menu_split: Vec<&str> = split[4].split(';').collect();

    // Set the menu_shown value to 0 to always hide it
    #[cfg(not(feature = "show_menu"))]
    {
        menu_split[0] = "0";
    }

    #[cfg(not(feature = "disable_resize"))]
    {
        // Set the resize limits to 2 - i32::MAX to allow unlimited resizing
        menu_split[1] = "2";
        split[5] = &maxi32;
        split[6] = "2";
        split[7] = &maxi32;
    }

    // Re-join the values back into a string
    rejoined_menu = menu_split.join(";");
    split[4] = &rejoined_menu;

    // Write the modified values back into the registry
    match hkcu.open_subkey("Software\\PDCurses").and_then(|reg_key| {
        reg_key.set_value::<String, &str>(&exe_name, &split.join(","))
    }) {
        Err(e) => warn!("Failed to set registry value: {}", e),
        _ => (),
    }
}

pub fn _attron(w: *mut WINDOW, attributes: chtype) -> i32 {
    unsafe { wattron(w, attributes) }
}

pub fn _attroff(w: *mut WINDOW, attributes: chtype) -> i32 {
    unsafe { wattroff(w, attributes) }
}

pub fn _attrset(w: *mut WINDOW, attributes: chtype) -> i32 {
    unsafe { wattrset(w, attributes) }
}

pub fn _COLORS() -> i32 {
    unsafe { COLORS }
}

pub fn _COLOR_PAIRS() -> i32 {
    unsafe { COLOR_PAIRS }
}

pub fn _draw_box(w: *mut WINDOW, verch: chtype, horch: chtype) -> i32 {
    unsafe { _box(w, verch, horch) }
}

pub fn _getmouse() -> Result<MEVENT, i32> {
    let mut mevent = MEVENT {
        id: 0,
        x: 0,
        y: 0,
        z: 0,
        bstate: 0,
    };
    let error = unsafe { nc_getmouse(&mut mevent) };
    if error == 0 { Ok(mevent) } else { Err(error) }
}

pub fn _mouse_trafo(w: &mut *mut WINDOW, y: &mut i32, x: &mut i32, to_screen: bool) {
    unsafe {
        wmouse_trafo(*w, y, x, to_screen as u8);
    }
}

pub fn _resize_term(nlines: i32, ncols: i32) -> i32 {
    unsafe { resize_term(nlines, ncols) }
}

pub fn _set_blink(enabled: bool) -> i32 {
    unsafe { PDC_set_blink(enabled as u8) }
}

pub fn _set_title(title: &str) {
    let s = CString::new(title).unwrap();
    unsafe { PDC_set_title(s.as_ptr()) }
}

/// Converts an integer returned by getch() to a Input value
pub fn to_special_keycode(i: i32) -> Input {
    // Not the best, but until I add _all_ the keys between UNDO and RESIZE this will have to do
    // Most of them are PDCurses specific anyway and would not map to Input if I want to keep it
    // clean of implementation specific keys.
    if i == KEY_RESIZE {
        Input::KeyResize
    } else if i == KEY_MOUSE {
        Input::KeyMouse
    } else {
        assert!(
            i >= KEY_OFFSET,
            format!("Input value less than expected: {:?}", i)
        );
        let i = if i <= KEY_F15 {
            i - KEY_OFFSET
        } else {
            i - KEY_OFFSET - 48
        };
        if i as usize >= SPECIAL_KEY_CODES.len() {
            Input::Unknown(i)
        } else {
            SPECIAL_KEY_CODES[i as usize]
        }
    }
}

pub fn _ungetch(input: &Input) -> i32 {
    let i = convert_input_to_c_int(input);
    unsafe { PDC_ungetch(i) }
}

fn convert_input_to_c_int(input: &Input) -> c_int {
    match *input {
        Input::Character(c) => c as c_int,
        Input::Unknown(i) => i,
        Input::KeyResize => KEY_RESIZE,
        Input::KeyMouse => KEY_MOUSE,
        specialKeyCode => {
            for (i, skc) in SPECIAL_KEY_CODES.into_iter().enumerate() {
                if *skc == specialKeyCode {
                    let result = i as c_int + KEY_OFFSET;
                    if result <= KEY_F15 {
                        return result;
                    } else {
                        return result + 48;
                    }
                }
            }
            panic!("Failed to convert Input back to a c_int");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::convert_input_to_c_int;
    use input::Input;
    use libc::c_int;

    #[test]
    fn test_key_dl_to_special_keycode() {
        assert_eq!(Input::KeyDL, to_special_keycode(KEY_OFFSET + 0x48));
    }

    #[test]
    fn test_key_f15_to_input() {
        assert_eq!(Input::KeyF15, to_special_keycode(KEY_OFFSET + 0x08 + 15));
    }

    #[test]
    fn test_key_up_to_input() {
        assert_eq!(Input::KeyUp, to_special_keycode(KEY_OFFSET + 3));
    }

    #[test]
    fn test_convert_input_to_c_int() {
        let i = convert_input_to_c_int(&Input::Character('a'));
        assert_eq!('a' as c_int, i);
    }

    #[test]
    fn test_convert_backspace_to_c_int() {
        let i = convert_input_to_c_int(&Input::KeyBackspace);
        assert_eq!(KEY_OFFSET + 0x07, i);
    }

    #[test]
    fn test_convert_sdl_to_c_int() {
        let i = convert_input_to_c_int(&Input::KeySDL);
        assert_eq!(KEY_OFFSET + 0x7e, i);
    }

    #[test]
    fn test_convert_key_mouse() {
        let i = convert_input_to_c_int(&Input::KeyMouse);
        let kc = to_special_keycode(i);
        assert_eq!(i, convert_input_to_c_int(&kc));
    }
}
<commit_msg>Moved comment to be consistent with others<commit_after>#![allow(non_camel_case_types, non_snake_case)]
extern crate winreg;

use pdcurses::*;
use libc::c_int;

use std::env;
use std::ffi::{CString, OsStr};
use std::i32;
use std::path::Path;

use self::winreg::RegKey;
use windows::winreg::enums::HKEY_CURRENT_USER;

pub mod constants;
use self::constants::*;

use input::Input;

pub fn pre_init() {
    #[cfg(any(feature = "win32a", all(not(feature = "win32"), not(feature = "win32a"))))]
    win32a_pre_init();
}

#[cfg(any(feature = "win32a", all(not(feature = "win32"), not(feature = "win32a"))))]
fn win32a_pre_init() {

    let exe_name = env::current_exe()
        .ok()
        .as_ref()
        .map(Path::new)
        .and_then(Path::file_name)
        .and_then(OsStr::to_str)
        .map(String::from)
        .map(|mut x| {
            let last_dot = x.rfind('.').unwrap_or(0);
            x.truncate(last_dot);
            x
        });

    if exe_name.is_none() {
        warn!("Could not determine name of exe");
        return;
    }
    let exe_name = exe_name.unwrap();

    // The format of the registry value is:
    // <cols>x<rows>,<font_size>,<x_loc>,<y_loc>,<menu_shown>;<min_lines>,<max_lines>,<min_cols>,<max_cols>:<font_name>
    // Example: 80x25,12,312,312,1;2,2147483647,2,2147483647:Courier New
    let hkcu = RegKey::predef(HKEY_CURRENT_USER);
    let existing_value = hkcu.open_subkey("Software\\PDCurses")
        .and_then(|reg_key| reg_key.get_value::<String, &str>(&exe_name))
        .unwrap_or("80x25,12,0,0,1;25,25,80,80:Courier New".to_string());

    let rejoined_menu: String;
    let maxi32 = format!("{}", i32::MAX);
    let mut split: Vec<&str> = existing_value.split(',').collect();

    // The value at index 4 will be <menu_shown>;<min_lines> because we split on ,
    let mut menu_split: Vec<&str> = split[4].split(';').collect();

    // Set the menu_shown value to 0 to always hide it
    #[cfg(not(feature = "show_menu"))]
    {
        menu_split[0] = "0";
    }

    // Set the resize limits to 2 - i32::MAX to allow unlimited resizing
    #[cfg(not(feature = "disable_resize"))]
    {
        menu_split[1] = "2";
        split[5] = &maxi32;
        split[6] = "2";
        split[7] = &maxi32;
    }

    // Re-join the values back into a string
    rejoined_menu = menu_split.join(";");
    split[4] = &rejoined_menu;

    // Write the modified values back into the registry
    match hkcu.open_subkey("Software\\PDCurses").and_then(|reg_key| {
        reg_key.set_value::<String, &str>(&exe_name, &split.join(","))
    }) {
        Err(e) => warn!("Failed to set registry value: {}", e),
        _ => (),
    }
}

pub fn _attron(w: *mut WINDOW, attributes: chtype) -> i32 {
    unsafe { wattron(w, attributes) }
}

pub fn _attroff(w: *mut WINDOW, attributes: chtype) -> i32 {
    unsafe { wattroff(w, attributes) }
}

pub fn _attrset(w: *mut WINDOW, attributes: chtype) -> i32 {
    unsafe { wattrset(w, attributes) }
}

pub fn _COLORS() -> i32 {
    unsafe { COLORS }
}

pub fn _COLOR_PAIRS() -> i32 {
    unsafe { COLOR_PAIRS }
}

pub fn _draw_box(w: *mut WINDOW, verch: chtype, horch: chtype) -> i32 {
    unsafe { _box(w, verch, horch) }
}

pub fn _getmouse() -> Result<MEVENT, i32> {
    let mut mevent = MEVENT {
        id: 0,
        x: 0,
        y: 0,
        z: 0,
        bstate: 0,
    };
    let error = unsafe { nc_getmouse(&mut mevent) };
    if error == 0 { Ok(mevent) } else { Err(error) }
}

pub fn _mouse_trafo(w: &mut *mut WINDOW, y: &mut i32, x: &mut i32, to_screen: bool) {
    unsafe {
        wmouse_trafo(*w, y, x, to_screen as u8);
    }
}

pub fn _resize_term(nlines: i32, ncols: i32) -> i32 {
    unsafe { resize_term(nlines, ncols) }
}

pub fn _set_blink(enabled: bool) -> i32 {
    unsafe { PDC_set_blink(enabled as u8) }
}

pub fn _set_title(title: &str) {
    let s = CString::new(title).unwrap();
    unsafe { PDC_set_title(s.as_ptr()) }
}

/// Converts an integer returned by getch() to a Input value
pub fn to_special_keycode(i: i32) -> Input {
    // Not the best, but until I add _all_ the keys between UNDO and RESIZE this will have to do
    // Most of them are PDCurses specific anyway and would not map to Input if I want to keep it
    // clean of implementation specific keys.
    if i == KEY_RESIZE {
        Input::KeyResize
    } else if i == KEY_MOUSE {
        Input::KeyMouse
    } else {
        assert!(
            i >= KEY_OFFSET,
            format!("Input value less than expected: {:?}", i)
        );
        let i = if i <= KEY_F15 {
            i - KEY_OFFSET
        } else {
            i - KEY_OFFSET - 48
        };
        if i as usize >= SPECIAL_KEY_CODES.len() {
            Input::Unknown(i)
        } else {
            SPECIAL_KEY_CODES[i as usize]
        }
    }
}

pub fn _ungetch(input: &Input) -> i32 {
    let i = convert_input_to_c_int(input);
    unsafe { PDC_ungetch(i) }
}

fn convert_input_to_c_int(input: &Input) -> c_int {
    match *input {
        Input::Character(c) => c as c_int,
        Input::Unknown(i) => i,
        Input::KeyResize => KEY_RESIZE,
        Input::KeyMouse => KEY_MOUSE,
        specialKeyCode => {
            for (i, skc) in SPECIAL_KEY_CODES.into_iter().enumerate() {
                if *skc == specialKeyCode {
                    let result = i as c_int + KEY_OFFSET;
                    if result <= KEY_F15 {
                        return result;
                    } else {
                        return result + 48;
                    }
                }
            }
            panic!("Failed to convert Input back to a c_int");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::convert_input_to_c_int;
    use input::Input;
    use libc::c_int;

    #[test]
    fn test_key_dl_to_special_keycode() {
        assert_eq!(Input::KeyDL, to_special_keycode(KEY_OFFSET + 0x48));
    }

    #[test]
    fn test_key_f15_to_input() {
        assert_eq!(Input::KeyF15, to_special_keycode(KEY_OFFSET + 0x08 + 15));
    }

    #[test]
    fn test_key_up_to_input() {
        assert_eq!(Input::KeyUp, to_special_keycode(KEY_OFFSET + 3));
    }

    #[test]
    fn test_convert_input_to_c_int() {
        let i = convert_input_to_c_int(&Input::Character('a'));
        assert_eq!('a' as c_int, i);
    }

    #[test]
    fn test_convert_backspace_to_c_int() {
        let i = convert_input_to_c_int(&Input::KeyBackspace);
        assert_eq!(KEY_OFFSET + 0x07, i);
    }

    #[test]
    fn test_convert_sdl_to_c_int() {
        let i = convert_input_to_c_int(&Input::KeySDL);
        assert_eq!(KEY_OFFSET + 0x7e, i);
    }

    #[test]
    fn test_convert_key_mouse() {
        let i = convert_input_to_c_int(&Input::KeyMouse);
        let kc = to_special_keycode(i);
        assert_eq!(i, convert_input_to_c_int(&kc));
    }
}
<|endoftext|>


<commit_before>use crypt32;
use std::io;
use std::mem;
use std::ptr;
use winapi;

use cert_context::CertContext;
use Inner;

pub struct CtlContext(winapi::PCCTL_CONTEXT);

impl Drop for CtlContext {
	fn drop(&mut self) {
		unsafe {
			crypt32::CertFreeCTLContext(self.0);
		}
	}
}

impl Inner<winapi::PCCTL_CONTEXT> for CtlContext {
	unsafe fn from_inner(t: winapi::PCCTL_CONTEXT) -> CtlContext {
		CtlContext(t)
	}

	fn as_inner(&self) -> winapi::PCCTL_CONTEXT {
		self.0
	}
}

impl CtlContext {
	pub fn builder() -> Builder {
		Builder {
			entries: vec![],
			usages: vec![],
		}
	}
}

pub struct Builder {
	entries: Vec<CtlEntry>,
	usages: Vec<Vec<u8>>,
}

impl Builder {
	pub fn entry(&mut self, entry: CtlEntry) -> &mut Builder {
		self.entries.push(entry);
		self
	}

	pub fn usage(&mut self, usage: &str) -> &mut Builder {
		let mut usage = usage.as_bytes().to_owned();
		usage.push(0);
		self.usages.push(usage);
		self
	}

	pub fn build(&self) -> io::Result<Vec<u8>> {
		unsafe {
			let encoding = winapi::X509_ASN_ENCODING | winapi::PKCS_7_ASN_ENCODING;

			let mut usages = self.usages.iter().map(|u| u.as_ptr()).collect::<Vec<_>>();
			let mut entries = self.entries.iter()
							      .map(|e| *(e.0.as_ptr() as *const winapi::CTL_ENTRY))
							      .collect::<Vec<_>>();

			let mut ctl_info: winapi::CTL_INFO = mem::zeroed();
			ctl_info.dwVersion = winapi::CTL_V1;
			ctl_info.SubjectUsage.cUsageIdentifier = usages.len() as winapi::DWORD;
			ctl_info.SubjectUsage.rgpszUsageIdentifier = usages.as_mut_ptr() as *mut winapi::LPSTR;
			let mut algorithm = winapi::szOID_OIWSEC_sha1.as_bytes().to_owned();
			algorithm.push(0);
			ctl_info.SubjectAlgorithm.pszObjId = algorithm.as_ptr() as winapi::LPSTR;
			ctl_info.cCTLEntry = entries.len() as winapi::DWORD;
			ctl_info.rgCTLEntry = entries.as_mut_ptr();

			let mut sign_info: winapi::CMSG_SIGNED_ENCODE_INFO = mem::zeroed();
			sign_info.cbSize = mem::size_of_val(&sign_info) as winapi::DWORD;

			let flags = winapi::CMSG_ENCODE_SORTED_CTL_FLAG |
				winapi::CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG;

			let mut size = 0;

			let res = crypt32::CryptMsgEncodeAndSignCTL(
				encoding,
				&mut ctl_info,
				&mut sign_info,
				flags,
				ptr::null_mut(),
				&mut size);
			if res == winapi::FALSE {
				return Err(io::Error::last_os_error());
			}

			let mut encoded = vec![0; size as usize];

			let res = crypt32::CryptMsgEncodeAndSignCTL(
				encoding,
				&mut ctl_info,
				&mut sign_info,
				flags,
				encoded.as_mut_ptr() as *mut winapi::BYTE,
				&mut size);
			if res == winapi::FALSE {
				return Err(io::Error::last_os_error());
			}

			Ok(encoded)
		}
	}
}

pub struct CtlEntry(Vec<u8>);

impl CtlEntry {
	pub fn from_certificate(cert: &mut CertContext) -> io::Result<CtlEntry> {
		unsafe {
			let mut size = 0;

			let res = crypt32::CertCreateCTLEntryFromCertificateContextProperties(
				cert.as_inner(),
				0,
				ptr::null_mut(),
				winapi::CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
				ptr::null_mut(),
				ptr::null_mut(),
				&mut size);
			if res == winapi::FALSE {
				return Err(io::Error::last_os_error());
			}

			let mut entry = vec![0; size as usize];
			let res = crypt32::CertCreateCTLEntryFromCertificateContextProperties(
				cert.as_inner(),
				0,
				ptr::null_mut(),
				winapi::CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
				ptr::null_mut(),
				entry.as_mut_ptr() as winapi::PCTL_ENTRY,
				&mut size);
			if res == winapi::FALSE {
				Err(io::Error::last_os_error())
			} else {
				Ok(CtlEntry(entry))
			}
		}
	}
}

#[cfg(test)]
mod test {
	use std::io::Read;
	use std::fs::File;
	use cert_store::CertStore;
	use ctl_context::{CtlContext, CtlEntry};

	#[test]
	fn create_ctl() {
        let mut file = File::open(concat!(env!("CARGO_MANIFEST_DIR"),
                                          "/test/self-signed.badssl.com.cer"))
                           .unwrap();
        let mut cert = vec![];
        file.read_to_end(&mut cert).unwrap();

        let mut store = CertStore::memory().unwrap();
        let mut cert = store.add_der_certificate(&cert).unwrap();

        let entry = CtlEntry::from_certificate(&mut cert).unwrap();
        CtlContext::builder()
            .entry(entry)
            .usage("1.3.6.1.4.1.311.2.2.2")
            .build()
            .unwrap();
	}
}<commit_msg>Restructure ctl creation<commit_after>use crypt32;
use std::io;
use std::mem;
use std::ptr;
use winapi;

use cert_context::CertContext;
use Inner;

pub struct CtlContext(winapi::PCCTL_CONTEXT);

impl Drop for CtlContext {
	fn drop(&mut self) {
		unsafe {
			crypt32::CertFreeCTLContext(self.0);
		}
	}
}

impl Inner<winapi::PCCTL_CONTEXT> for CtlContext {
	unsafe fn from_inner(t: winapi::PCCTL_CONTEXT) -> CtlContext {
		CtlContext(t)
	}

	fn as_inner(&self) -> winapi::PCCTL_CONTEXT {
		self.0
	}
}

impl CtlContext {
	pub fn builder() -> Builder {
		Builder {
			certificates: vec![],
			usages: vec![],
		}
	}
}

pub struct Builder {
	certificates: Vec<CertContext>,
	usages: Vec<Vec<u8>>,
}

impl Builder {
	pub fn certificate(&mut self, cert: CertContext) -> &mut Builder {
		self.certificates.push(cert);
		self
	}

	pub fn usage(&mut self, usage: &str) -> &mut Builder {
		let mut usage = usage.as_bytes().to_owned();
		usage.push(0);
		self.usages.push(usage);
		self
	}

	pub fn build(&self) -> io::Result<Vec<u8>> {
		unsafe {
			let encoding = winapi::X509_ASN_ENCODING | winapi::PKCS_7_ASN_ENCODING;

			let mut usages = self.usages.iter().map(|u| u.as_ptr()).collect::<Vec<_>>();
			let mut entry_data = vec![];
			let mut entries = vec![];
			for certificate in &self.certificates {
				let data = try!(cert_entry(certificate));
				entries.push(*(data.as_ptr() as *const winapi::CTL_ENTRY));
				entry_data.push(data);
			}

			let mut ctl_info: winapi::CTL_INFO = mem::zeroed();
			ctl_info.dwVersion = winapi::CTL_V1;
			ctl_info.SubjectUsage.cUsageIdentifier = usages.len() as winapi::DWORD;
			ctl_info.SubjectUsage.rgpszUsageIdentifier = usages.as_mut_ptr() as *mut winapi::LPSTR;
			let mut algorithm = winapi::szOID_OIWSEC_sha1.as_bytes().to_owned();
			algorithm.push(0);
			ctl_info.SubjectAlgorithm.pszObjId = algorithm.as_ptr() as winapi::LPSTR;
			ctl_info.cCTLEntry = entries.len() as winapi::DWORD;
			ctl_info.rgCTLEntry = entries.as_mut_ptr();

			let mut sign_info: winapi::CMSG_SIGNED_ENCODE_INFO = mem::zeroed();
			sign_info.cbSize = mem::size_of_val(&sign_info) as winapi::DWORD;
			let mut encoded_certs = self.certificates
										.iter()
										.map(|c| {
											winapi::CERT_BLOB {
												cbData: (*c.as_inner()).cbCertEncoded,
												pbData: (*c.as_inner()).pbCertEncoded,
											}
										})
										.collect::<Vec<_>>();
			sign_info.rgCertEncoded = encoded_certs.as_mut_ptr();
			sign_info.cCertEncoded = encoded_certs.len() as winapi::DWORD;

			let flags = winapi::CMSG_ENCODE_SORTED_CTL_FLAG |
				winapi::CMSG_ENCODE_HASHED_SUBJECT_IDENTIFIER_FLAG;

			let mut size = 0;

			let res = crypt32::CryptMsgEncodeAndSignCTL(
				encoding,
				&mut ctl_info,
				&mut sign_info,
				flags,
				ptr::null_mut(),
				&mut size);
			if res == winapi::FALSE {
				return Err(io::Error::last_os_error());
			}

			let mut encoded = vec![0; size as usize];

			let res = crypt32::CryptMsgEncodeAndSignCTL(
				encoding,
				&mut ctl_info,
				&mut sign_info,
				flags,
				encoded.as_mut_ptr() as *mut winapi::BYTE,
				&mut size);
			if res == winapi::FALSE {
				return Err(io::Error::last_os_error());
			}

			Ok(encoded)
		}
	}
}

fn cert_entry(cert: &CertContext) -> io::Result<Vec<u8>> {
	unsafe {
		let mut size = 0;

		let res = crypt32::CertCreateCTLEntryFromCertificateContextProperties(
			cert.as_inner(),
			0,
			ptr::null_mut(),
			winapi::CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
			ptr::null_mut(),
			ptr::null_mut(),
			&mut size);
		if res == winapi::FALSE {
			return Err(io::Error::last_os_error());
		}

		let mut entry = vec![0; size as usize];
		let res = crypt32::CertCreateCTLEntryFromCertificateContextProperties(
			cert.as_inner(),
			0,
			ptr::null_mut(),
			winapi::CTL_ENTRY_FROM_PROP_CHAIN_FLAG,
			ptr::null_mut(),
			entry.as_mut_ptr() as winapi::PCTL_ENTRY,
			&mut size);
		if res == winapi::FALSE {
			Err(io::Error::last_os_error())
		} else {
			Ok(entry)
		}
	}
}

#[cfg(test)]
mod test {
	use std::io::Read;
	use std::fs::File;
	use cert_store::CertStore;
	use ctl_context::CtlContext;

	#[test]
	fn create_ctl() {
        let mut file = File::open(concat!(env!("CARGO_MANIFEST_DIR"),
                                          "/test/self-signed.badssl.com.cer"))
                           .unwrap();
        let mut cert = vec![];
        file.read_to_end(&mut cert).unwrap();

        let mut store = CertStore::memory().unwrap();
        let cert = store.add_der_certificate(&cert).unwrap();

        CtlContext::builder()
        	.certificate(cert)
            .usage("1.3.6.1.4.1.311.2.2.2")
            .build()
            .unwrap();
	}
}<|endoftext|>


<commit_before>
//! The data (inner representation) traits for ndarray

use std::mem;
use std::rc::Rc;

use {
    ArrayBase,
    Dimension,
    ViewRepr,
};

/// Array’s inner representation.
///
/// ***Note:*** `Data` is not an extension interface at this point.
/// Traits in Rust can serve many different roles. This trait is public because
/// it is used as a bound on public methods.
pub unsafe trait Data {
    type Elem;
    fn slice(&self) -> &[Self::Elem];
}

/// Array’s writable inner representation.
pub unsafe trait DataMut : Data {
    fn slice_mut(&mut self) -> &mut [Self::Elem];
    #[inline]
    fn ensure_unique<D>(&mut ArrayBase<Self, D>)
        where Self: Sized,
              D: Dimension
    { }

    #[inline]
    fn is_unique(&mut self) -> bool {
        true
    }
}

/// Clone an Array’s storage.
pub unsafe trait DataClone : Data {
    /// Unsafe because, `ptr` must point inside the current storage.
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem);
}

unsafe impl Data for Rc<Vec> {
    type Elem = A;
    fn slice(&self) -> &[A] {
        self
    }
}

// NOTE: Copy on write
unsafe impl DataMut for Rc<Vec>
    where A: Clone
{
    fn slice_mut(&mut self) -> &mut [A] {
        &mut Rc::make_mut(self)[..]
    }

    fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
        where Self: Sized,
              D: Dimension
    {
        if Rc::get_mut(&mut self_.data).is_some() {
            return;
        }
        if self_.dim.size() <= self_.data.len() / 2 {
            // Create a new vec if the current view is less than half of
            // backing data.
            unsafe {
                *self_ = ArrayBase::from_vec_dim_unchecked(self_.dim.clone(),
                                                           self_.iter()
                                                            .cloned()
                                                            .collect());
            }
            return;
        }
        let our_off = (self_.ptr as isize - self_.data.as_ptr() as isize) /
                      mem::size_of::() as isize;
        let rvec = Rc::make_mut(&mut self_.data);
        unsafe {
            self_.ptr = rvec.as_mut_ptr().offset(our_off);
        }
    }

    fn is_unique(&mut self) -> bool {
        Rc::get_mut(self).is_some()
    }
}

unsafe impl DataClone for Rc<Vec> {
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        // pointer is preserved
        (self.clone(), ptr)
    }
}

unsafe impl Data for Vec {
    type Elem = A;
    fn slice(&self) -> &[A] {
        self
    }
}

unsafe impl DataMut for Vec {
    fn slice_mut(&mut self) -> &mut [A] {
        self
    }
}

unsafe impl DataClone for Vec
    where A: Clone
{
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        let mut u = self.clone();
        let our_off = (self.as_ptr() as isize - ptr as isize) /
                      mem::size_of::() as isize;
        let new_ptr = u.as_mut_ptr().offset(our_off);
        (u, new_ptr)
    }
}

unsafe impl<'a, A> Data for ViewRepr<&'a A> {
    type Elem = A;
    fn slice(&self) -> &[A] {
        &[]
    }
}

unsafe impl<'a, A> DataClone for ViewRepr<&'a A> {
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        (*self, ptr)
    }
}

unsafe impl<'a, A> Data for ViewRepr<&'a mut A> {
    type Elem = A;
    fn slice(&self) -> &[A] {
        &[]
    }
}

unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> {
    fn slice_mut(&mut self) -> &mut [A] {
        &mut []
    }
}

/// Array representation that is a unique or shared owner of its data.
pub unsafe trait DataOwned : Data {
    fn new(elements: Vec<Self::Elem>) -> Self;
    fn into_shared(self) -> Rc<Vec<Self::Elem>>;
}

/// Array representation that is a lightweight view.
pub unsafe trait DataShared : Clone + DataClone { }

unsafe impl DataShared for Rc<Vec> {}
unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {}

unsafe impl DataOwned for Vec {
    fn new(elements: Vec) -> Self {
        elements
    }
    fn into_shared(self) -> Rc<Vec> {
        Rc::new(self)
    }
}

unsafe impl DataOwned for Rc<Vec> {
    fn new(elements: Vec) -> Self {
        Rc::new(elements)
    }
    fn into_shared(self) -> Rc<Vec> {
        self
    }
}

<commit_msg>Edit docs for data traits<commit_after>
//! The data (inner representation) traits for ndarray

use std::mem;
use std::rc::Rc;

use {
    ArrayBase,
    Dimension,
    ViewRepr,
};

/// Array representation trait.
///
/// ***Note:*** `Data` is not an extension interface at this point.
/// Traits in Rust can serve many different roles. This trait is public because
/// it is used as a bound on public methods.
pub unsafe trait Data {
    /// The array element type.
    type Elem;
    #[doc(hidden)]
    fn slice(&self) -> &[Self::Elem];
}

/// Array representation trait.
///
/// For an array with writable elements.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataMut : Data {
    #[doc(hidden)]
    fn slice_mut(&mut self) -> &mut [Self::Elem];
    #[doc(hidden)]
    #[inline]
    fn ensure_unique<D>(&mut ArrayBase<Self, D>)
        where Self: Sized,
              D: Dimension
    { }

    #[doc(hidden)]
    #[inline]
    fn is_unique(&mut self) -> bool {
        true
    }
}

/// Array representation trait.
///
/// An array representation that can be cloned.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataClone : Data {
    #[doc(hidden)]
    /// Unsafe because, `ptr` must point inside the current storage.
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem);
}

unsafe impl Data for Rc<Vec> {
    type Elem = A;
    fn slice(&self) -> &[A] {
        self
    }
}

// NOTE: Copy on write
unsafe impl DataMut for Rc<Vec>
    where A: Clone
{
    fn slice_mut(&mut self) -> &mut [A] {
        &mut Rc::make_mut(self)[..]
    }

    fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
        where Self: Sized,
              D: Dimension
    {
        if Rc::get_mut(&mut self_.data).is_some() {
            return;
        }
        if self_.dim.size() <= self_.data.len() / 2 {
            // Create a new vec if the current view is less than half of
            // backing data.
            unsafe {
                *self_ = ArrayBase::from_vec_dim_unchecked(self_.dim.clone(),
                                                           self_.iter()
                                                            .cloned()
                                                            .collect());
            }
            return;
        }
        let our_off = (self_.ptr as isize - self_.data.as_ptr() as isize) /
                      mem::size_of::() as isize;
        let rvec = Rc::make_mut(&mut self_.data);
        unsafe {
            self_.ptr = rvec.as_mut_ptr().offset(our_off);
        }
    }

    fn is_unique(&mut self) -> bool {
        Rc::get_mut(self).is_some()
    }
}

unsafe impl DataClone for Rc<Vec> {
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        // pointer is preserved
        (self.clone(), ptr)
    }
}

unsafe impl Data for Vec {
    type Elem = A;
    fn slice(&self) -> &[A] {
        self
    }
}

unsafe impl DataMut for Vec {
    fn slice_mut(&mut self) -> &mut [A] {
        self
    }
}

unsafe impl DataClone for Vec
    where A: Clone
{
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        let mut u = self.clone();
        let our_off = (self.as_ptr() as isize - ptr as isize) /
                      mem::size_of::() as isize;
        let new_ptr = u.as_mut_ptr().offset(our_off);
        (u, new_ptr)
    }
}

unsafe impl<'a, A> Data for ViewRepr<&'a A> {
    type Elem = A;
    fn slice(&self) -> &[A] {
        &[]
    }
}

unsafe impl<'a, A> DataClone for ViewRepr<&'a A> {
    unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
        (*self, ptr)
    }
}

unsafe impl<'a, A> Data for ViewRepr<&'a mut A> {
    type Elem = A;
    fn slice(&self) -> &[A] {
        &[]
    }
}

unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> {
    fn slice_mut(&mut self) -> &mut [A] {
        &mut []
    }
}

/// Array representation trait.
///
/// A representation that is a unique or shared owner of its data.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataOwned : Data {
    #[doc(hidden)]
    fn new(elements: Vec<Self::Elem>) -> Self;
    #[doc(hidden)]
    fn into_shared(self) -> Rc<Vec<Self::Elem>>;
}

/// Array representation trait.
///
/// A representation that is a lightweight view.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataShared : Clone + DataClone { }

unsafe impl DataShared for Rc<Vec> {}
unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {}

unsafe impl DataOwned for Vec {
    fn new(elements: Vec) -> Self {
        elements
    }
    fn into_shared(self) -> Rc<Vec> {
        Rc::new(self)
    }
}

unsafe impl DataOwned for Rc<Vec> {
    fn new(elements: Vec) -> Self {
        Rc::new(elements)
    }
    fn into_shared(self) -> Rc<Vec> {
        self
    }
}

<|endoftext|>


<commit_before>//! Compiles JMESPath expressions.

extern crate rustc_serialize;

use std::io::Cursor;
use std::collections::BTreeMap;
use self::rustc_serialize::json::Json;

use ast::{Ast, Comparator, KeyValuePair};
use vm::Opcode;

pub fn compile_opcodes(ast: &Ast) -> Vec<Opcode> {
    let mut opcodes = compile_with_offset(&ast, 0);
    opcodes.push(Opcode::Halt);
    opcodes
}

fn compile_with_offset(ast: &Ast, offset: usize) -> Vec<Opcode> {
    let mut opcodes: Vec<Opcode> = Vec::new();
    match *ast {
        Ast::CurrentNode => opcodes.push(Opcode::Load(0)),
        Ast::Identifier(ref j) => opcodes.push(Opcode::Field(j.clone())),
        Ast::Index(i) => {
            if i < 0 {
                opcodes.push(Opcode::NegativeIndex((i.abs() - 1) as usize));
            } else {
                opcodes.push(Opcode::Index(i as usize));
            }
        },
        Ast::Or(ref lhs, ref rhs) => {
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*lhs, offset));
            opcodes.push(Opcode::Truthy);
            let next_offset = opcodes.len() + 1;
            let right = compile_with_offset(&*rhs, next_offset);
            opcodes.push(Opcode::Brt(next_offset + right.len()));
            opcodes = merge_opcodes(opcodes, right);
        },
        Ast::Subexpr(ref lhs, ref rhs) => {
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*lhs, offset));
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*rhs, offset));
        },
        Ast::Comparison(ref cmp, ref lhs, ref rhs) => {
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*lhs, offset));
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*rhs, offset));
            opcodes.push(match cmp {
                &Comparator::Lt => Opcode::Lt,
                &Comparator::Lte => Opcode::Lte,
                &Comparator::Gt => Opcode::Gt,
                &Comparator::Gte => Opcode::Gte,
                &Comparator::Eq => Opcode::Eq,
                &Comparator::Ne => Opcode::Ne,
            });
        },
        _ => panic!("not implemented yet!")
    };
    opcodes
}

fn merge_opcodes(mut a: Vec<Opcode>, b: Vec<Opcode>) -> Vec<Opcode> {
    for opcode in b {
        a.push(opcode);
    }
    a
}

#[cfg(test)]
mod test {
    extern crate rustc_serialize;
    use self::rustc_serialize::json::Json;
    use super::*;
    use ast::{Ast, Comparator};
    use vm::Opcode;

    #[test] fn assembles_identifiers() {
        let ast = Ast::Identifier("foo".to_owned());
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::Field("foo".to_owned()), Opcode::Halt], opcodes);
    }

    #[test] fn assembles_positive_index() {
        let ast = Ast::Index(1);
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::Index(1), Opcode::Halt], opcodes);
    }

    #[test] fn assembles_negative_index() {
        let ast = Ast::Index(-2);
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::NegativeIndex(1), Opcode::Halt], opcodes);
    }

    #[test] fn assembles_or_expression() {
        let ast = Ast::Or(
            Box::new(Ast::Identifier("foo".to_owned())),
            Box::new(Ast::Identifier("bar".to_owned())));
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::Field("foo".to_owned()),
                        Opcode::Truthy,
                        Opcode::Brt(4),
                        Opcode::Field("bar".to_owned()),
                        Opcode::Halt],
                   opcodes);
    }

    #[test] fn assembles_current_node() {
        let ast = Ast::CurrentNode;
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::Load(0), Opcode::Halt], opcodes);
    }

    #[test] fn assembles_eq_comparison() {
        let tests = vec![(Comparator::Lt, Opcode::Lt),
                         (Comparator::Lte, Opcode::Lte),
                         (Comparator::Gt, Opcode::Gt),
                         (Comparator::Gte, Opcode::Gte),
                         (Comparator::Eq, Opcode::Eq),
                         (Comparator::Ne, Opcode::Ne)];
        for (cmp, op) in tests {
            let ast = Ast::Comparison(
                cmp,
                Box::new(Ast::Identifier("foo".to_string())),
                Box::new(Ast::Identifier("bar".to_string())));
            let opcodes = compile_opcodes(&ast);
            assert_eq!(vec![Opcode::Field("foo".to_string()),
                            Opcode::Field("bar".to_string()),
                            op,
                            Opcode::Halt], opcodes);
        }
    }
}
<commit_msg>Adding condition and literal compiling<commit_after>//! Compiles JMESPath expressions.

extern crate rustc_serialize;

use std::io::Cursor;
use std::collections::BTreeMap;
use self::rustc_serialize::json::Json;

use ast::{Ast, Comparator, KeyValuePair};
use vm::Opcode;

pub fn compile_opcodes(ast: &Ast) -> Vec<Opcode> {
    let mut opcodes = compile_with_offset(&ast, 0);
    opcodes.push(Opcode::Halt);
    opcodes
}

fn compile_with_offset(ast: &Ast, offset: usize) -> Vec<Opcode> {
    let mut opcodes: Vec<Opcode> = Vec::new();
    match *ast {
        Ast::CurrentNode => opcodes.push(Opcode::Load(0)),
        Ast::Identifier(ref j) => opcodes.push(Opcode::Field(j.clone())),
        Ast::Index(i) => {
            if i < 0 {
                opcodes.push(Opcode::NegativeIndex((i.abs() - 1) as usize));
            } else {
                opcodes.push(Opcode::Index(i as usize));
            }
        },
        Ast::Or(ref lhs, ref rhs) => {
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*lhs, offset));
            opcodes.push(Opcode::Truthy);
            let next_offset = opcodes.len() + 1;
            let right = compile_with_offset(&*rhs, next_offset);
            opcodes.push(Opcode::Brt(next_offset + right.len()));
            opcodes = merge_opcodes(opcodes, right);
        },
        Ast::Subexpr(ref lhs, ref rhs) => {
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*lhs, offset));
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*rhs, offset));
        },
        Ast::Comparison(ref cmp, ref lhs, ref rhs) => {
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*lhs, offset));
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*rhs, offset));
            opcodes.push(match cmp {
                &Comparator::Lt => Opcode::Lt,
                &Comparator::Lte => Opcode::Lte,
                &Comparator::Gt => Opcode::Gt,
                &Comparator::Gte => Opcode::Gte,
                &Comparator::Eq => Opcode::Eq,
                &Comparator::Ne => Opcode::Ne,
            });
        },
        Ast::Condition(ref lhs, ref rhs) => {
            opcodes = merge_opcodes(opcodes, compile_with_offset(&*lhs, offset));
            opcodes.push(Opcode::Push(Json::Boolean(true)));
            opcodes.push(Opcode::Eq);
            let next_offset = opcodes.len() + 1;
            let right = compile_with_offset(&*rhs, next_offset);
            opcodes.push(Opcode::Brf(next_offset + right.len() + 1));
            opcodes = merge_opcodes(opcodes, right);
            let next_offset = opcodes.len() + 2;
            opcodes.push(Opcode::Br(next_offset));
            opcodes.push(Opcode::Push(Json::Null));
        },
        Ast::Literal(ref json) => opcodes.push(Opcode::Push(json.clone())),
        _ => panic!("not implemented yet!")
    };
    opcodes
}

fn merge_opcodes(mut a: Vec<Opcode>, b: Vec<Opcode>) -> Vec<Opcode> {
    for opcode in b {
        a.push(opcode);
    }
    a
}

#[cfg(test)]
mod test {
    extern crate rustc_serialize;
    use self::rustc_serialize::json::Json;
    use super::*;
    use ast::{Ast, Comparator};
    use vm::Opcode;

    #[test] fn assembles_identifiers() {
        let ast = Ast::Identifier("foo".to_owned());
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::Field("foo".to_owned()), Opcode::Halt], opcodes);
    }

    #[test] fn assembles_positive_index() {
        let ast = Ast::Index(1);
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::Index(1), Opcode::Halt], opcodes);
    }

    #[test] fn assembles_negative_index() {
        let ast = Ast::Index(-2);
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::NegativeIndex(1), Opcode::Halt], opcodes);
    }

    #[test] fn assembles_or_expression() {
        let ast = Ast::Or(
            Box::new(Ast::Identifier("foo".to_owned())),
            Box::new(Ast::Identifier("bar".to_owned())));
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::Field("foo".to_owned()),
                        Opcode::Truthy,
                        Opcode::Brt(4),
                        Opcode::Field("bar".to_owned()),
                        Opcode::Halt],
                   opcodes);
    }

    #[test] fn assembles_current_node() {
        let ast = Ast::CurrentNode;
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::Load(0), Opcode::Halt], opcodes);
    }

    #[test] fn assembles_eq_comparison() {
        let tests = vec![(Comparator::Lt, Opcode::Lt),
                         (Comparator::Lte, Opcode::Lte),
                         (Comparator::Gt, Opcode::Gt),
                         (Comparator::Gte, Opcode::Gte),
                         (Comparator::Eq, Opcode::Eq),
                         (Comparator::Ne, Opcode::Ne)];
        for (cmp, op) in tests {
            let ast = Ast::Comparison(
                cmp,
                Box::new(Ast::Identifier("foo".to_string())),
                Box::new(Ast::Identifier("bar".to_string())));
            let opcodes = compile_opcodes(&ast);
            assert_eq!(vec![Opcode::Field("foo".to_string()),
                            Opcode::Field("bar".to_string()),
                            op,
                            Opcode::Halt], opcodes);
        }
    }

    #[test] fn assembles_conditions() {
        let ast = Ast::Condition(
            Box::new(Ast::Literal(Json::Boolean(true))),
            Box::new(Ast::Identifier("bar".to_owned())));
        let opcodes = compile_opcodes(&ast);
        assert_eq!(vec![Opcode::Push(Json::Boolean(true)),
                        Opcode::Push(Json::Boolean(true)),
                        Opcode::Eq,
                        Opcode::Brf(6),
                        Opcode::Field("bar".to_owned()),
                        Opcode::Br(7),
                        Opcode::Push(Json::Null),
                        Opcode::Halt],
                   opcodes);
    }
}
<|endoftext|>


<commit_before>use crate::{sys, Token};

use std::fmt;

/// A readiness event.
///
/// `Event` is a readiness state paired with a [`Token`]. It is returned by
/// [`Poll::poll`].
///
/// For more documentation on polling and events, see [`Poll`].
///
/// [`Poll::poll`]: ../struct.Poll.html#method.poll
/// [`Poll`]: ../struct.Poll.html
/// [`Token`]: ../struct.Token.html
#[repr(transparent)]
pub struct Event {
    inner: sys::Event,
}

impl Event {
    /// Returns the event's token.
    #[inline]
    pub fn token(&self) -> Token {
        sys::event::token(&self.inner)
    }

    /// Returns true if the event contains readable readiness.
    #[inline]
    pub fn is_readable(&self) -> bool {
        sys::event::is_readable(&self.inner)
    }

    /// Returns true if the event contains writable readiness.
    #[inline]
    pub fn is_writable(&self) -> bool {
        sys::event::is_writable(&self.inner)
    }

    /// Returns true if the event contains error readiness.
    ///
    /// Error events occur when the socket enters an error state. In this case,
    /// the socket will also receive a readable or writable event. Reading or
    /// writing to the socket will result in an error.
    ///
    /// # Notes
    ///
    /// Method is available on all platforms, but not all platforms trigger the
    /// error event.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | `EPOLLERR`      |
    /// | [kqueue]      | `EV_ERROR` and `EV_EOF` with `fflags` set to `0`. |
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    #[inline]
    pub fn is_error(&self) -> bool {
        sys::event::is_error(&self.inner)
    }

    /// Returns true if the event contains read closed readiness.
    ///
    /// # Notes
    ///
    /// Read closed readiness can be expected after any of the following have
    /// occurred:
    /// * The local stream has shutdown the read half of its socket
    /// * The local stream has shtudown both the read half and the write half
    ///   of its socket
    /// * The peer stream has shtudown the write half its socket; this sends a
    ///   `FIN` packet that has been received by the local stream
    ///
    /// Method is a best effort implementation. While some platforms may not
    /// return readiness when read half is closed, it is guaranteed that
    /// false-positives will not occur.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | `EPOLLHUP`, or  |
    /// |               | `EPOLLIN` and EPOLLRDHUP` |
    /// | [kqueue]      | `EV_EOF`        |
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    #[inline]
    pub fn is_read_closed(&self) -> bool {
        sys::event::is_read_closed(&self.inner)
    }

    /// Returns true if the event contains write closed readiness.
    ///
    /// # Notes
    ///
    /// On [epoll] this is essentially a check for `EPOLLHUP` flag as the
    /// local stream shutting down its write half does not trigger this event.
    ///
    /// On [kqueue] the local stream shutting down the write half of its
    /// socket will trigger this event.
    ///
    /// Method is a best effort implementation. While some platforms may not
    /// return readiness when write half is closed, it is guaranteed that
    /// false-positives will not occur.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | `EPOLLHUP`, or  |
    /// |               | `EPOLLOUT` and `EPOLLERR` |
    /// | [kqueue]      | `EV_EOF`        |
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    pub fn is_write_closed(&self) -> bool {
        sys::event::is_write_closed(&self.inner)
    }

    /// Returns true if the event contains priority readiness.
    ///
    /// # Notes
    ///
    /// Method is available on all platforms, but not all platforms trigger the
    /// priority event.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | `EPOLLPRI`      |
    /// | [kqueue]      | *Not supported* |
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    #[inline]
    pub fn is_priority(&self) -> bool {
        sys::event::is_priority(&self.inner)
    }

    /// Returns true if the event contains AIO readiness.
    ///
    /// # Notes
    ///
    /// Method is available on all platforms, but not all platforms support AIO.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | *Not supported* |
    /// | [kqueue]1 | `EVFILT_AIO` |
    ///
    /// 1: Only supported on DragonFly BSD, FreeBSD, iOS and macOS.
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    #[inline]
    pub fn is_aio(&self) -> bool {
        sys::event::is_aio(&self.inner)
    }

    /// Returns true if the event contains LIO readiness.
    ///
    /// # Notes
    ///
    /// Method is available on all platforms, but only FreeBSD supports LIO. On
    /// FreeBSD this method checks the `EVFILT_LIO` flag.
    #[inline]
    pub fn is_lio(&self) -> bool {
        sys::event::is_lio(&self.inner)
    }

    /// Create a reference to an `Event` from a platform specific event.
    pub(crate) fn from_sys_event_ref(sys_event: &sys::Event) -> &Event {
        unsafe {
            // This is safe because the memory layout of `Event` is
            // the same as `sys::Event` due to the `repr(transparent)` attribute.
            &*(sys_event as *const sys::Event as *const Event)
        }
    }
}

/// When the [alternate] flag is enabled this will print platform specific
/// details, for example the fields of the `kevent` structure on platforms that
/// use `kqueue(2)`. Note however that the output of this implementation is
/// **not** consider a part of the stable API.
///
/// [alternate]: fmt::Formatter::alternate
impl fmt::Debug for Event {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let alternate = f.alternate();
        let mut d = f.debug_struct("Event");
        d.field("token", &self.token())
            .field("readable", &self.is_readable())
            .field("writable", &self.is_writable())
            .field("error", &self.is_error())
            .field("read_closed", &self.is_read_closed())
            .field("write_closed", &self.is_write_closed())
            .field("priority", &self.is_priority())
            .field("aio", &self.is_aio())
            .field("lio", &self.is_lio());

        if alternate {
            struct EventDetails<'a>(&'a sys::Event);

            impl<'a> fmt::Debug for EventDetails<'a> {
                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                    sys::event::debug_details(f, self.0)
                }
            }

            d.field("details", &EventDetails(&self.inner)).finish()
        } else {
            d.finish()
        }
    }
}
<commit_msg>Remove inline attributes from Event methods<commit_after>use crate::{sys, Token};

use std::fmt;

/// A readiness event.
///
/// `Event` is a readiness state paired with a [`Token`]. It is returned by
/// [`Poll::poll`].
///
/// For more documentation on polling and events, see [`Poll`].
///
/// [`Poll::poll`]: ../struct.Poll.html#method.poll
/// [`Poll`]: ../struct.Poll.html
/// [`Token`]: ../struct.Token.html
#[repr(transparent)]
pub struct Event {
    inner: sys::Event,
}

impl Event {
    /// Returns the event's token.
    pub fn token(&self) -> Token {
        sys::event::token(&self.inner)
    }

    /// Returns true if the event contains readable readiness.
    pub fn is_readable(&self) -> bool {
        sys::event::is_readable(&self.inner)
    }

    /// Returns true if the event contains writable readiness.
    pub fn is_writable(&self) -> bool {
        sys::event::is_writable(&self.inner)
    }

    /// Returns true if the event contains error readiness.
    ///
    /// Error events occur when the socket enters an error state. In this case,
    /// the socket will also receive a readable or writable event. Reading or
    /// writing to the socket will result in an error.
    ///
    /// # Notes
    ///
    /// Method is available on all platforms, but not all platforms trigger the
    /// error event.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | `EPOLLERR`      |
    /// | [kqueue]      | `EV_ERROR` and `EV_EOF` with `fflags` set to `0`. |
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    pub fn is_error(&self) -> bool {
        sys::event::is_error(&self.inner)
    }

    /// Returns true if the event contains read closed readiness.
    ///
    /// # Notes
    ///
    /// Read closed readiness can be expected after any of the following have
    /// occurred:
    /// * The local stream has shutdown the read half of its socket
    /// * The local stream has shtudown both the read half and the write half
    ///   of its socket
    /// * The peer stream has shtudown the write half its socket; this sends a
    ///   `FIN` packet that has been received by the local stream
    ///
    /// Method is a best effort implementation. While some platforms may not
    /// return readiness when read half is closed, it is guaranteed that
    /// false-positives will not occur.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | `EPOLLHUP`, or  |
    /// |               | `EPOLLIN` and EPOLLRDHUP` |
    /// | [kqueue]      | `EV_EOF`        |
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    pub fn is_read_closed(&self) -> bool {
        sys::event::is_read_closed(&self.inner)
    }

    /// Returns true if the event contains write closed readiness.
    ///
    /// # Notes
    ///
    /// On [epoll] this is essentially a check for `EPOLLHUP` flag as the
    /// local stream shutting down its write half does not trigger this event.
    ///
    /// On [kqueue] the local stream shutting down the write half of its
    /// socket will trigger this event.
    ///
    /// Method is a best effort implementation. While some platforms may not
    /// return readiness when write half is closed, it is guaranteed that
    /// false-positives will not occur.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | `EPOLLHUP`, or  |
    /// |               | `EPOLLOUT` and `EPOLLERR` |
    /// | [kqueue]      | `EV_EOF`        |
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    pub fn is_write_closed(&self) -> bool {
        sys::event::is_write_closed(&self.inner)
    }

    /// Returns true if the event contains priority readiness.
    ///
    /// # Notes
    ///
    /// Method is available on all platforms, but not all platforms trigger the
    /// priority event.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | `EPOLLPRI`      |
    /// | [kqueue]      | *Not supported* |
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    #[inline]
    pub fn is_priority(&self) -> bool {
        sys::event::is_priority(&self.inner)
    }

    /// Returns true if the event contains AIO readiness.
    ///
    /// # Notes
    ///
    /// Method is available on all platforms, but not all platforms support AIO.
    ///
    /// The table below shows what flags are checked on what OS.
    ///
    /// | [OS selector] | Flag(s) checked |
    /// |---------------|-----------------|
    /// | [epoll]       | *Not supported* |
    /// | [kqueue]1 | `EVFILT_AIO` |
    ///
    /// 1: Only supported on DragonFly BSD, FreeBSD, iOS and macOS.
    ///
    /// [OS selector]: ../struct.Poll.html#implementation-notes
    /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html
    /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
    pub fn is_aio(&self) -> bool {
        sys::event::is_aio(&self.inner)
    }

    /// Returns true if the event contains LIO readiness.
    ///
    /// # Notes
    ///
    /// Method is available on all platforms, but only FreeBSD supports LIO. On
    /// FreeBSD this method checks the `EVFILT_LIO` flag.
    pub fn is_lio(&self) -> bool {
        sys::event::is_lio(&self.inner)
    }

    /// Create a reference to an `Event` from a platform specific event.
    pub(crate) fn from_sys_event_ref(sys_event: &sys::Event) -> &Event {
        unsafe {
            // This is safe because the memory layout of `Event` is
            // the same as `sys::Event` due to the `repr(transparent)` attribute.
            &*(sys_event as *const sys::Event as *const Event)
        }
    }
}

/// When the [alternate] flag is enabled this will print platform specific
/// details, for example the fields of the `kevent` structure on platforms that
/// use `kqueue(2)`. Note however that the output of this implementation is
/// **not** consider a part of the stable API.
///
/// [alternate]: fmt::Formatter::alternate
impl fmt::Debug for Event {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let alternate = f.alternate();
        let mut d = f.debug_struct("Event");
        d.field("token", &self.token())
            .field("readable", &self.is_readable())
            .field("writable", &self.is_writable())
            .field("error", &self.is_error())
            .field("read_closed", &self.is_read_closed())
            .field("write_closed", &self.is_write_closed())
            .field("priority", &self.is_priority())
            .field("aio", &self.is_aio())
            .field("lio", &self.is_lio());

        if alternate {
            struct EventDetails<'a>(&'a sys::Event);

            impl<'a> fmt::Debug for EventDetails<'a> {
                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                    sys::event::debug_details(f, self.0)
                }
            }

            d.field("details", &EventDetails(&self.inner)).finish()
        } else {
            d.finish()
        }
    }
}
<|endoftext|>


<commit_before>use std::ptr::null;
use std::str::raw;
use libc::{c_int, c_char, c_double};
use sync::mutex::{StaticMutex, MUTEX_INIT};

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *c_char, bUpdate: c_int, pahDriverList: *()) -> *();
    fn OGR_DS_GetLayerCount(hDS: *()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *());
    fn OGR_DS_GetLayer(hDS: *(), iLayer: c_int) -> *();
    fn OGR_L_GetNextFeature(hLayer: *()) -> *();
    fn OGR_F_GetFieldIndex(hFeat: *(), pszName: *c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *(), i: c_int) -> *();
    fn OGR_F_GetFieldAsString(hFeat: *(), iField: c_int) -> *c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *(), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *()) -> *();
    fn OGR_F_Destroy(hFeat: *());
    fn OGR_G_ExportToWkt(hGeom: *(), ppszSrcText: **c_char) -> c_int;
    fn OGR_Fld_GetType(hDefn: *()) -> c_int;
    fn OGRFree(ptr: *());
}

static OFTInteger:        c_int = 0;
static OFTIntegerList:    c_int = 1;
static OFTReal:           c_int = 2;
static OFTRealList:       c_int = 3;
static OFTString:         c_int = 4;
static OFTStringList:     c_int = 5;
static OFTWideString:     c_int = 6;
static OFTWideStringList: c_int = 7;
static OFTBinary:         c_int = 8;
static OFTDate:           c_int = 9;
static OFTTime:           c_int = 10;
static OFTDateTime:       c_int = 11;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

pub enum FieldValue {
    StringValue(String),
    F64Value(f64),
}

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *(),
}

impl VectorDataset {
    pub fn get_layer_count(&self) -> int {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as int;
    }

    pub fn get_layer<'a>(&'a self, idx: int) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    vector_dataset: &'a VectorDataset,
    c_layer: *(),
}

impl<'a> Layer<'a> {
    pub fn features<'a>(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator<Feature<'a>> for FeatureIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    layer: &'a Layer<'a>,
    c_feature: *(),
}

impl<'a> Feature<'a> {
    pub fn get_field(&self, name: String) -> FieldValue {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFTString => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return StringValue(raw::from_c_str(rv));
                },
                OFTReal => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return F64Value(rv as f64);
                },
                _ => fail!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn get_string_field(&self, name: String) -> String {
        return match self.get_field(name) {
            StringValue(rv) => rv,
            _ => fail!("not a string")
        }
    }

    pub fn get_f64_field(&self, name: String) -> f64 {
        return match self.get_field(name) {
            F64Value(rv) => rv,
            _ => fail!("not an f64")
        }
    }

    pub fn get_wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = raw::from_c_str(c_wkt);
            OGRFree(c_wkt as *());
            return wkt;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

#[cfg(test)]
mod test {
    use std::os::getenv;
    use std::path::Path;
    use super::{Feature, open};

    fn fixture_path(name: &str) -> Path {
        let envvar = "RUST_GDAL_TEST_FIXTURES";
        let fixtures = match getenv(envvar) {
            Some(p) => Path::new(p),
            None => fail!("Environment variable {} not set", envvar)
        };
        let rv = fixtures.join(name);
        return rv;
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        assert_eq!(ds.get_layer_count(), 1);
    }

    #[test]
    fn test_iterate_features() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let features: Vec<Feature> = layer.features().collect();
        assert_eq!(features.len(), 21);
    }

    #[test]
    fn test_get_string_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert_eq!(feature.get_string_field("highway".to_string()),
                   "footway".to_string());
        assert_eq!(
            layer.features()
                 .count(|f|
                    f.get_string_field("highway".to_string()) ==
                    "residential".to_string()),
            2);
    }

    #[test]
    fn test_get_float_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert_almost_eq(feature.get_f64_field("sort_key".to_string()), -9.0);
    }

    #[test]
    fn test_get_wkt() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        let wkt = feature.get_wkt();
        assert_eq!(wkt, "LINESTRING (26.1019276 44.4302748,26.1019382 44.4303191,26.1020002 44.4304202)".to_string());
    }
}
<commit_msg>return None if the field is missing<commit_after>use std::ptr::null;
use std::str::raw;
use libc::{c_int, c_char, c_double};
use sync::mutex::{StaticMutex, MUTEX_INIT};

#[link(name="gdal")]
extern {
    fn OGRRegisterAll();
    fn OGROpen(pszName: *c_char, bUpdate: c_int, pahDriverList: *()) -> *();
    fn OGR_DS_GetLayerCount(hDS: *()) -> c_int;
    fn OGR_DS_Destroy(hDataSource: *());
    fn OGR_DS_GetLayer(hDS: *(), iLayer: c_int) -> *();
    fn OGR_L_GetNextFeature(hLayer: *()) -> *();
    fn OGR_F_GetFieldIndex(hFeat: *(), pszName: *c_char) -> c_int;
    fn OGR_F_GetFieldDefnRef(hFeat: *(), i: c_int) -> *();
    fn OGR_F_GetFieldAsString(hFeat: *(), iField: c_int) -> *c_char;
    fn OGR_F_GetFieldAsDouble(hFeat: *(), iField: c_int) -> c_double;
    fn OGR_F_GetGeometryRef(hFeat: *()) -> *();
    fn OGR_F_Destroy(hFeat: *());
    fn OGR_G_ExportToWkt(hGeom: *(), ppszSrcText: **c_char) -> c_int;
    fn OGR_Fld_GetType(hDefn: *()) -> c_int;
    fn OGRFree(ptr: *());
}

static OFTInteger:        c_int = 0;
static OFTIntegerList:    c_int = 1;
static OFTReal:           c_int = 2;
static OFTRealList:       c_int = 3;
static OFTString:         c_int = 4;
static OFTStringList:     c_int = 5;
static OFTWideString:     c_int = 6;
static OFTWideStringList: c_int = 7;
static OFTBinary:         c_int = 8;
static OFTDate:           c_int = 9;
static OFTTime:           c_int = 10;
static OFTDateTime:       c_int = 11;

static mut LOCK: StaticMutex = MUTEX_INIT;
static mut registered_drivers: bool = false;

pub enum FieldValue {
    StringValue(String),
    F64Value(f64),
}

fn register_drivers() {
    unsafe {
        let _g = LOCK.lock();
        if ! registered_drivers {
            OGRRegisterAll();
            registered_drivers = true;
        }
    }
}

pub struct VectorDataset {
    c_dataset: *(),
}

impl VectorDataset {
    pub fn get_layer_count(&self) -> int {
        return unsafe { OGR_DS_GetLayerCount(self.c_dataset) } as int;
    }

    pub fn get_layer<'a>(&'a self, idx: int) -> Option<Layer<'a>> {
        let c_layer = unsafe { OGR_DS_GetLayer(self.c_dataset, idx as c_int) };
        return match c_layer.is_null() {
            true  => None,
            false => Some(Layer{vector_dataset: self, c_layer: c_layer}),
        };
    }
}

impl Drop for VectorDataset {
    fn drop(&mut self) {
        unsafe { OGR_DS_Destroy(self.c_dataset); }
    }
}

pub struct Layer<'a> {
    vector_dataset: &'a VectorDataset,
    c_layer: *(),
}

impl<'a> Layer<'a> {
    pub fn features<'a>(&'a self) -> FeatureIterator<'a> {
        return FeatureIterator{layer: self};
    }
}

pub struct FeatureIterator<'a> {
    layer: &'a Layer<'a>,
}

impl<'a> Iterator<Feature<'a>> for FeatureIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<Feature<'a>> {
        let c_feature = unsafe { OGR_L_GetNextFeature(self.layer.c_layer) };
        return match c_feature.is_null() {
            true  => None,
            false => Some(Feature{layer: self.layer, c_feature: c_feature}),
        };
    }
}

pub struct Feature<'a> {
    layer: &'a Layer<'a>,
    c_feature: *(),
}

impl<'a> Feature<'a> {
    pub fn get_field(&self, name: String) -> Option<FieldValue> {
        return name.with_c_str(|c_name| unsafe {
            let field_id = OGR_F_GetFieldIndex(self.c_feature, c_name);
            if field_id == -1 {
                return None;
            }
            let field_defn = OGR_F_GetFieldDefnRef(self.c_feature, field_id);
            let field_type = OGR_Fld_GetType(field_defn);
            return match field_type {
                OFTString => {
                    let rv = OGR_F_GetFieldAsString(self.c_feature, field_id);
                    return Some(StringValue(raw::from_c_str(rv)));
                },
                OFTReal => {
                    let rv = OGR_F_GetFieldAsDouble(self.c_feature, field_id);
                    return Some(F64Value(rv as f64));
                },
                _ => fail!("Unknown field type {}", field_type)
            }
        });
    }

    pub fn get_string_field(&self, name: String) -> String {
        return match self.get_field(name) {
            Some(StringValue(rv)) => rv,
            _ => fail!("not a string")
        }
    }

    pub fn get_f64_field(&self, name: String) -> f64 {
        return match self.get_field(name) {
            Some(F64Value(rv)) => rv,
            _ => fail!("not an f64")
        }
    }

    pub fn get_wkt(&self) -> String {
        unsafe {
            let c_geom = OGR_F_GetGeometryRef(self.c_feature);
            let c_wkt: *c_char = null();
            OGR_G_ExportToWkt(c_geom, &c_wkt);
            let wkt = raw::from_c_str(c_wkt);
            OGRFree(c_wkt as *());
            return wkt;
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Feature<'a> {
    fn drop(&mut self) {
        unsafe { OGR_F_Destroy(self.c_feature); }
    }
}

pub fn open(path: &Path) -> Option<VectorDataset> {
    register_drivers();
    let filename = path.as_str().unwrap();
    let c_dataset = filename.with_c_str(|c_filename| {
        return unsafe { OGROpen(c_filename, 0, null()) };
    });
    return match c_dataset.is_null() {
        true  => None,
        false => Some(VectorDataset{c_dataset: c_dataset}),
    };
}

#[cfg(test)]
mod test {
    use std::os::getenv;
    use std::path::Path;
    use super::{Feature, open};

    fn fixture_path(name: &str) -> Path {
        let envvar = "RUST_GDAL_TEST_FIXTURES";
        let fixtures = match getenv(envvar) {
            Some(p) => Path::new(p),
            None => fail!("Environment variable {} not set", envvar)
        };
        let rv = fixtures.join(name);
        return rv;
    }

    fn assert_almost_eq(a: f64, b: f64) {
        let f: f64 = a / b;
        assert!(f < 1.00001);
        assert!(f > 0.99999);
    }

    #[test]
    fn test_layer_count() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        assert_eq!(ds.get_layer_count(), 1);
    }

    #[test]
    fn test_iterate_features() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let features: Vec<Feature> = layer.features().collect();
        assert_eq!(features.len(), 21);
    }

    #[test]
    fn test_get_string_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert_eq!(feature.get_string_field("highway".to_string()),
                   "footway".to_string());
        assert_eq!(
            layer.features()
                 .count(|f|
                    f.get_string_field("highway".to_string()) ==
                    "residential".to_string()),
            2);
    }

    #[test]
    fn test_get_float_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert_almost_eq(feature.get_f64_field("sort_key".to_string()), -9.0);
    }

    #[test]
    fn test_get_missing_field() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        assert!(feature.get_field("no such field".to_string()).is_none());
    }

    #[test]
    fn test_get_wkt() {
        let ds = open(&fixture_path("roads.geojson")).unwrap();
        let layer = ds.get_layer(0).unwrap();
        let feature = layer.features().next().unwrap();
        let wkt = feature.get_wkt();
        assert_eq!(wkt, "LINESTRING (26.1019276 44.4302748,26.1019382 44.4303191,26.1020002 44.4304202)".to_string());
    }
}
<|endoftext|>