<commit_before>#![feature(libc)]
#![feature(core)]
#![feature(hash)]

/*!
 * The ```ladspa``` crate provides an interface for writing [LADSPA](http://www.ladspa.org/)
 * plugins safely in Rust.
 *
 * ##Creating the project
 *
 * Run ```cargo new my_ladspa_plugin``` to generate a Cargo project for your plugin, then add
 * the following to the generated Cargo.toml:
 *
 * ```
 * [dependencies]
 * ladspa = "*"
 *
 * [lib]
 * name = "my_ladspa_plugin"
 * crate-type = ["dylib"]
 * ```
 * This will pull in the correct dependency and ensure that the library generated when you build
 * your plugin is compatible with LADSPA hosts.
 *
 * ## Writing the code
 * You'll want to implement
 * ```get_ladspa_descriptor``` in your src/lib.rs. This function is expected to return 1 or more
 * ```PluginDescriptor```s describing the plugins exposed by your library. See the documentation
 * for ```get_ladspa_descriptor``` and the examples [on Github](dead_link) for more information.
 *
 * ## Testing it out
 * There is a list of host software supporting LADSPA on the
 * [LADSPA home page](http://www.ladspa.org/). In order for a host to find your plugin, you will
 * either need to copy the *.so file from target/ after building to /usr/lib/ladspa/ (on most
 * systems, it may be different on your system) or set the enviornment variable ```LADSPA_PATH```
 * to equal the directory where you store your plugins.
 */

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

mod ffi;

pub use ffi::ladspa_descriptor;

use std::cell::{RefCell, RefMut};

#[allow(improper_ctypes)]
extern {
    /**
     * Your plugin must implement this function.
     * ```get_ladspa_descriptor``` returns a description of a supported plugin for a given plugin
     * index. When the index is out of bounds for the number of plugins supported by your library,
     * you are expected to return ```None```.
     *
     * Example no-op implementation:
     *
     * ```rust{.ignore}
     * #[no_mangle]
     * pub extern fn get_ladspa_descriptor(index: u64) -> Option<ladspa::PluginDescriptor> {
     *     None
     * }
     * ```
     */
    pub fn get_ladspa_descriptor(index: u64) -> Option<PluginDescriptor>;
}

/// The data type used internally by LADSPA for audio and control ports.
pub type Data = f32;

/// Describes the properties of a ```Plugin``` to be exposed as a LADSPA plugin.
pub struct PluginDescriptor {
    /// Unique IDs are an unfortunate remnant of the LADSPA API. During development, it is
    /// suggested to pick one under 1000, but it should be changed before release. More information
    /// is available here: http://www.ladspa.org/ladspa_sdk/unique_ids.html
    pub unique_id: u64,

    /// Plugin labels are expected to be a unique descriptor string for this specific plugin within
    /// the library. Labels are case sensitive and expected not to contain spaces.
    pub label: &'static str,

    /// The properties of a plugin describe restrictions and features for it's use. See
    /// documentation for ```Properties``` for info on available options.
    pub properties: Properties,

    /// The name of the plugin. This is usually how it is identified.
    pub name: &'static str,

    /// The maker of the plugin. Can be empty.
    pub maker: &'static str,

    /// Indicates copyright of the plugin. If no copyright applies, "None" should be used.
    pub copyright: &'static str,

    /// A vector of input and output ports exposed by the plugin. See the documentation for
    /// ```Port``` for more information.
    pub ports: Vec<Port>,

    /// A function which creates a new instance of the plugin.
    ///
    /// Note: Initialization, such as resetting plugin state, should go in ```Plugin::activate``` rather
    /// than here. This should just return a basic instance, ready to be activated.
    /// If your plugin has no internal state, you may optionally not implement ```Plugin::activate```
    /// and do everything here.
    pub new: fn(desc: &PluginDescriptor, sample_rate: u64) -> Box<Plugin>,
}

#[derive(Copy)]
/// Represents an input or output to the plugin representing either audio or
/// control data.
pub struct Port {
    /// The name of the port. For control ports, this will likely be shown by the host in an
    /// automatically generated GUI next to the control. For audio ports, it is mostly just
    /// for identification in your code but some hosts may display it.
    pub name: &'static str,

    /// Describes the type of port: audio or control, input or output.
    pub desc: PortDescriptor,

    /// Most useful on control inputs but can be used on any type of port.
    pub hint: Option<ControlHint>,

    /// Most useful on control inputs but can be used on any type of port.
    pub default: Option<DefaultValue>,

    /// The lower bound of values to accepted by default (the host may ignore this).
    pub lower_bound: Option<Data>,

    /// The upper bound of values to accepted by default (the host may ignore this).
    pub upper_bound: Option<Data>,
}

#[derive(Copy)]
/// Represents the 4 types of ports: audio or control, input or output.
pub enum PortDescriptor {
    AudioInput = 8 | 1,
    AudioOutput = 8 | 2,
    ControlInput = 4 | 1,
    ControlOutput = 4 | 2,
}

bitflags!(
    #[doc="Represents the special properties a control port may hold. These are merely hints as to the
    use of the port and may be completely ignored by the host. For audio ports, use ```CONTROL_HINT_NONE```.
    To attach multiple properties, bitwise-or them together.
    See documentation for the constants beginning with HINT_ for the more information."]
    flags ControlHint: i32 {
        #[doc="Indicates that this is a toggled port. Toggled ports may only have default values
        of zero or one, although the host may send any value, where <= 0 is false and > 0 is true."]
        const HINT_TOGGLED = 0x4,

        #[doc="Indicates that all values related to the port will be multiplied by the sample rate by
        the host before passing them to your plugin. This includes the lower and upper bounds. If you
        want an upper bound of 22050 with this property and a sample rate of 44100, set the upper bound
        to 0.5"]
        const HINT_SAMPLE_RATE = 0x8,

        #[doc="Indicates that the data passed through this port would be better represented on a
        logarithmic scale"]
        const HINT_LOGARITHMIC = 0x10,

        #[doc="Indicates that the data passed through this port should be represented as integers. Bounds
        may be interpreted exclusively depending on the host"]
        const HINT_INTEGER = 0x20,
    }
);

#[derive(Copy)]
/// The default values that a control port may hold. For audio ports, use DefaultControlValue::None.
pub enum DefaultValue {
    /// Equal to the ```lower_bound``` of the ```Port```.
    Minimum = 0x40,
    /// For ports with
    /// ```LADSPA_HINT_LOGARITHMIC```, this should be ```exp(log(lower_bound) * 0.75 +
    /// log(upper_bound) * 0.25)```. Otherwise, this should be ```(lower_bound * 0.75 +
    /// upper_bound * 0.25)```.
    Low = 0x80,
    /// For ports with
    /// ```CONTROL_HINT_LOGARITHMIC```, this should be ```exp(log(lower_bound) * 0.5 +
    /// log(upper_bound) * 0.5)```. Otherwise, this should be ```(lower_bound * 0.5 +
    /// upper_bound * 0.5)```.
    Middle = 0xC0,
    /// For ports with
    /// ```LADSPA_HINT_LOGARITHMIC```, this should be ```exp(log(lower_bound) * 0.25 +
    /// log(upper_bound) * 0.75)```. Otherwise, this should be ```(lower_bound * 0.25 +
    /// upper_bound * 0.75)```.
    High = 0x100,
    /// Equal to the ```upper_bound``` of the ```Port```.
    Maximum = 0x140,

    /// Equal to 0 or false for toggled values.
    Value0 = 0x200,
    /// Equal to 1 or true for toggled values.
    Value1 = 0x240,
    /// Equal to 100.
    Value100 = 0x280,
    /// Equal to 440, concert A. This may be off by a few Hz if the host is using an alternate
    /// tuning.
    Value440 = 0x2C0,
}

/// Represents a connection between a port and the data attached to the port by the plugin
/// host.
pub struct PortConnection<'a> {
    /// The port which the data is connected to.
    pub port: Port,

    /// The data connected to the port. It's usually simpler to use the various unwrap_* functions
    /// than to interface with this directly.
    pub data: PortData<'a>,
}

/// Represents the four types of data a port can hold.
pub enum PortData<'a> {
    AudioInput(&'a [Data]),
    AudioOutput(RefCell<&'a mut [Data]>),
    ControlInput(&'a Data),
    ControlOutput(RefCell<&'a mut Data>),
}

impl<'a> PortConnection<'a> {
    /// Returns a slice pointing to the internal data of an audio input port. Panics if this port
    /// is not an ```AudioIn``` port.
    pub fn unwrap_audio(&'a self) -> &'a [Data] {
        if let PortData::AudioInput(ref data) = self.data {
            data
        } else {
            panic!("PortConnection::unwrap_audio called on a non audio input port!")
        }
    }

    /// Returns a mutable slice pointing to the internal data of an audio output port. Panics if
    /// this port is not an ```AudioOut``` port.
    pub fn unwrap_audio_mut(&'a self) -> RefMut<'a, &'a mut [Data]> {
        if let PortData::AudioOutput(ref data) = self.data {
            data.borrow_mut()
        } else {
            panic!("PortConnection::unwrap_audio_mut called on a non audio output port!")
        }
    }

    /// Returns a refrence to the internal data of an control input port. Panics if this port
    /// is not an ```ControlIn``` port.
    pub fn unwrap_control(&'a self) -> &'a Data {
        if let PortData::ControlInput(data) = self.data {
            data
        } else {
            panic!("PortConnection::unwrap_control called on a non control input port!")
        }
    }

    /// Returns a mutable refrence to the internal data of an audio output port. Panics if
    /// this port is not an ```ControlOut``` port.
    pub fn unwrap_control_mut(&'a self) -> RefMut<'a, &'a mut Data> {
        if let PortData::ControlOutput(ref data) = self.data {
            data.borrow_mut()
        } else {
            panic!("PortConnection::unwrap_control called on a non control output port!")
        }
    }
}

bitflags!(
    #[doc="Represents the special properties a LADSPA plugin can have.
    To attach multiple properties, bitwise-or them together, for example
    ```PROP_REALTIME | PROP_INPLACE_BROKEN```.
    See documentation for the constants beginning with PROP_ for the more information."]
    flags Properties: i32 {

        #[doc="No properties."]
        const PROP_NONE = 0,

        #[doc="Indicates that the plugin has a realtime dependency so it's output may not be cached."]
        const PROP_REALTIME = 1,

        #[doc="Indicates that the plugin will not function correctly if the input and output audio
        data has the same memory location. This could be an issue if you copy input to output
        then refer back to previous values of the input as they will be overwritten. It is
        recommended that you avoid using this flag if possible as it can decrease the speed of
        the plugin."]
        const PROP_INPLACE_BROKEN = 2,

        #[doc="Indicates that the plugin is capable of running not only in a conventional host but
        also in a 'hard real-time' environment. To qualify for this the plugin must
        satisfy all of the following:

        * The plugin must not use malloc(), free() or other heap memory
        management within its run() function. All new
        memory used in run() must be managed via the stack. These
        restrictions only apply to the run() function.

        * The plugin will not attempt to make use of any library
        functions with the exceptions of functions in the ANSI standard C
        and C maths libraries, which the host is expected to provide.

        * The plugin will not access files, devices, pipes, sockets, IPC
        or any other mechanism that might result in process or thread
        blocking.

        * The plugin will take an amount of time to execute a run()
        call approximately of form (A+B*SampleCount) where A
        and B depend on the machine and host in use. This amount of time
        may not depend on input signals or plugin state. The host is left
        the responsibility to perform timings to estimate upper bounds for
        A and B."]
        const PROP_HARD_REALTIME_CAPABLE = 4,
    }
);

/// Represents an instance of a plugin which may be exposed as a LADSPA plugin using
/// ```get_ladspa_descriptor```. It is not necessary to implement activate to deactivate.
pub trait Plugin {
    /// The plugin instance must reset all state information dependent
    /// on the history of the plugin instance here.
    /// Will be called before `run` is called for the first time.
    fn activate(&mut self) { }

    /// Runs the plugin on a number of samples, given the connected ports.
    fn run<'a>(&mut self, sample_count: usize, ports: &[&'a PortConnection<'a>]);

    /// Indicates the plugin is no longer live.
    fn deactivate(&mut self) { }
}
<commit_msg>Fix docs to point to the examples dir correctly<commit_after>#![feature(libc)]
#![feature(core)]
#![feature(hash)]

/*!
 * The ```ladspa``` crate provides an interface for writing [LADSPA](http://www.ladspa.org/)
 * plugins safely in Rust.
 *
 * ##Creating the project
 *
 * Run ```cargo new my_ladspa_plugin``` to generate a Cargo project for your plugin, then add
 * the following to the generated Cargo.toml:
 *
 * ```
 * [dependencies]
 * ladspa = "*"
 *
 * [lib]
 * name = "my_ladspa_plugin"
 * crate-type = ["dylib"]
 * ```
 * This will pull in the correct dependency and ensure that the library generated when you build
 * your plugin is compatible with LADSPA hosts.
 *
 * ## Writing the code
 * You'll want to implement
 * ```get_ladspa_descriptor``` in your src/lib.rs. This function is expected to return 1 or more
 * ```PluginDescriptor```s describing the plugins exposed by your library. See the documentation
 * for ```get_ladspa_descriptor``` and the examples
 * [on Github](https://github.com/nwoeanhinnogaehr/ladspa.rs/tree/master/examples) for more
 * information.
 *
 * ## Testing it out
 * There is a list of host software supporting LADSPA on the
 * [LADSPA home page](http://www.ladspa.org/). In order for a host to find your plugin, you will
 * either need to copy the *.so file from target/ after building to /usr/lib/ladspa/ (on most
 * systems, it may be different on your system) or set the enviornment variable ```LADSPA_PATH```
 * to equal the directory where you store your plugins.
 */

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

mod ffi;

pub use ffi::ladspa_descriptor;

use std::cell::{RefCell, RefMut};

#[allow(improper_ctypes)]
extern {
    /**
     * Your plugin must implement this function.
     * ```get_ladspa_descriptor``` returns a description of a supported plugin for a given plugin
     * index. When the index is out of bounds for the number of plugins supported by your library,
     * you are expected to return ```None```.
     *
     * Example no-op implementation:
     *
     * ```rust{.ignore}
     * #[no_mangle]
     * pub extern fn get_ladspa_descriptor(index: u64) -> Option<ladspa::PluginDescriptor> {
     *     None
     * }
     * ```
     */
    pub fn get_ladspa_descriptor(index: u64) -> Option<PluginDescriptor>;
}

/// The data type used internally by LADSPA for audio and control ports.
pub type Data = f32;

/// Describes the properties of a ```Plugin``` to be exposed as a LADSPA plugin.
pub struct PluginDescriptor {
    /// Unique IDs are an unfortunate remnant of the LADSPA API. During development, it is
    /// suggested to pick one under 1000, but it should be changed before release. More information
    /// is available here: http://www.ladspa.org/ladspa_sdk/unique_ids.html
    pub unique_id: u64,

    /// Plugin labels are expected to be a unique descriptor string for this specific plugin within
    /// the library. Labels are case sensitive and expected not to contain spaces.
    pub label: &'static str,

    /// The properties of a plugin describe restrictions and features for it's use. See
    /// documentation for ```Properties``` for info on available options.
    pub properties: Properties,

    /// The name of the plugin. This is usually how it is identified.
    pub name: &'static str,

    /// The maker of the plugin. Can be empty.
    pub maker: &'static str,

    /// Indicates copyright of the plugin. If no copyright applies, "None" should be used.
    pub copyright: &'static str,

    /// A vector of input and output ports exposed by the plugin. See the documentation for
    /// ```Port``` for more information.
    pub ports: Vec<Port>,

    /// A function which creates a new instance of the plugin.
    ///
    /// Note: Initialization, such as resetting plugin state, should go in ```Plugin::activate``` rather
    /// than here. This should just return a basic instance, ready to be activated.
    /// If your plugin has no internal state, you may optionally not implement ```Plugin::activate```
    /// and do everything here.
    pub new: fn(desc: &PluginDescriptor, sample_rate: u64) -> Box<Plugin>,
}

#[derive(Copy)]
/// Represents an input or output to the plugin representing either audio or
/// control data.
pub struct Port {
    /// The name of the port. For control ports, this will likely be shown by the host in an
    /// automatically generated GUI next to the control. For audio ports, it is mostly just
    /// for identification in your code but some hosts may display it.
    pub name: &'static str,

    /// Describes the type of port: audio or control, input or output.
    pub desc: PortDescriptor,

    /// Most useful on control inputs but can be used on any type of port.
    pub hint: Option<ControlHint>,

    /// Most useful on control inputs but can be used on any type of port.
    pub default: Option<DefaultValue>,

    /// The lower bound of values to accepted by default (the host may ignore this).
    pub lower_bound: Option<Data>,

    /// The upper bound of values to accepted by default (the host may ignore this).
    pub upper_bound: Option<Data>,
}

#[derive(Copy)]
/// Represents the 4 types of ports: audio or control, input or output.
pub enum PortDescriptor {
    AudioInput = 8 | 1,
    AudioOutput = 8 | 2,
    ControlInput = 4 | 1,
    ControlOutput = 4 | 2,
}

bitflags!(
    #[doc="Represents the special properties a control port may hold. These are merely hints as to the
    use of the port and may be completely ignored by the host. For audio ports, use ```CONTROL_HINT_NONE```.
    To attach multiple properties, bitwise-or them together.
    See documentation for the constants beginning with HINT_ for the more information."]
    flags ControlHint: i32 {
        #[doc="Indicates that this is a toggled port. Toggled ports may only have default values
        of zero or one, although the host may send any value, where <= 0 is false and > 0 is true."]
        const HINT_TOGGLED = 0x4,

        #[doc="Indicates that all values related to the port will be multiplied by the sample rate by
        the host before passing them to your plugin. This includes the lower and upper bounds. If you
        want an upper bound of 22050 with this property and a sample rate of 44100, set the upper bound
        to 0.5"]
        const HINT_SAMPLE_RATE = 0x8,

        #[doc="Indicates that the data passed through this port would be better represented on a
        logarithmic scale"]
        const HINT_LOGARITHMIC = 0x10,

        #[doc="Indicates that the data passed through this port should be represented as integers. Bounds
        may be interpreted exclusively depending on the host"]
        const HINT_INTEGER = 0x20,
    }
);

#[derive(Copy)]
/// The default values that a control port may hold. For audio ports, use DefaultControlValue::None.
pub enum DefaultValue {
    /// Equal to the ```lower_bound``` of the ```Port```.
    Minimum = 0x40,
    /// For ports with
    /// ```LADSPA_HINT_LOGARITHMIC```, this should be ```exp(log(lower_bound) * 0.75 +
    /// log(upper_bound) * 0.25)```. Otherwise, this should be ```(lower_bound * 0.75 +
    /// upper_bound * 0.25)```.
    Low = 0x80,
    /// For ports with
    /// ```CONTROL_HINT_LOGARITHMIC```, this should be ```exp(log(lower_bound) * 0.5 +
    /// log(upper_bound) * 0.5)```. Otherwise, this should be ```(lower_bound * 0.5 +
    /// upper_bound * 0.5)```.
    Middle = 0xC0,
    /// For ports with
    /// ```LADSPA_HINT_LOGARITHMIC```, this should be ```exp(log(lower_bound) * 0.25 +
    /// log(upper_bound) * 0.75)```. Otherwise, this should be ```(lower_bound * 0.25 +
    /// upper_bound * 0.75)```.
    High = 0x100,
    /// Equal to the ```upper_bound``` of the ```Port```.
    Maximum = 0x140,

    /// Equal to 0 or false for toggled values.
    Value0 = 0x200,
    /// Equal to 1 or true for toggled values.
    Value1 = 0x240,
    /// Equal to 100.
    Value100 = 0x280,
    /// Equal to 440, concert A. This may be off by a few Hz if the host is using an alternate
    /// tuning.
    Value440 = 0x2C0,
}

/// Represents a connection between a port and the data attached to the port by the plugin
/// host.
pub struct PortConnection<'a> {
    /// The port which the data is connected to.
    pub port: Port,

    /// The data connected to the port. It's usually simpler to use the various unwrap_* functions
    /// than to interface with this directly.
    pub data: PortData<'a>,
}

/// Represents the four types of data a port can hold.
pub enum PortData<'a> {
    AudioInput(&'a [Data]),
    AudioOutput(RefCell<&'a mut [Data]>),
    ControlInput(&'a Data),
    ControlOutput(RefCell<&'a mut Data>),
}

impl<'a> PortConnection<'a> {
    /// Returns a slice pointing to the internal data of an audio input port. Panics if this port
    /// is not an ```AudioIn``` port.
    pub fn unwrap_audio(&'a self) -> &'a [Data] {
        if let PortData::AudioInput(ref data) = self.data {
            data
        } else {
            panic!("PortConnection::unwrap_audio called on a non audio input port!")
        }
    }

    /// Returns a mutable slice pointing to the internal data of an audio output port. Panics if
    /// this port is not an ```AudioOut``` port.
    pub fn unwrap_audio_mut(&'a self) -> RefMut<'a, &'a mut [Data]> {
        if let PortData::AudioOutput(ref data) = self.data {
            data.borrow_mut()
        } else {
            panic!("PortConnection::unwrap_audio_mut called on a non audio output port!")
        }
    }

    /// Returns a refrence to the internal data of an control input port. Panics if this port
    /// is not an ```ControlIn``` port.
    pub fn unwrap_control(&'a self) -> &'a Data {
        if let PortData::ControlInput(data) = self.data {
            data
        } else {
            panic!("PortConnection::unwrap_control called on a non control input port!")
        }
    }

    /// Returns a mutable refrence to the internal data of an audio output port. Panics if
    /// this port is not an ```ControlOut``` port.
    pub fn unwrap_control_mut(&'a self) -> RefMut<'a, &'a mut Data> {
        if let PortData::ControlOutput(ref data) = self.data {
            data.borrow_mut()
        } else {
            panic!("PortConnection::unwrap_control called on a non control output port!")
        }
    }
}

bitflags!(
    #[doc="Represents the special properties a LADSPA plugin can have.
    To attach multiple properties, bitwise-or them together, for example
    ```PROP_REALTIME | PROP_INPLACE_BROKEN```.
    See documentation for the constants beginning with PROP_ for the more information."]
    flags Properties: i32 {

        #[doc="No properties."]
        const PROP_NONE = 0,

        #[doc="Indicates that the plugin has a realtime dependency so it's output may not be cached."]
        const PROP_REALTIME = 1,

        #[doc="Indicates that the plugin will not function correctly if the input and output audio
        data has the same memory location. This could be an issue if you copy input to output
        then refer back to previous values of the input as they will be overwritten. It is
        recommended that you avoid using this flag if possible as it can decrease the speed of
        the plugin."]
        const PROP_INPLACE_BROKEN = 2,

        #[doc="Indicates that the plugin is capable of running not only in a conventional host but
        also in a 'hard real-time' environment. To qualify for this the plugin must
        satisfy all of the following:

        * The plugin must not use malloc(), free() or other heap memory
        management within its run() function. All new
        memory used in run() must be managed via the stack. These
        restrictions only apply to the run() function.

        * The plugin will not attempt to make use of any library
        functions with the exceptions of functions in the ANSI standard C
        and C maths libraries, which the host is expected to provide.

        * The plugin will not access files, devices, pipes, sockets, IPC
        or any other mechanism that might result in process or thread
        blocking.

        * The plugin will take an amount of time to execute a run()
        call approximately of form (A+B*SampleCount) where A
        and B depend on the machine and host in use. This amount of time
        may not depend on input signals or plugin state. The host is left
        the responsibility to perform timings to estimate upper bounds for
        A and B."]
        const PROP_HARD_REALTIME_CAPABLE = 4,
    }
);

/// Represents an instance of a plugin which may be exposed as a LADSPA plugin using
/// ```get_ladspa_descriptor```. It is not necessary to implement activate to deactivate.
pub trait Plugin {
    /// The plugin instance must reset all state information dependent
    /// on the history of the plugin instance here.
    /// Will be called before `run` is called for the first time.
    fn activate(&mut self) { }

    /// Runs the plugin on a number of samples, given the connected ports.
    fn run<'a>(&mut self, sample_count: usize, ports: &[&'a PortConnection<'a>]);

    /// Indicates the plugin is no longer live.
    fn deactivate(&mut self) { }
}
<|endoftext|>


<commit_before>#![warn(missing_docs, trivial_numeric_casts, unused_extern_crates, unused_import_braces, unused_qualifications,
        unused_results)]

//! # Pascal strings in Rust.
//!
//! A `PascalString`, or `ShortString` is a String which stores its data on the stack. Because of this, it has
//! a fixed maximum size, which cannot be changed. Traditionally, the size of a `PascalString` is 256 bytes -
//! the first byte stores the length, which means that each remaining byte is indexable using only that byte.
//!
//! This is a very niche string type - generally, you are better off using `std::string::String`, or the
//! `AsciiString` type from the `ascii` crate if you need an ascii string. They have no upper size limit, and
//! are cheaper to pass around as they are only 64 bytes on the stack. Generally, you should only use `PascalString` if:
//!
//! * You know that you absolutely, certainly cannot do without heap allocation.
//! * You need to store your string data inline into your `struct` type - for example if you will allocate a bunch
//!   of these custom `struct` types into a pool allocator, and cannot afford the heap fragmentation.
//! * You will keep, allocate, and deallocate a *lot* of short strings in your program.

extern crate ascii as ascii_crate;

pub mod ascii;
pub mod utf8;

const PASCAL_STRING_BUF_SIZE: usize = ::std::u8::MAX as usize;
<commit_msg>Document the modules<commit_after>#![warn(missing_docs, trivial_numeric_casts, unused_extern_crates, unused_import_braces, unused_qualifications,
        unused_results)]

//! # Pascal strings in Rust.
//!
//! A `PascalString`, or `ShortString` is a String which stores its data on the stack. Because of this, it has
//! a fixed maximum size, which cannot be changed. Traditionally, the size of a `PascalString` is 256 bytes -
//! the first byte stores the length, which means that each remaining byte is indexable using only that byte.
//!
//! This is a very niche string type - generally, you are better off using `std::string::String`, or the
//! `AsciiString` type from the `ascii` crate if you need an ascii string. They have no upper size limit, and
//! are cheaper to pass around as they are only 64 bytes on the stack. Generally, you should only use `PascalString` if:
//!
//! * You know that you absolutely, certainly cannot do without heap allocation.
//! * You need to store your string data inline into your `struct` type - for example if you will allocate a bunch
//!   of these custom `struct` types into a pool allocator, and cannot afford the heap fragmentation.
//! * You will keep, allocate, and deallocate a *lot* of short strings in your program.

extern crate ascii as ascii_crate;

/// Ascii encoded pascal strings.
pub mod ascii;

/// Utf8 encoded pascal strings.
pub mod utf8;

const PASCAL_STRING_BUF_SIZE: usize = ::std::u8::MAX as usize;
<|endoftext|>


<commit_before>pub mod ffi;
pub mod hl;

#[cfg(test)]
mod tests {
    use ffi::*;
    use hl::*;
    use std::sync::{ONCE_INIT, Once};
    static GLSLANG_INITIALIZATION: Once = ONCE_INIT;

    fn init() {
        GLSLANG_INITIALIZATION.call_once(|| initialize().unwrap());
    }

    #[test]
    fn test_linkage() {
        init();
    }

    #[test]
    fn test_translation_complex() {
        init();
        const FRAGMENT_SHADER: u32 = 0x8B30;
        let source = "
   precision mediump float;
   varying vec2 vTextureCoord;

   uniform sampler2D uSampler;

   void main() {
      gl_FragColor = texture2D(uSampler, vTextureCoord);
   }
";
        let resources = BuiltInResources::default();
        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Glsl,
                                                  &resources).unwrap();

        assert!(compiler.compile_and_translate(&[source]).is_ok());
    }

    #[test]
    fn test_translation() {
        const SHADER: &'static str = "void main() {
    gl_FragColor = vec4(0, 1, 0, 1);  // green
}";
        const EXPECTED: &'static str = "void main(){
(gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0));
}\n";
        const FRAGMENT_SHADER: u32 = 0x8B30;

        init();

        let resources = BuiltInResources::default();
        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Glsl,
                                                  &resources).unwrap();

        let result = compiler.compile_and_translate(&[SHADER]).unwrap();
        println!("{:?}", result);
        assert!(result == EXPECTED);
    }

    // TODO(emilio): run this test. We can't actually run it because travis machines can't output
    // essl.
    fn test_translation_essl() {
        const SHADER: &'static str = "void main() {
    gl_FragColor = vec4(0, 1, 0, 1);  // green
}";
        const EXPECTED: &'static str = "void main(){
(gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0));
}\n";
        const FRAGMENT_SHADER: u32 = 0x8B30;

        init();

        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Essl,
                                                  &BuiltInResources::default()).expect("Failed to create a validator for essl");

        let result = compiler.compile_and_translate(&[SHADER]).unwrap();
        println!("{:?}", result);
        assert!(result == EXPECTED);
    }
}
<commit_msg>lib: Test essl translation.<commit_after>pub mod ffi;
pub mod hl;

#[cfg(test)]
mod tests {
    use ffi::*;
    use hl::*;
    use std::sync::{ONCE_INIT, Once};
    static GLSLANG_INITIALIZATION: Once = ONCE_INIT;

    fn init() {
        GLSLANG_INITIALIZATION.call_once(|| initialize().unwrap());
    }

    #[test]
    fn test_linkage() {
        init();
    }

    #[test]
    fn test_translation_complex() {
        init();
        const FRAGMENT_SHADER: u32 = 0x8B30;
        let source = "
   precision mediump float;
   varying vec2 vTextureCoord;

   uniform sampler2D uSampler;

   void main() {
      gl_FragColor = texture2D(uSampler, vTextureCoord);
   }
";
        let resources = BuiltInResources::default();
        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Glsl,
                                                  &resources).unwrap();

        assert!(compiler.compile_and_translate(&[source]).is_ok());
    }

    #[test]
    fn test_translation() {
        const SHADER: &'static str = "void main() {
    gl_FragColor = vec4(0, 1, 0, 1);  // green
}";
        const EXPECTED: &'static str = "void main(){
(gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0));
}\n";
        const FRAGMENT_SHADER: u32 = 0x8B30;

        init();

        let resources = BuiltInResources::default();
        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Glsl,
                                                  &resources).unwrap();

        let result = compiler.compile_and_translate(&[SHADER]).unwrap();
        println!("{:?}", result);
        assert!(result == EXPECTED);
    }

    #[test]
    fn test_translation_essl() {
        const SHADER: &'static str = "void main() {
    gl_FragColor = vec4(0, 1, 0, 1);  // green
}";
        const EXPECTED: &'static str = "void main(){
(gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0));
}\n";
        const FRAGMENT_SHADER: u32 = 0x8B30;

        init();

        let compiler = ShaderValidator::for_webgl(FRAGMENT_SHADER,
                                                  Output::Essl,
                                                  &BuiltInResources::default()).expect("Failed to create a validator for essl");

        let result = compiler.compile_and_translate(&[SHADER]).unwrap();
        println!("{:?}", result);
        assert!(result == EXPECTED);
    }
}
<|endoftext|>


<commit_before>//! Whatlang is a Rust library to detect(regonize) natural languages.
//! Apart from it, the library also recognizes scripts (writing system).
//! Every language and script are represented by determined list of enums.
//!
//! # Examples
//!
//! Using `detect` function:
//!
//! ```
//! use whatlang::{detect, Lang, Script};
//!
//! let text = "Ĉu vi ne volas eklerni Esperanton? Bonvolu! Estas unu de la plej bonaj aferoj!";
//! let info = detect(text).unwrap();
//! assert_eq!(info.lang(), Lang::Epo);
//! assert_eq!(info.script(), Script::Latin);
//!
//! // TODO:
//! // Confidence is in the range from 0 to 1.
//! // assert_eq!(info.confidence(), 1.0);
//! // assert!(info.is_reliable());
//! ```
//!
//! Using `Detector` with specified blacklist or whitelist:
//!
//! ```
//! // TODO:
//! // use whatlang::{Detector, Lang};
//!
//! // let whitelist = vec![Lang::Eng, Lang::Rus];
//!
//! // // You can also create detector using with_blacklist function
//! // let detector = Detector::with_whitelist(whitelist);
//! // let lang = detector.detect_lang("There is no reason not to learn Esperanto.");
//! // assert_eq!(lang, Some(Lang::Eng));
//! ```
//!
// mod detect;
// mod detector;
mod error;
// mod info;
mod lang;
mod scripts;
mod trigrams;
mod utils;
mod core;
mod alphabets;
mod combined;

// pub use crate::detector::Detector;
// pub use crate::info::Info;
pub use crate::lang::Lang;
// pub use crate::options::Options;
pub use crate::scripts::{detect_script, Script};

pub use crate::core::{detect, detect_lang, detect_with_options, Output, Method, Options};

// pub use crate::detect::detect;
// pub use crate::detect::detect_lang;
// pub use crate::detect::detect_with_options;
// pub use crate::scripts::detect_script;
<commit_msg>Cleanup lib.rs<commit_after>//! Whatlang is a Rust library to detect(regonize) natural languages.
//! Apart from it, the library also recognizes scripts (writing system).
//! Every language and script are represented by determined list of enums.
//!
//! # Examples
//!
//! Using `detect` function:
//!
//! ```
//! use whatlang::{detect, Lang, Script};
//!
//! let text = "Ĉu vi ne volas eklerni Esperanton? Bonvolu! Estas unu de la plej bonaj aferoj!";
//! let info = detect(text).unwrap();
//! assert_eq!(info.lang(), Lang::Epo);
//! assert_eq!(info.script(), Script::Latin);
//!
//! // TODO:
//! // Confidence is in the range from 0 to 1.
//! // assert_eq!(info.confidence(), 1.0);
//! // assert!(info.is_reliable());
//! ```
//!
//! Using `Detector` with specified blacklist or whitelist:
//!
//! ```
//! // TODO:
//! // use whatlang::{Detector, Lang};
//!
//! // let whitelist = vec![Lang::Eng, Lang::Rus];
//!
//! // // You can also create detector using with_blacklist function
//! // let detector = Detector::with_whitelist(whitelist);
//! // let lang = detector.detect_lang("There is no reason not to learn Esperanto.");
//! // assert_eq!(lang, Some(Lang::Eng));
//! ```
//!
// mod detect;
// mod detector;
mod error;
// mod info;
mod lang;
mod scripts;
mod trigrams;
mod utils;
mod core;
mod alphabets;
mod combined;

// pub use crate::detector::Detector;
// pub use crate::info::Info;
pub use crate::lang::Lang;
pub use crate::scripts::{detect_script, Script};
pub use crate::core::{detect, detect_lang, detect_with_options, Output, Method, Options};
<|endoftext|>


<commit_before>trait StringChars<T> {
    fn all_chars(self) -> Vec<T>;
}

impl StringChars<String> for String {
    fn all_chars(self) -> Vec<String> {
        let char_vec: Vec<String> = self
                                    .split("")
                                    .map(|cur_char| { cur_char.to_string() })
                                    .collect();
        char_vec
    }
}

trait VecExtensions<T> {
    fn last_pos(&self) -> usize;
}

impl VecExtensions<String> for Vec<String> {
    fn last_pos(&self) -> usize {
        self.len() - 1
    }
}

fn vec_shift(input: &Vec<String>, start: usize, end: usize) -> String {
    input
    .iter()
    .enumerate()
    .filter(|&(i, _)| { i >= start && i <= end }) // end needed for one case otherwise not
    .map(|(_, x)| { x.to_string() })
    .collect::<Vec<String>>()
    .join("")
}

fn shift_seq(offset: i32, base_seq: String) -> String {
    #[warn(unused_assignments)]
    let mut new_seq = String::new();
    let seq_vec: Vec<String> = base_seq.all_chars();

    if offset >= seq_vec.len() as i32 {
        new_seq = vec_shift(&seq_vec, (offset as usize) % seq_vec.len(), seq_vec.last_pos());
        if offset % seq_vec.len() as i32 != 0 {
            new_seq = format!("{}{}", new_seq, vec_shift(&seq_vec, 0, (offset as usize) % seq_vec.len() - 1));
        }
    } else {
        new_seq = vec_shift(&seq_vec, offset as usize, seq_vec.last_pos());
        if offset != 0 {
            new_seq = format!("{}{}", new_seq, vec_shift(&seq_vec, 0, (offset - 1) as usize));
        }
    }
    new_seq
}

pub fn encipher(offset: i32, message: &str) -> String {
    let base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    let base_seq = base.to_string().all_chars();
    let new_seq = shift_seq(offset, base.to_string()).all_chars();

    let mut new_string = String::new();

    for achar in message.to_string().all_chars() {
        let mut found = false;
        for i in 0..base_seq.last_pos() {
            if achar == base_seq[i] {
                new_string += &new_seq[i];
                found = true;
            }
        }
        if !found {
            new_string += "achar"
        }
    }

    new_string
}

pub fn decipher(offset: i32, message: &str) -> String {
    let base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    let cipher_seq = shift_seq(offset, base.to_string()).all_chars();
    let base_seq = base.to_string().all_chars();

    let mut new_string = String::new();

    for achar in message.to_string().all_chars() {
        let mut found = false;
        for i in 0..cipher_seq.last_pos() {
            if achar == cipher_seq[i] {
                new_string += &base_seq[i];
                found  = true;
            }
        }
        if !found {
            new_string += &achar;
        }
    }
    new_string
}
<commit_msg>We want to keep unknown chars when we encipher.<commit_after>trait StringChars<T> {
    fn all_chars(self) -> Vec<T>;
}

impl StringChars<String> for String {
    fn all_chars(self) -> Vec<String> {
        let char_vec: Vec<String> = self
                                    .split("")
                                    .map(|cur_char| { cur_char.to_string() })
                                    .collect();
        char_vec
    }
}

trait VecExtensions<T> {
    fn last_pos(&self) -> usize;
}

impl VecExtensions<String> for Vec<String> {
    fn last_pos(&self) -> usize {
        self.len() - 1
    }
}

fn vec_shift(input: &Vec<String>, start: usize, end: usize) -> String {
    input
    .iter()
    .enumerate()
    .filter(|&(i, _)| { i >= start && i <= end }) // end needed for one case otherwise not
    .map(|(_, x)| { x.to_string() })
    .collect::<Vec<String>>()
    .join("")
}

fn shift_seq(offset: i32, base_seq: String) -> String {
    #[warn(unused_assignments)]
    let mut new_seq = String::new();
    let seq_vec: Vec<String> = base_seq.all_chars();

    if offset >= seq_vec.len() as i32 {
        new_seq = vec_shift(&seq_vec, (offset as usize) % seq_vec.len(), seq_vec.last_pos());
        if offset % seq_vec.len() as i32 != 0 {
            new_seq = format!("{}{}", new_seq, vec_shift(&seq_vec, 0, (offset as usize) % seq_vec.len() - 1));
        }
    } else {
        new_seq = vec_shift(&seq_vec, offset as usize, seq_vec.last_pos());
        if offset != 0 {
            new_seq = format!("{}{}", new_seq, vec_shift(&seq_vec, 0, (offset - 1) as usize));
        }
    }
    new_seq
}

pub fn encipher(offset: i32, message: &str) -> String {
    let base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    let base_seq = base.to_string().all_chars();
    let new_seq = shift_seq(offset, base.to_string()).all_chars();

    let mut new_string = String::new();

    for achar in message.to_string().all_chars() {
        let mut found = false;
        for i in 0..base_seq.last_pos() {
            if achar == base_seq[i] {
                new_string += &new_seq[i];
                found = true;
            }
        }
        if !found {
            new_string += &achar;
        }
    }

    new_string
}

pub fn decipher(offset: i32, message: &str) -> String {
    let base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    let cipher_seq = shift_seq(offset, base.to_string()).all_chars();
    let base_seq = base.to_string().all_chars();

    let mut new_string = String::new();

    for achar in message.to_string().all_chars() {
        let mut found = false;
        for i in 0..cipher_seq.last_pos() {
            if achar == cipher_seq[i] {
                new_string += &base_seq[i];
                found  = true;
            }
        }
        if !found {
            new_string += &achar;
        }
    }
    new_string
}
<|endoftext|>


<commit_before>extern crate petgraph;

// XXX: Self-loops?

use petgraph::{Graph, Directed};
use petgraph::graph::{NodeIndex, IndexType};
use std::collections::HashSet;
use std::hash::Hash;

#[repr(u8)]
#[derive(Debug)]
pub enum TriadType {
    T003 = 0,
    T012,
    T102,
    T021D,

    T021U,
    T021C,
    T111D,
    T111U,

    T030T,
    T030C,
    T201,
    T120D,

    T120U,
    T120C,
    T210,
    T300
}

impl TriadType {
    #[inline(always)]
    fn from_u8(i: u8) -> TriadType {
        use std::mem;
        assert!(i < 16);
        unsafe { mem::transmute(i) }
    }
}

fn tricode<N, E, I: IndexType>(graph: &Graph<N, E, Directed, I>, v: NodeIndex<I>, u: NodeIndex<I>, w: NodeIndex<I>) -> usize {
    let mut tricode = 0;
    if let Some(_) = graph.find_edge(v, u) { tricode |= 1 << 0; }
    if let Some(_) = graph.find_edge(u, v) { tricode |= 1 << 1; }
    if let Some(_) = graph.find_edge(v, w) { tricode |= 1 << 2; }
    if let Some(_) = graph.find_edge(w, v) { tricode |= 1 << 3; }
    if let Some(_) = graph.find_edge(u, w) { tricode |= 1 << 4; }
    if let Some(_) = graph.find_edge(w, u) { tricode |= 1 << 5; }
    return tricode;
}

const TRITYPES: [u8;64] = [0, 1, 1, 2, 1, 3, 5, 7, 1, 5, 4, 6, 2, 7, 6, 10,
                           1, 5, 3, 7, 4, 8, 8, 12, 5, 9, 8, 13, 6, 13, 11, 14,
                           1, 4, 5, 6, 5, 8, 9, 13, 3, 8, 8, 11, 7, 12, 13, 14,
                           2, 6, 7, 10, 6, 11, 13, 14, 7, 13, 12, 14, 10, 14, 14, 15];

#[derive(Debug)]
pub struct TriadicCensus {
    census: [u64; 16],
}

impl TriadicCensus {
    /// Calculates the `distance` between two TriadicCensus structs, treated as
    /// points in a 16-dimensional space.
    pub fn distance(a: &TriadicCensus, b: &TriadicCensus) -> f64 {
        let mut sum = 0.0f64;
        for i in 0..16 {
            let va = a.census[i];
            let vb = b.census[i];
            let diff = (if va > vb { va - vb } else { vb - va }) as f64;
            sum += diff * diff;
        }
        sum.sqrt()
    }

    #[inline(always)]
    fn new() -> TriadicCensus {
        TriadicCensus{census: [0;16]}
    }

    #[inline(always)]
    fn add(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] += cnt;
    }

    #[inline(always)]
    fn set(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] = cnt;
    }

    #[inline(always)]
    pub fn get(&self, triad_type: TriadType) -> u64 {
        self.census[triad_type as usize]
    }

    #[inline(always)]
    pub fn as_slice<'a>(&'a self) -> &'a[u64] {
        &self.census[..]
    }

    /// XXX: Optimize: find_edge() is O(k) with k the number of edges.
    pub fn from_graph<N, E, I: IndexType+Hash>(graph: &Graph<N, E, Directed, I>) -> TriadicCensus {
        let n = graph.node_count();

        let mut census = TriadicCensus::new();

        for i in 0..n {
            let v = NodeIndex::new(i);

            let mut neighbors_v = HashSet::new();
            for u in graph.neighbors_undirected(v) {
                if v < u {
                    neighbors_v.insert(u);
                }
            }

            for u in neighbors_v {
                let mut s = HashSet::new();
                for nu in graph.neighbors_undirected(u) { s.insert(nu); }
                for nv in graph.neighbors_undirected(v) { s.insert(nv); }
                let _ = s.remove(&u);
                let _ = s.remove(&v);

                let tri_type =
                    if graph.find_edge(v, u).is_some() && graph.find_edge(u, v).is_some() {
                        TriadType::T102
                    } else {
                        TriadType::T012
                    };

                let cnt = n as i64 - s.len() as i64 - 2;
                assert!(cnt >= 0);
                census.add(tri_type, cnt as u64);
                for w in s {
                    if u < w || (v < w && w < u && !(graph.find_edge(v, w).is_some() || graph.find_edge(w, v).is_some())) {
                       let tri_type = TriadType::from_u8(TRITYPES[tricode(graph, v, u, w)]);
                       census.add(tri_type, 1);
                    }
                }
            }
        }

        let mut sum = 0;
        for &cnt in &census.as_slice()[1..] {
            sum += cnt;
        }
        let n = n as u64;
        // Integer division below is guaranteed to produce an integral result
        census.set(TriadType::T003, (n * (n - 1) * (n - 2)) / 6 - sum);
        return census;
    }
}

#[test]
fn test_simple() {
    let mut g: Graph<(),()> = Graph::new();

    let n1 = g.add_node(());
    let n2 = g.add_node(());
    let n3 = g.add_node(());

    let c1 = TriadicCensus::from_graph(&g);
    assert_eq!(&[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c1.as_slice());

    g.add_edge(n1, n3, ());
    let c2 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c2.as_slice());

    let d = TriadicCensus::distance(&c1, &c2); // should be sqrt(2)
    assert!(d > 1.414 && d < 1.415);

    g.add_edge(n3, n1, ());
    let c3 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0], c3.as_slice());

    g.add_edge(n2, n3, ());
    let c4 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0], c4.as_slice());
}

#[cfg(test)]
fn line_graph(n: u32) -> Graph<(),(), Directed> {
    let mut g: Graph<(),(), Directed> = Graph::new();

    let mut prev = g.add_node(());
    for _ in 0..n-1 {
        let cur = g.add_node(());
        g.add_edge(prev, cur, ());
        prev = cur;
    }
    return g;
}

#[cfg(test)]
fn circular_graph(n: u32) -> Graph<(),(), Directed> {
    let mut g: Graph<(),(), Directed> = Graph::new();

    let first = g.add_node(());
    let mut prev = first;
    for _ in 0..n-1 {
        let cur = g.add_node(());
        g.add_edge(prev, cur, ());
        prev = cur;
    }
    g.add_edge(prev, first, ());
    return g;
}

#[test]
fn test_line_graph() {
    // Result compared with igraph.triad_census().
    let c = TriadicCensus::from_graph(&line_graph(20));
    assert_eq!(&[816,306,0,0,0,18,0,0,0,0,0,0,0,0,0,0], c.as_slice());

    let c = TriadicCensus::from_graph(&line_graph(40));
    assert_eq!(&[8436,1406,0,0,0,38,0,0,0,0,0,0,0,0,0,0], c.as_slice());
}

#[test]
fn test_circular_graph() {
    // Result compared with igraph.triad_census().
    let c = TriadicCensus::from_graph(&circular_graph(20));
    assert_eq!(&[800,320,0,0,0,20,0,0,0,0,0,0,0,0,0,0], c.as_slice());

    let c = TriadicCensus::from_graph(&circular_graph(40));
    assert_eq!(&[8400,1440,0,0,0,40,0,0,0,0,0,0,0,0,0,0], c.as_slice());

}
<commit_msg>rustfmt<commit_after>extern crate petgraph;

// XXX: Self-loops?

use petgraph::{Graph, Directed};
use petgraph::graph::{NodeIndex, IndexType};
use std::collections::HashSet;
use std::hash::Hash;

#[repr(u8)]
#[derive(Debug)]
pub enum TriadType {
    T003 = 0,
    T012,
    T102,
    T021D,

    T021U,
    T021C,
    T111D,
    T111U,

    T030T,
    T030C,
    T201,
    T120D,

    T120U,
    T120C,
    T210,
    T300,
}

impl TriadType {
    #[inline(always)]
    fn from_u8(i: u8) -> TriadType {
        use std::mem;
        assert!(i < 16);
        unsafe { mem::transmute(i) }
    }
}

fn tricode<N, E, I: IndexType>(graph: &Graph<N, E, Directed, I>,
                               v: NodeIndex<I>,
                               u: NodeIndex<I>,
                               w: NodeIndex<I>)
                               -> usize {
    let mut tricode = 0;
    if let Some(_) = graph.find_edge(v, u) {
        tricode |= 1 << 0;
    }
    if let Some(_) = graph.find_edge(u, v) {
        tricode |= 1 << 1;
    }
    if let Some(_) = graph.find_edge(v, w) {
        tricode |= 1 << 2;
    }
    if let Some(_) = graph.find_edge(w, v) {
        tricode |= 1 << 3;
    }
    if let Some(_) = graph.find_edge(u, w) {
        tricode |= 1 << 4;
    }
    if let Some(_) = graph.find_edge(w, u) {
        tricode |= 1 << 5;
    }
    return tricode;
}

const TRITYPES: [u8; 64] = [0, 1, 1, 2, 1, 3, 5, 7, 1, 5, 4, 6, 2, 7, 6, 10, 1, 5, 3, 7, 4, 8, 8,
                            12, 5, 9, 8, 13, 6, 13, 11, 14, 1, 4, 5, 6, 5, 8, 9, 13, 3, 8, 8, 11,
                            7, 12, 13, 14, 2, 6, 7, 10, 6, 11, 13, 14, 7, 13, 12, 14, 10, 14, 14,
                            15];

#[derive(Debug)]
pub struct TriadicCensus {
    census: [u64; 16],
}

impl TriadicCensus {
    /// Calculates the `distance` between two TriadicCensus structs, treated as
    /// points in a 16-dimensional space.
    pub fn distance(a: &TriadicCensus, b: &TriadicCensus) -> f64 {
        let mut sum = 0.0f64;
        for i in 0..16 {
            let va = a.census[i];
            let vb = b.census[i];
            let diff = (if va > vb {
                va - vb
            } else {
                vb - va
            }) as f64;
            sum += diff * diff;
        }
        sum.sqrt()
    }

    #[inline(always)]
    fn new() -> TriadicCensus {
        TriadicCensus { census: [0; 16] }
    }

    #[inline(always)]
    fn add(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] += cnt;
    }

    #[inline(always)]
    fn set(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] = cnt;
    }

    #[inline(always)]
    pub fn get(&self, triad_type: TriadType) -> u64 {
        self.census[triad_type as usize]
    }

    #[inline(always)]
    pub fn as_slice<'a>(&'a self) -> &'a [u64] {
        &self.census[..]
    }

    /// XXX: Optimize: find_edge() is O(k) with k the number of edges.
    pub fn from_graph<N, E, I: IndexType + Hash>(graph: &Graph<N, E, Directed, I>) -> TriadicCensus {
        let n = graph.node_count();

        let mut census = TriadicCensus::new();

        for i in 0..n {
            let v = NodeIndex::new(i);

            let mut neighbors_v = HashSet::new();
            for u in graph.neighbors_undirected(v) {
                if v < u {
                    neighbors_v.insert(u);
                }
            }

            for u in neighbors_v {
                let mut s = HashSet::new();
                for nu in graph.neighbors_undirected(u) {
                    s.insert(nu);
                }
                for nv in graph.neighbors_undirected(v) {
                    s.insert(nv);
                }
                let _ = s.remove(&u);
                let _ = s.remove(&v);

                let tri_type = if graph.find_edge(v, u).is_some() &&
                                  graph.find_edge(u, v).is_some() {
                    TriadType::T102
                } else {
                    TriadType::T012
                };

                let cnt = n as i64 - s.len() as i64 - 2;
                assert!(cnt >= 0);
                census.add(tri_type, cnt as u64);
                for w in s {
                    if u < w ||
                       (v < w && w < u &&
                        !(graph.find_edge(v, w).is_some() || graph.find_edge(w, v).is_some())) {
                        let tri_type = TriadType::from_u8(TRITYPES[tricode(graph, v, u, w)]);
                        census.add(tri_type, 1);
                    }
                }
            }
        }

        let mut sum = 0;
        for &cnt in &census.as_slice()[1..] {
            sum += cnt;
        }
        let n = n as u64;
        // Integer division below is guaranteed to produce an integral result
        census.set(TriadType::T003, (n * (n - 1) * (n - 2)) / 6 - sum);
        return census;
    }
}

#[test]
fn test_simple() {
    let mut g: Graph<(), ()> = Graph::new();

    let n1 = g.add_node(());
    let n2 = g.add_node(());
    let n3 = g.add_node(());

    let c1 = TriadicCensus::from_graph(&g);
    assert_eq!(&[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
               c1.as_slice());

    g.add_edge(n1, n3, ());
    let c2 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
               c2.as_slice());

    let d = TriadicCensus::distance(&c1, &c2); // should be sqrt(2)
    assert!(d > 1.414 && d < 1.415);

    g.add_edge(n3, n1, ());
    let c3 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
               c3.as_slice());

    g.add_edge(n2, n3, ());
    let c4 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
               c4.as_slice());
}

#[cfg(test)]
fn line_graph(n: u32) -> Graph<(), (), Directed> {
    let mut g: Graph<(), (), Directed> = Graph::new();

    let mut prev = g.add_node(());
    for _ in 0..n - 1 {
        let cur = g.add_node(());
        g.add_edge(prev, cur, ());
        prev = cur;
    }
    return g;
}

#[cfg(test)]
fn circular_graph(n: u32) -> Graph<(), (), Directed> {
    let mut g: Graph<(), (), Directed> = Graph::new();

    let first = g.add_node(());
    let mut prev = first;
    for _ in 0..n - 1 {
        let cur = g.add_node(());
        g.add_edge(prev, cur, ());
        prev = cur;
    }
    g.add_edge(prev, first, ());
    return g;
}

#[test]
fn test_line_graph() {
    // Result compared with igraph.triad_census().
    let c = TriadicCensus::from_graph(&line_graph(20));
    assert_eq!(&[816, 306, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
               c.as_slice());

    let c = TriadicCensus::from_graph(&line_graph(40));
    assert_eq!(&[8436, 1406, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
               c.as_slice());
}

#[test]
fn test_circular_graph() {
    // Result compared with igraph.triad_census().
    let c = TriadicCensus::from_graph(&circular_graph(20));
    assert_eq!(&[800, 320, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
               c.as_slice());

    let c = TriadicCensus::from_graph(&circular_graph(40));
    assert_eq!(&[8400, 1440, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
               c.as_slice());

}
<|endoftext|>


<commit_before>#![feature(convert)]
extern crate libc;
extern crate groonga_sys as ffi;
use std::mem;
use ffi::groonga as groonga;

mod commandapi;

#[derive(Clone, Debug)]
pub struct LibGroonga {
    disposed: bool
}

impl LibGroonga {
    pub fn new() -> Result<LibGroonga, String> {
        let rc =  commandapi::groonga_init();
        if rc != groonga::GRN_SUCCESS {
            return Err("Couldn't initilize Groonga.".to_string())
        }
        Ok(LibGroonga{ disposed: false })
    }

    fn close(&mut self) -> Result<(), String> {
        if self.disposed {
            return Ok(())
        }
        let rc = commandapi::groonga_fin();
        if rc != groonga::GRN_SUCCESS {
            return Err("Couldn't finalized Groonga.".to_string())
        }
        self.disposed = true;
        Ok(())
    }
}

impl Drop for LibGroonga {
    fn drop(&mut self) {
        self.close().unwrap();
    }
}

#[derive(Clone, Debug)]
pub struct Context {
    ctx: *mut groonga::grn_ctx,
    disposed: bool
}

impl Context {
    pub fn new() -> Result<Context, String> {
        let ctx = commandapi::groonga_ctx_open(0);
        if ctx.is_null() {
            return Err("Couldn't create Groonga Context.".to_string())
        }
        Ok(Context{ ctx: ctx, disposed: false })
    }

    pub fn close(&mut self) -> Result<(), String> {
        if self.disposed {
            return Ok(())
        }
        let rc = commandapi::groonga_ctx_close(self.ctx);
        if rc != groonga::GRN_SUCCESS {
            return Err("Couldn't dispose Groonga Context.".to_string())
        }
        unsafe {
            self.ctx = mem::zeroed();
        }
        self.disposed = true;
        Ok(())
    }
}

#[derive(Clone, Debug)]
pub struct Database {
    ctx: *mut groonga::grn_ctx,
    disposed: bool
}

impl Database {
    pub fn new(ctx: Context) -> Database {
        Database{ctx: ctx.ctx, disposed: false}
    }

    pub fn uses(&mut self, dbpath: &str) {
        let _ = commandapi::groonga_db_use(self.ctx, dbpath);
    }

    fn close(&mut self) {
        if self.disposed {
            return
        }
        unsafe {
            self.ctx = mem::zeroed();
        }
        self.disposed = true;
    }
}

impl Drop for Database {
    fn drop(&mut self) {
        self.close()
    }
}

#[derive(Clone, Debug)]
pub struct Command {
    ctx: *mut groonga::grn_ctx,
    disposed: bool
}

impl Command {
    pub fn new(ctx: Context) -> Command {
        Command{ctx: ctx.ctx, disposed: false}
    }

    pub fn groonga_version() -> &'static str {
        commandapi::get_groonga_version()
    }

    pub fn execute(&mut self, command: &str) -> String {
        let result = commandapi::groonga_execute_command(self.ctx, command);
        match result {
            Ok(v) => v,
            Err(_) => "".to_string()
        }
    }

    fn close(&mut self) {
        if self.disposed {
            return
        }
        unsafe {
            self.ctx = mem::zeroed();
        }
        self.disposed = true;
    }
}

impl Drop for Command {
    fn drop(&mut self) {
        self.close()
    }
}
<commit_msg>Remove unstable `convert` feature allowing attribute<commit_after>extern crate libc;
extern crate groonga_sys as ffi;
use std::mem;
use ffi::groonga as groonga;

mod commandapi;

#[derive(Clone, Debug)]
pub struct LibGroonga {
    disposed: bool
}

impl LibGroonga {
    pub fn new() -> Result<LibGroonga, String> {
        let rc =  commandapi::groonga_init();
        if rc != groonga::GRN_SUCCESS {
            return Err("Couldn't initilize Groonga.".to_string())
        }
        Ok(LibGroonga{ disposed: false })
    }

    fn close(&mut self) -> Result<(), String> {
        if self.disposed {
            return Ok(())
        }
        let rc = commandapi::groonga_fin();
        if rc != groonga::GRN_SUCCESS {
            return Err("Couldn't finalized Groonga.".to_string())
        }
        self.disposed = true;
        Ok(())
    }
}

impl Drop for LibGroonga {
    fn drop(&mut self) {
        self.close().unwrap();
    }
}

#[derive(Clone, Debug)]
pub struct Context {
    ctx: *mut groonga::grn_ctx,
    disposed: bool
}

impl Context {
    pub fn new() -> Result<Context, String> {
        let ctx = commandapi::groonga_ctx_open(0);
        if ctx.is_null() {
            return Err("Couldn't create Groonga Context.".to_string())
        }
        Ok(Context{ ctx: ctx, disposed: false })
    }

    pub fn close(&mut self) -> Result<(), String> {
        if self.disposed {
            return Ok(())
        }
        let rc = commandapi::groonga_ctx_close(self.ctx);
        if rc != groonga::GRN_SUCCESS {
            return Err("Couldn't dispose Groonga Context.".to_string())
        }
        unsafe {
            self.ctx = mem::zeroed();
        }
        self.disposed = true;
        Ok(())
    }
}

#[derive(Clone, Debug)]
pub struct Database {
    ctx: *mut groonga::grn_ctx,
    disposed: bool
}

impl Database {
    pub fn new(ctx: Context) -> Database {
        Database{ctx: ctx.ctx, disposed: false}
    }

    pub fn uses(&mut self, dbpath: &str) {
        let _ = commandapi::groonga_db_use(self.ctx, dbpath);
    }

    fn close(&mut self) {
        if self.disposed {
            return
        }
        unsafe {
            self.ctx = mem::zeroed();
        }
        self.disposed = true;
    }
}

impl Drop for Database {
    fn drop(&mut self) {
        self.close()
    }
}

#[derive(Clone, Debug)]
pub struct Command {
    ctx: *mut groonga::grn_ctx,
    disposed: bool
}

impl Command {
    pub fn new(ctx: Context) -> Command {
        Command{ctx: ctx.ctx, disposed: false}
    }

    pub fn groonga_version() -> &'static str {
        commandapi::get_groonga_version()
    }

    pub fn execute(&mut self, command: &str) -> String {
        let result = commandapi::groonga_execute_command(self.ctx, command);
        match result {
            Ok(v) => v,
            Err(_) => "".to_string()
        }
    }

    fn close(&mut self) {
        if self.disposed {
            return
        }
        unsafe {
            self.ctx = mem::zeroed();
        }
        self.disposed = true;
    }
}

impl Drop for Command {
    fn drop(&mut self) {
        self.close()
    }
}
<|endoftext|>


<commit_before><commit_msg>pick up the tests<commit_after>mod types;
<|endoftext|>


<commit_before>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interface to the random number generator of the operating system.
//!
//! # Platform sources
//!
//! | OS               | interface
//! |------------------|---------------------------------------------------------
//! | Linux, Android   | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
//! | Windows          | [`RtlGenRandom`][3]
//! | macOS            | [`getentropy()`][19] if available, otherwise [`/dev/random`][20] (identical to `/dev/urandom`)
//! | iOS              | [`SecRandomCopyBytes`][4]
//! | FreeBSD          | [`getrandom()`][21] if available, otherwise [`kern.arandom`][5]
//! | OpenBSD          | [`getentropy`][6]
//! | NetBSD           | [`/dev/urandom`][7] after successfully polling `/dev/random`
//! | Dragonfly BSD    | [`/dev/random`][8]
//! | Solaris, illumos | [`getrandom`][9] system call if available, otherwise [`/dev/random`][10]
//! | Fuchsia OS       | [`cprng_draw`][11]
//! | Redox            | [`rand:`][12]
//! | CloudABI         | [`cloudabi_sys_random_get`][13]
//! | Haiku            | `/dev/random` (identical to `/dev/urandom`)
//! | L4RE, SGX, UEFI  | [RDRAND][18]
//! | Hermit           | [RDRAND][18] as [`sys_rand`][22] is currently broken.
//! | Web browsers     | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and ams.js][14])
//! | Node.js          | [`crypto.randomBytes`][15] (see [Support for WebAssembly and ams.js][16])
//! | WASI             | [`__wasi_random_get`][17]
//!
//! Getrandom doesn't have a blanket implementation for all Unix-like operating
//! systems that reads from `/dev/urandom`. This ensures all supported operating
//! systems are using the recommended interface and respect maximum buffer
//! sizes.
//!
//! ## Unsupported targets
//!
//! By default, compiling `getrandom` for an unsupported target will result in
//! a compilation error. If you want to build an application which uses `getrandom`
//! for such target, you can either:
//! - Use [`[replace]`][replace] or [`[patch]`][patch] section in your `Cargo.toml`
//! to switch to a custom implementation with a support of your target.
//! - Enable the `dummy` feature to have getrandom use an implementation that always
//! fails at run-time on unsupported targets.
//!
//! [replace]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-replace-section
//! [patch]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-patch-section
//!
//! ## Support for WebAssembly and asm.js
//!
//! Getrandom supports all of Rust's current `wasm32` targets, and it works with
//! both Node.js and web browsers. The three Emscripten targets
//! `asmjs-unknown-emscripten`, `wasm32-unknown-emscripten`, and
//! `wasm32-experimental-emscripten` use Emscripten's `/dev/random` emulation.
//! The WASI target `wasm32-wasi` uses the [`__wasi_random_get`][17] function
//! defined by the WASI standard.
//!
//! Getrandom also supports `wasm32-unknown-unknown` by directly calling
//! JavaScript methods. Rust currently has two ways to do this: [bindgen] and
//! [stdweb]. Getrandom supports using either one by enabling the
//! `wasm-bindgen` or `stdweb` crate features. Note that if both features are
//! enabled, `wasm-bindgen` will be used. If neither feature is enabled, calls
//! to `getrandom` will always fail at runtime.
//!
//! [bindgen]: https://github.com/rust-lang/rust-bindgen
//! [stdweb]: https://github.com/koute/stdweb
//!
//! ## Early boot
//!
//! It is possible that early in the boot process the OS hasn't had enough time
//! yet to collect entropy to securely seed its RNG, especially on virtual
//! machines.
//!
//! Some operating systems always block the thread until the RNG is securely
//! seeded. This can take anywhere from a few seconds to more than a minute.
//! Others make a best effort to use a seed from before the shutdown and don't
//! document much.
//!
//! A few, Linux, NetBSD and Solaris, offer a choice between blocking and
//! getting an error; in these cases we always choose to block.
//!
//! On Linux (when the `genrandom` system call is not available) and on NetBSD
//! reading from `/dev/urandom` never blocks, even when the OS hasn't collected
//! enough entropy yet. To avoid returning low-entropy bytes, we first read from
//! `/dev/random` and only switch to `/dev/urandom` once this has succeeded.
//!
//! # Error handling
//!
//! We always choose failure over returning insecure "random" bytes. In general,
//! on supported platforms, failure is highly unlikely, though not impossible.
//! If an error does occur, then it is likely that it will occur on every call to
//! `getrandom`, hence after the first successful call one can be reasonably
//! confident that no errors will occur.
//!
//! On unsupported platforms, `getrandom` always fails. See the [`Error`] type
//! for more information on what data is returned on failure.
//!
//! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
//! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
//! [3]: https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom
//! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
//! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
//! [6]: https://man.openbsd.org/getentropy.2
//! [7]: http://netbsd.gw.com/cgi-bin/man-cgi?random+4+NetBSD-current
//! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random&section=4
//! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
//! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html
//! [11]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
//! [12]: https://github.com/redox-os/randd/blob/master/src/main.rs
//! [13]: https://github.com/nuxinl/cloudabi#random_get
//! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
//! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
//! [16]: #support-for-webassembly-and-amsjs
//! [17]: https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md#__wasi_random_get
//! [18]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
//! [19]: https://www.unix.com/man-page/mojave/2/getentropy/
//! [20]: https://www.unix.com/man-page/mojave/4/random/
//! [21]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
//! [22]: https://github.com/hermitcore/libhermit-rs/blob/09c38b0371cee6f56a541400ba453e319e43db53/src/syscalls/random.rs#L21

#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
    html_root_url = "https://rust-random.github.io/rand/"
)]
#![no_std]
#![cfg_attr(feature = "stdweb", recursion_limit = "128")]
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]

#[macro_use]
extern crate cfg_if;

cfg_if! {
    if #[cfg(feature = "log")] {
        #[allow(unused)]
        #[macro_use]
        extern crate log;
    } else {
        #[allow(unused)]
        macro_rules! error {
            ($($x:tt)*) => {};
        }
        #[allow(unused)]
        macro_rules! warn {
            ($($x:tt)*) => {};
        }
        #[allow(unused)]
        macro_rules! info {
            ($($x:tt)*) => {};
        }
    }
}

mod error;
pub use crate::error::Error;

#[allow(dead_code)]
mod util;

cfg_if! {
    // Unlike the other Unix, Fuchsia and iOS don't use the libc to make any calls.
    if #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "emscripten",
                 target_os = "freebsd", target_os = "haiku",     target_os = "illumos",
                 target_os = "linux",   target_os = "macos",     target_os = "netbsd",
                 target_os = "openbsd", target_os = "redox",     target_os = "solaris"))] {
        #[allow(dead_code)]
        mod util_libc;
        // Keep std-only trait definitions for backwards compatiblity
        mod error_impls;
    } else if #[cfg(feature = "std")] {
        mod error_impls;
    }
}

// These targets read from a file as a fallback method.
#[cfg(any(
    target_os = "android",
    target_os = "linux",
    target_os = "macos",
    target_os = "solaris",
    target_os = "illumos",
))]
mod use_file;

// System-specific implementations.
//
// These should all provide getrandom_inner with the same signature as getrandom.
cfg_if! {
    if #[cfg(target_os = "android")] {
        #[path = "linux_android.rs"] mod imp;
    } else if #[cfg(target_os = "cloudabi")] {
        #[path = "cloudabi.rs"] mod imp;
    } else if #[cfg(target_os = "dragonfly")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "emscripten")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "freebsd")] {
        #[path = "freebsd.rs"] mod imp;
    } else if #[cfg(target_os = "fuchsia")] {
        #[path = "fuchsia.rs"] mod imp;
    } else if #[cfg(target_os = "haiku")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "illumos")] {
        #[path = "solaris_illumos.rs"] mod imp;
    } else if #[cfg(target_os = "ios")] {
        #[path = "ios.rs"] mod imp;
    } else if #[cfg(target_os = "linux")] {
        #[path = "linux_android.rs"] mod imp;
    } else if #[cfg(target_os = "macos")] {
        #[path = "macos.rs"] mod imp;
    } else if #[cfg(target_os = "netbsd")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "openbsd")] {
        #[path = "openbsd.rs"] mod imp;
    } else if #[cfg(target_os = "redox")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "solaris")] {
        #[path = "solaris_illumos.rs"] mod imp;
    } else if #[cfg(target_os = "wasi")] {
        #[path = "wasi.rs"] mod imp;
    } else if #[cfg(all(windows, getrandom_uwp))] {
        #[path = "windows_uwp.rs"] mod imp;
    } else if #[cfg(windows)] {
        #[path = "windows.rs"] mod imp;
    } else if #[cfg(all(target_arch = "x86_64", any(
                  target_os = "hermit",
                  target_os = "l4re",
                  target_os = "uefi",
                  target_env = "sgx",
              )))] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
        cfg_if! {
            if #[cfg(feature = "wasm-bindgen")] {
                #[path = "wasm32_bindgen.rs"] mod imp;
            } else if #[cfg(feature = "stdweb")] {
                #[path = "wasm32_stdweb.rs"] mod imp;
            } else {
                // Always have an implementation for wasm32-unknown-unknown.
                // See https://github.com/rust-random/getrandom/issues/87
                #[path = "dummy.rs"] mod imp;
            }
        }
    } else if #[cfg(feature = "dummy")] {
        #[path = "dummy.rs"] mod imp;
    } else {
        compile_error!("\
            target is not supported, for more information see: \
            https://docs.rs/getrandom/#unsupported-targets\
        ");
    }
}

/// Fill `dest` with random bytes from the system's preferred random number
/// source.
///
/// This function returns an error on any failure, including partial reads. We
/// make no guarantees regarding the contents of `dest` on error.
///
/// Blocking is possible, at least during early boot; see module documentation.
///
/// In general, `getrandom` will be fast enough for interactive usage, though
/// significantly slower than a user-space CSPRNG; for the latter consider
/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
pub fn getrandom(dest: &mut [u8]) -> Result<(), error::Error> {
    imp::getrandom_inner(dest)
}
<commit_msg>Handle zero-length slices (#104)<commit_after>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interface to the random number generator of the operating system.
//!
//! # Platform sources
//!
//! | OS               | interface
//! |------------------|---------------------------------------------------------
//! | Linux, Android   | [`getrandom`][1] system call if available, otherwise [`/dev/urandom`][2] after successfully polling `/dev/random`
//! | Windows          | [`RtlGenRandom`][3]
//! | macOS            | [`getentropy()`][19] if available, otherwise [`/dev/random`][20] (identical to `/dev/urandom`)
//! | iOS              | [`SecRandomCopyBytes`][4]
//! | FreeBSD          | [`getrandom()`][21] if available, otherwise [`kern.arandom`][5]
//! | OpenBSD          | [`getentropy`][6]
//! | NetBSD           | [`/dev/urandom`][7] after successfully polling `/dev/random`
//! | Dragonfly BSD    | [`/dev/random`][8]
//! | Solaris, illumos | [`getrandom`][9] system call if available, otherwise [`/dev/random`][10]
//! | Fuchsia OS       | [`cprng_draw`][11]
//! | Redox            | [`rand:`][12]
//! | CloudABI         | [`cloudabi_sys_random_get`][13]
//! | Haiku            | `/dev/random` (identical to `/dev/urandom`)
//! | L4RE, SGX, UEFI  | [RDRAND][18]
//! | Hermit           | [RDRAND][18] as [`sys_rand`][22] is currently broken.
//! | Web browsers     | [`Crypto.getRandomValues`][14] (see [Support for WebAssembly and ams.js][14])
//! | Node.js          | [`crypto.randomBytes`][15] (see [Support for WebAssembly and ams.js][16])
//! | WASI             | [`__wasi_random_get`][17]
//!
//! Getrandom doesn't have a blanket implementation for all Unix-like operating
//! systems that reads from `/dev/urandom`. This ensures all supported operating
//! systems are using the recommended interface and respect maximum buffer
//! sizes.
//!
//! ## Unsupported targets
//!
//! By default, compiling `getrandom` for an unsupported target will result in
//! a compilation error. If you want to build an application which uses `getrandom`
//! for such target, you can either:
//! - Use [`[replace]`][replace] or [`[patch]`][patch] section in your `Cargo.toml`
//! to switch to a custom implementation with a support of your target.
//! - Enable the `dummy` feature to have getrandom use an implementation that always
//! fails at run-time on unsupported targets.
//!
//! [replace]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-replace-section
//! [patch]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-patch-section
//!
//! ## Support for WebAssembly and asm.js
//!
//! Getrandom supports all of Rust's current `wasm32` targets, and it works with
//! both Node.js and web browsers. The three Emscripten targets
//! `asmjs-unknown-emscripten`, `wasm32-unknown-emscripten`, and
//! `wasm32-experimental-emscripten` use Emscripten's `/dev/random` emulation.
//! The WASI target `wasm32-wasi` uses the [`__wasi_random_get`][17] function
//! defined by the WASI standard.
//!
//! Getrandom also supports `wasm32-unknown-unknown` by directly calling
//! JavaScript methods. Rust currently has two ways to do this: [bindgen] and
//! [stdweb]. Getrandom supports using either one by enabling the
//! `wasm-bindgen` or `stdweb` crate features. Note that if both features are
//! enabled, `wasm-bindgen` will be used. If neither feature is enabled, calls
//! to `getrandom` will always fail at runtime.
//!
//! [bindgen]: https://github.com/rust-lang/rust-bindgen
//! [stdweb]: https://github.com/koute/stdweb
//!
//! ## Early boot
//!
//! It is possible that early in the boot process the OS hasn't had enough time
//! yet to collect entropy to securely seed its RNG, especially on virtual
//! machines.
//!
//! Some operating systems always block the thread until the RNG is securely
//! seeded. This can take anywhere from a few seconds to more than a minute.
//! Others make a best effort to use a seed from before the shutdown and don't
//! document much.
//!
//! A few, Linux, NetBSD and Solaris, offer a choice between blocking and
//! getting an error; in these cases we always choose to block.
//!
//! On Linux (when the `genrandom` system call is not available) and on NetBSD
//! reading from `/dev/urandom` never blocks, even when the OS hasn't collected
//! enough entropy yet. To avoid returning low-entropy bytes, we first read from
//! `/dev/random` and only switch to `/dev/urandom` once this has succeeded.
//!
//! # Error handling
//!
//! We always choose failure over returning insecure "random" bytes. In general,
//! on supported platforms, failure is highly unlikely, though not impossible.
//! If an error does occur, then it is likely that it will occur on every call to
//! `getrandom`, hence after the first successful call one can be reasonably
//! confident that no errors will occur.
//!
//! On unsupported platforms, `getrandom` always fails. See the [`Error`] type
//! for more information on what data is returned on failure.
//!
//! [1]: http://man7.org/linux/man-pages/man2/getrandom.2.html
//! [2]: http://man7.org/linux/man-pages/man4/urandom.4.html
//! [3]: https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom
//! [4]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
//! [5]: https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4
//! [6]: https://man.openbsd.org/getentropy.2
//! [7]: http://netbsd.gw.com/cgi-bin/man-cgi?random+4+NetBSD-current
//! [8]: https://leaf.dragonflybsd.org/cgi/web-man?command=random&section=4
//! [9]: https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
//! [10]: https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html
//! [11]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
//! [12]: https://github.com/redox-os/randd/blob/master/src/main.rs
//! [13]: https://github.com/nuxinl/cloudabi#random_get
//! [14]: https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
//! [15]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
//! [16]: #support-for-webassembly-and-amsjs
//! [17]: https://github.com/WebAssembly/WASI/blob/master/design/WASI-core.md#__wasi_random_get
//! [18]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
//! [19]: https://www.unix.com/man-page/mojave/2/getentropy/
//! [20]: https://www.unix.com/man-page/mojave/4/random/
//! [21]: https://www.freebsd.org/cgi/man.cgi?query=getrandom&manpath=FreeBSD+12.0-stable
//! [22]: https://github.com/hermitcore/libhermit-rs/blob/09c38b0371cee6f56a541400ba453e319e43db53/src/syscalls/random.rs#L21

#![doc(
    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
    html_root_url = "https://rust-random.github.io/rand/"
)]
#![no_std]
#![cfg_attr(feature = "stdweb", recursion_limit = "128")]
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]

#[macro_use]
extern crate cfg_if;

cfg_if! {
    if #[cfg(feature = "log")] {
        #[allow(unused)]
        #[macro_use]
        extern crate log;
    } else {
        #[allow(unused)]
        macro_rules! error {
            ($($x:tt)*) => {};
        }
        #[allow(unused)]
        macro_rules! warn {
            ($($x:tt)*) => {};
        }
        #[allow(unused)]
        macro_rules! info {
            ($($x:tt)*) => {};
        }
    }
}

mod error;
pub use crate::error::Error;

#[allow(dead_code)]
mod util;

cfg_if! {
    // Unlike the other Unix, Fuchsia and iOS don't use the libc to make any calls.
    if #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "emscripten",
                 target_os = "freebsd", target_os = "haiku",     target_os = "illumos",
                 target_os = "linux",   target_os = "macos",     target_os = "netbsd",
                 target_os = "openbsd", target_os = "redox",     target_os = "solaris"))] {
        #[allow(dead_code)]
        mod util_libc;
        // Keep std-only trait definitions for backwards compatiblity
        mod error_impls;
    } else if #[cfg(feature = "std")] {
        mod error_impls;
    }
}

// These targets read from a file as a fallback method.
#[cfg(any(
    target_os = "android",
    target_os = "linux",
    target_os = "macos",
    target_os = "solaris",
    target_os = "illumos",
))]
mod use_file;

// System-specific implementations.
//
// These should all provide getrandom_inner with the same signature as getrandom.
cfg_if! {
    if #[cfg(target_os = "android")] {
        #[path = "linux_android.rs"] mod imp;
    } else if #[cfg(target_os = "cloudabi")] {
        #[path = "cloudabi.rs"] mod imp;
    } else if #[cfg(target_os = "dragonfly")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "emscripten")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "freebsd")] {
        #[path = "freebsd.rs"] mod imp;
    } else if #[cfg(target_os = "fuchsia")] {
        #[path = "fuchsia.rs"] mod imp;
    } else if #[cfg(target_os = "haiku")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "illumos")] {
        #[path = "solaris_illumos.rs"] mod imp;
    } else if #[cfg(target_os = "ios")] {
        #[path = "ios.rs"] mod imp;
    } else if #[cfg(target_os = "linux")] {
        #[path = "linux_android.rs"] mod imp;
    } else if #[cfg(target_os = "macos")] {
        #[path = "macos.rs"] mod imp;
    } else if #[cfg(target_os = "netbsd")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "openbsd")] {
        #[path = "openbsd.rs"] mod imp;
    } else if #[cfg(target_os = "redox")] {
        #[path = "use_file.rs"] mod imp;
    } else if #[cfg(target_os = "solaris")] {
        #[path = "solaris_illumos.rs"] mod imp;
    } else if #[cfg(target_os = "wasi")] {
        #[path = "wasi.rs"] mod imp;
    } else if #[cfg(all(windows, getrandom_uwp))] {
        #[path = "windows_uwp.rs"] mod imp;
    } else if #[cfg(windows)] {
        #[path = "windows.rs"] mod imp;
    } else if #[cfg(all(target_arch = "x86_64", any(
                  target_os = "hermit",
                  target_os = "l4re",
                  target_os = "uefi",
                  target_env = "sgx",
              )))] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
        cfg_if! {
            if #[cfg(feature = "wasm-bindgen")] {
                #[path = "wasm32_bindgen.rs"] mod imp;
            } else if #[cfg(feature = "stdweb")] {
                #[path = "wasm32_stdweb.rs"] mod imp;
            } else {
                // Always have an implementation for wasm32-unknown-unknown.
                // See https://github.com/rust-random/getrandom/issues/87
                #[path = "dummy.rs"] mod imp;
            }
        }
    } else if #[cfg(feature = "dummy")] {
        #[path = "dummy.rs"] mod imp;
    } else {
        compile_error!("\
            target is not supported, for more information see: \
            https://docs.rs/getrandom/#unsupported-targets\
        ");
    }
}

/// Fill `dest` with random bytes from the system's preferred random number
/// source.
///
/// This function returns an error on any failure, including partial reads. We
/// make no guarantees regarding the contents of `dest` on error. If `dest` is
/// empty, `getrandom` immediately returns success, making no calls to the
/// underlying operating system.
///
/// Blocking is possible, at least during early boot; see module documentation.
///
/// In general, `getrandom` will be fast enough for interactive usage, though
/// significantly slower than a user-space CSPRNG; for the latter consider
/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
pub fn getrandom(dest: &mut [u8]) -> Result<(), error::Error> {
    if dest.is_empty() {
        return Ok(())
    }
    imp::getrandom_inner(dest)
}
<|endoftext|>


<commit_before>// Copyright 2016 Doug Goldstein
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A simple logger to provide symantics similar to what is expected
//! of most UNIX utilities by logging to stderr and the higher the
//! verbosity the higher the log level
//!
//! ### Examples
//!
//! ```rust
//! #[macro_use]
//! extern crate log;
//! extern crate stderrlog;
//!
//! fn main() {
//!     stderrlog::new().module(module_path!()).init().unwrap();
//!
//!     info!("starting up");
//!
//!     // ...
//! }
//! ```
//!
//! ```rust
//! extern crate docopt;
//! #[macro_use]
//! extern crate log;
//! extern crate rustc_serialize;
//! extern crate stderrlog;
//!
//! use docopt::Docopt;
//!
//! const USAGE: &'static str = "
//! Usage: program [-q] [-v...]
//! ";
//!
//! #[derive(Debug, RustcDecodable)]
//! struct Args {
//!     flag_q: bool,
//!     flag_v: usize,
//! }
//!
//! fn main() {
//!     let args: Args = Docopt::new(USAGE)
//!                             .and_then(|d| d.decode())
//!                             .unwrap_or_else(|e| e.exit());
//!
//!     stderrlog::new()
//!             .module(module_path!())
//!             .quiet(args.flag_q)
//!             .verbosity(args.flag_v)
//!             .init()
//!             .unwrap();
//!     info!("starting up");
//!
//!     // ...
//! }

extern crate log;

use log::{LogLevelFilter, LogMetadata};
use std::collections::BTreeSet;
use std::io::Write;

#[derive(Clone, Debug)]
pub struct StdErrLog {
    verbosity: LogLevelFilter,
    quiet: bool,
    modules: BTreeSet<String>,
}

impl log::Log for StdErrLog {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= log::max_log_level()
    }

    fn log(&self, record: &log::LogRecord) {

        // if logging isn't enabled for this level do a quick out
        if !self.enabled(record.metadata()) {
            return;
        }

        // this logger only logs the requested modules
        if self.modules.contains(record.location().module_path()) || self.modules.is_empty() {
            let _ = writeln!(&mut ::std::io::stderr(),
                             "{} - {}",
                             record.level(),
                             record.args());
        }
    }
}

impl StdErrLog {
    pub fn new() -> StdErrLog {
        StdErrLog {
            verbosity: LogLevelFilter::Error,
            quiet: false,
            modules: BTreeSet::new(),
        }
    }

    /// Sets the verbosity level of messages that will be displayed
    pub fn verbosity(&mut self, verbosity: usize) -> &mut StdErrLog {
        let log_lvl = match verbosity {
            0 => LogLevelFilter::Error,
            1 => LogLevelFilter::Warn,
            2 => LogLevelFilter::Info,
            3 => LogLevelFilter::Debug,
            _ => LogLevelFilter::Trace,
        };

        self.verbosity = log_lvl;
        self
    }

    pub fn quiet(&mut self, quiet: bool) -> &mut StdErrLog {
        self.quiet = quiet;
        self
    }

    pub fn module(&mut self, module: &str) -> &mut StdErrLog {
        self.modules.insert(module.to_owned());
        self
    }

    pub fn modules(&mut self, modules: Vec<&str>) -> &mut StdErrLog {
        for module in modules {
            self.modules.insert(module.to_owned());
        }
        self
    }

    pub fn init(&self) -> Result<(), log::SetLoggerError> {

        log::set_logger(|max_log_level| {
            if self.quiet {
                max_log_level.set(LogLevelFilter::Off);
            } else {
                max_log_level.set(self.verbosity);
            }

            Box::new(self.clone())
        })
    }
}

pub fn new() -> StdErrLog {
    StdErrLog::new()
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_default_level() {
        extern crate log;

        super::new().module(module_path!()).init().unwrap();

        assert_eq!(log::LogLevel::Error, log::max_log_level())
    }
}
<commit_msg>fix logging of sub-module components<commit_after>// Copyright 2016 Doug Goldstein
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A simple logger to provide symantics similar to what is expected
//! of most UNIX utilities by logging to stderr and the higher the
//! verbosity the higher the log level
//!
//! ### Examples
//!
//! ```rust
//! #[macro_use]
//! extern crate log;
//! extern crate stderrlog;
//!
//! fn main() {
//!     stderrlog::new().module(module_path!()).init().unwrap();
//!
//!     info!("starting up");
//!
//!     // ...
//! }
//! ```
//!
//! ```rust
//! extern crate docopt;
//! #[macro_use]
//! extern crate log;
//! extern crate rustc_serialize;
//! extern crate stderrlog;
//!
//! use docopt::Docopt;
//!
//! const USAGE: &'static str = "
//! Usage: program [-q] [-v...]
//! ";
//!
//! #[derive(Debug, RustcDecodable)]
//! struct Args {
//!     flag_q: bool,
//!     flag_v: usize,
//! }
//!
//! fn main() {
//!     let args: Args = Docopt::new(USAGE)
//!                             .and_then(|d| d.decode())
//!                             .unwrap_or_else(|e| e.exit());
//!
//!     stderrlog::new()
//!             .module(module_path!())
//!             .quiet(args.flag_q)
//!             .verbosity(args.flag_v)
//!             .init()
//!             .unwrap();
//!     info!("starting up");
//!
//!     // ...
//! }

extern crate log;

use log::{LogLevelFilter, LogMetadata};
use std::io::Write;

#[derive(Clone, Debug)]
pub struct StdErrLog {
    verbosity: LogLevelFilter,
    quiet: bool,
    modules: Vec<String>,
}

impl log::Log for StdErrLog {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= log::max_log_level()
    }

    fn log(&self, record: &log::LogRecord) {

        // if logging isn't enabled for this level do a quick out
        if !self.enabled(record.metadata()) {
            return;
        }

        // module we are logging for
        let curr_mod = record.location().module_path();

        // this logger only logs the requested modules unless the
        // vector of modules is empty
        // modules will have module::file in the module_path
        if self.modules.is_empty() || self.modules.iter().any(|x| curr_mod.starts_with(x)) {
            let _ = writeln!(&mut ::std::io::stderr(),
                             "{} - {}",
                             record.level(),
                             record.args());
        }
    }
}

impl StdErrLog {
    pub fn new() -> StdErrLog {
        StdErrLog {
            verbosity: LogLevelFilter::Error,
            quiet: false,
            modules: vec![],
        }
    }

    /// Sets the verbosity level of messages that will be displayed
    pub fn verbosity(&mut self, verbosity: usize) -> &mut StdErrLog {
        let log_lvl = match verbosity {
            0 => LogLevelFilter::Error,
            1 => LogLevelFilter::Warn,
            2 => LogLevelFilter::Info,
            3 => LogLevelFilter::Debug,
            _ => LogLevelFilter::Trace,
        };

        self.verbosity = log_lvl;
        self
    }

    pub fn quiet(&mut self, quiet: bool) -> &mut StdErrLog {
        self.quiet = quiet;
        self
    }

    pub fn module(&mut self, module: &str) -> &mut StdErrLog {
        self.modules.push(module.to_owned());
        self
    }

    pub fn modules(&mut self, modules: Vec<String>) -> &mut StdErrLog {
        self.modules.extend(modules);
        self
    }

    pub fn init(&self) -> Result<(), log::SetLoggerError> {

        log::set_logger(|max_log_level| {
            if self.quiet {
                max_log_level.set(LogLevelFilter::Off);
            } else {
                max_log_level.set(self.verbosity);
            }

            Box::new(self.clone())
        })
    }
}

pub fn new() -> StdErrLog {
    StdErrLog::new()
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_default_level() {
        extern crate log;

        super::new().module(module_path!()).init().unwrap();

        assert_eq!(log::LogLevel::Error, log::max_log_level())
    }
}
<|endoftext|>