<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 reading from `/dev/random` once
//! | Windows          | [`RtlGenRandom`][3]
//! | macOS            | [`getentropy()`][19] if available, otherise [`/dev/random`][20] (identical to `/dev/urandom`)
//! | iOS              | [`SecRandomCopyBytes`][4]
//! | FreeBSD          | [`kern.arandom`][5]
//! | OpenBSD          | [`getentropy`][6]
//! | NetBSD           | [`/dev/urandom`][7] after reading from `/dev/random` once
//! | 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`)
//! | SGX, UEFI        | [RDRAND][18]
//! | 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.
//!
//! ## Support for WebAssembly and ams.js
//!
//! The three Emscripten targets `asmjs-unknown-emscripten`,
//! `wasm32-unknown-emscripten` and `wasm32-experimental-emscripten` use
//! Emscripten's emulation of `/dev/random` on web browsers and Node.js.
//!
//! The bare WASM target `wasm32-unknown-unknown` tries to call the javascript
//! methods directly, using either `stdweb` or `wasm-bindgen` depending on what
//! features are activated for this crate. Note that if both features are
//! enabled `wasm-bindgen` will be used. If neither feature is enabled,
//! `getrandom` will always fail.
//!
//! The WASI target `wasm32-wasi` uses the `__wasi_random_get` function defined
//! by the WASI standard.
//!
//!
//! ## 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 with [`Error::UNAVAILABLE`].
//!
//! ## Error codes
//! The crate uses the following custom error codes:
//! - `0x57f4c500` (dec: 1475659008) - an unknown error. Constant:
//! [`Error::UNKNOWN`]
//! - `0x57f4c501` (dec: 1475659009) - no generator is available. Constant:
//! [`Error::UNAVAILABLE`]
//! - `0x57f4c580` (dec: 1475659136) - `self.crypto` is undefined,
//! `wasm-bindgen` specific error.
//! - `0x57f4c581` (dec: 1475659137) - `crypto.getRandomValues` is undefined,
//! `wasm-bindgen` specific error.
//!
//! These codes are provided for reference only and should not be matched upon
//! (but you can match on `Error` constants). The codes may change in future and
//! such change will not be considered a breaking one.
//!
//! Other error codes will originate from an underlying system. In case if such
//! error is encountered, please consult with your system documentation.
//!
//! [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.googlesource.com/fuchsia/+/master/zircon/docs/syscalls/cprng_draw.md
//! [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/CraneStation/wasmtime/blob/master/docs/WASI-api.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/

#![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")]

#[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)*) => {};
        }
    }
}

#[cfg(feature = "std")]
extern crate std;

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

#[allow(dead_code)]
mod util;
#[cfg(any(unix, target_os = "redox"))]
#[allow(dead_code)]
mod util_libc;

// std-only trait definitions (also need for use_file)
#[cfg(any(feature = "std", unix, target_os = "redox"))]
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",
))]
#[allow(dead_code)]
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(windows)] {
        #[path = "windows.rs"] mod imp;
    } else if #[cfg(target_env = "sgx")] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(all(target_arch = "x86_64", target_os = "uefi"))] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(target_arch = "wasm32")] {
        cfg_if! {
            if #[cfg(feature = "wasm-bindgen")] {
                #[path = "wasm32_bindgen.rs"] mod imp;
            } else if #[cfg(feature = "stdweb")] {
                // temp fix for stdweb
                extern crate std;
                #[path = "wasm32_stdweb.rs"] mod imp;
            } else {
                #[path = "dummy.rs"] mod imp;
            }
        }
    } else {
        #[path = "dummy.rs"] mod imp;
    }
}

/// 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>Updated link to the official WASI repo (#59)<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 reading from `/dev/random` once
//! | Windows          | [`RtlGenRandom`][3]
//! | macOS            | [`getentropy()`][19] if available, otherise [`/dev/random`][20] (identical to `/dev/urandom`)
//! | iOS              | [`SecRandomCopyBytes`][4]
//! | FreeBSD          | [`kern.arandom`][5]
//! | OpenBSD          | [`getentropy`][6]
//! | NetBSD           | [`/dev/urandom`][7] after reading from `/dev/random` once
//! | 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`)
//! | SGX, UEFI        | [RDRAND][18]
//! | 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.
//!
//! ## Support for WebAssembly and ams.js
//!
//! The three Emscripten targets `asmjs-unknown-emscripten`,
//! `wasm32-unknown-emscripten` and `wasm32-experimental-emscripten` use
//! Emscripten's emulation of `/dev/random` on web browsers and Node.js.
//!
//! The bare WASM target `wasm32-unknown-unknown` tries to call the javascript
//! methods directly, using either `stdweb` or `wasm-bindgen` depending on what
//! features are activated for this crate. Note that if both features are
//! enabled `wasm-bindgen` will be used. If neither feature is enabled,
//! `getrandom` will always fail.
//!
//! The WASI target `wasm32-wasi` uses the `__wasi_random_get` function defined
//! by the WASI standard.
//!
//!
//! ## 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 with [`Error::UNAVAILABLE`].
//!
//! ## Error codes
//! The crate uses the following custom error codes:
//! - `0x57f4c500` (dec: 1475659008) - an unknown error. Constant:
//! [`Error::UNKNOWN`]
//! - `0x57f4c501` (dec: 1475659009) - no generator is available. Constant:
//! [`Error::UNAVAILABLE`]
//! - `0x57f4c580` (dec: 1475659136) - `self.crypto` is undefined,
//! `wasm-bindgen` specific error.
//! - `0x57f4c581` (dec: 1475659137) - `crypto.getRandomValues` is undefined,
//! `wasm-bindgen` specific error.
//!
//! These codes are provided for reference only and should not be matched upon
//! (but you can match on `Error` constants). The codes may change in future and
//! such change will not be considered a breaking one.
//!
//! Other error codes will originate from an underlying system. In case if such
//! error is encountered, please consult with your system documentation.
//!
//! [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.googlesource.com/fuchsia/+/master/zircon/docs/syscalls/cprng_draw.md
//! [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/

#![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")]

#[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)*) => {};
        }
    }
}

#[cfg(feature = "std")]
extern crate std;

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

#[allow(dead_code)]
mod util;
#[cfg(any(unix, target_os = "redox"))]
#[allow(dead_code)]
mod util_libc;

// std-only trait definitions (also need for use_file)
#[cfg(any(feature = "std", unix, target_os = "redox"))]
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",
))]
#[allow(dead_code)]
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(windows)] {
        #[path = "windows.rs"] mod imp;
    } else if #[cfg(target_env = "sgx")] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(all(target_arch = "x86_64", target_os = "uefi"))] {
        #[path = "rdrand.rs"] mod imp;
    } else if #[cfg(target_arch = "wasm32")] {
        cfg_if! {
            if #[cfg(feature = "wasm-bindgen")] {
                #[path = "wasm32_bindgen.rs"] mod imp;
            } else if #[cfg(feature = "stdweb")] {
                // temp fix for stdweb
                extern crate std;
                #[path = "wasm32_stdweb.rs"] mod imp;
            } else {
                #[path = "dummy.rs"] mod imp;
            }
        }
    } else {
        #[path = "dummy.rs"] mod imp;
    }
}

/// 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)
}
<|endoftext|>


<commit_before>//! # The Network Manager Library
//!
//! The Network Manager Library provides the essential
//! functionality for configuring Network Manager from Rust.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#[macro_use]
extern crate log;

#[macro_use]
extern crate bitflags;

extern crate dbus;

extern crate ascii;

mod dbus_nm;
mod dbus_api;
mod manager;
mod service;
mod connection;
mod device;
mod wifi;
mod ssid;

pub use manager::NetworkManager;
pub use connection::{Connection, ConnectionSettings, ConnectionState};
pub use device::{Device, DeviceType, DeviceState};
pub use wifi::AccessPoint;
<commit_msg>Export publicly Connectivity and ServiceState<commit_after>//! # The Network Manager Library
//!
//! The Network Manager Library provides the essential
//! functionality for configuring Network Manager from Rust.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#[macro_use]
extern crate log;

#[macro_use]
extern crate bitflags;

extern crate dbus;

extern crate ascii;

mod dbus_nm;
mod dbus_api;
mod manager;
mod service;
mod connection;
mod device;
mod wifi;
mod ssid;

pub use manager::{NetworkManager, Connectivity};
pub use connection::{Connection, ConnectionSettings, ConnectionState};
pub use device::{Device, DeviceType, DeviceState};
pub use wifi::AccessPoint;
pub use service::ServiceState;
<|endoftext|>


<commit_before>//! This crate implements a part of the Plugwise Circle and Plugwise Circle+ protocol (tested against
//! 2010 firmware). It still requires the official tooling to configure and to link the plugs. This
//! library supports the following operations:
//!
//! * switch a Circle on or off;
//! * retrieve the relay status of a Circle;
//! * actual power usage of a Circle (in Watts);
//! * power usage over time (retrieved per hour in kWh);
//! * set clock of a Circle;
//! * get actual clock of a Circle.
//!
//! This library is inspired on a
//! [Python implemention](https://bitbucket.org/hadara/python-plugwise/wiki/Home) which was based
//! on the analysis of the protocol by
//! [Maarten Damen](http://www.maartendamen.com/category/plugwise-unleashed/).
//!
//! This crate is tested against Linux, but since this crate is based on
//! [serial-rs](../serial/index.html) crate, it is expected this crate also works on Windows and
//! Mac OS X.
//!
//! Enable the relay of a Circle:
//!
//! ```ignore
//! extern crate plugwise;
//!
//! // Connect to a plugwise device
//! let serial = plugwise::plugwise(plugwise::Device::Serial("/dev/ttyUSB0")).unwrap();
//! // create a Circle (replace MAC address)
//! let circle = serial.create_circle(0x01234567890ABCDEF).unwrap();
//! // switch the Circle on
//! circle.switch_on().unwrap();
//! ```

extern crate crc16;
extern crate time;
extern crate serial;
extern crate num;

mod stub;
mod protocol;

use std::io::prelude::*;
use std::io;
use time::Duration;
use serial::prelude::*;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::BTreeMap;

pub use protocol::ProtocolSnoop;

struct PlugwiseInner<'a, I> {
    protocol: Rc<RefCell<protocol::Protocol<'a, I>>>
}

struct CircleInner<'a, I> {
    protocol: Rc<RefCell<protocol::Protocol<'a, I>>>,
    mac: u64,
    calibration_data: protocol::ResCalibration
}

impl<'a, I: Read+Write+'a> PlugwiseInner<'a, I> {
    fn initialize(port: I) -> io::Result<PlugwiseInner<'a, I>> {
        let plugwise = PlugwiseInner {
            protocol: Rc::new(RefCell::new(protocol::Protocol::new(port)))
        };

        let result = try!(plugwise.protocol.borrow_mut().initialize());

        if !result.is_online {
            return Err(io::Error::new(io::ErrorKind::Other, "not online"));
        }

        Ok(plugwise)
    }

    fn set_snoop(&self, snoop: ProtocolSnoop<'a>) {
        self.protocol.borrow_mut().set_snoop(snoop);
    }

    fn set_retries(&self, retries: u8) {
        self.protocol.borrow_mut().set_retries(retries);
    }
}

/// A abstract representation of the Plugwise USB stick.
pub trait Plugwise<'a> {
    /// Register a Circle (a wall outlet switch) and returns a abstract representation of the
    /// Circle.
    fn create_circle(&self, mac: u64) -> io::Result<Box<Circle + 'a>>;
}

/// A abstract representation of the Plugwise Circle/Circle+.
pub trait Circle {
    /// Switch the relay of Circle on.
    fn switch_on(&self) -> io::Result<()>;
    /// Switch the relay of Circle off.
    fn switch_off(&self) -> io::Result<()>;
    /// Retrieve the relay status of the Circle.
    fn is_switched_on(&self) -> io::Result<bool>;
    /// Get actual power usage of the Circle in Watts (sampled over the last 8 seconds).
    fn get_actual_watt_usage(&self) -> io::Result<f64>;
    /// Get the actual clock state of the Circle (in UTC).
    fn get_clock(&self) -> io::Result<time::Tm>;
    /// Set the clock state of the Circle.
    fn set_clock(&self, tm: time::Tm) -> io::Result<()>;
    /// Retrieve a map of power usages over time. To retrieve only the last logged items specify
    /// the number of elements to retrieve in `max_entries`. Each entry contains the power usage of
    /// one hour.
    fn get_power_buffer(&self, max_entries: Option<u32>) -> io::Result<BTreeMap<time::Timespec, f64>>;
}

impl<'a, I:Read+Write+'a> Plugwise<'a> for PlugwiseInner<'a, I> {
    fn create_circle(&self, mac: u64) -> io::Result<Box<Circle+ 'a>> {
        let calibration_data = try!(self.protocol.borrow_mut().calibrate(mac));
        Ok(Box::new(CircleInner {
            protocol: self.protocol.clone(),
            mac: mac,
            calibration_data: calibration_data
        }))
    }
}

impl<'a, I:Read+Write+'a> Circle for CircleInner<'a, I> {
    fn switch_on(&self) -> io::Result<()> {
        try!(self.protocol.borrow_mut().switch(self.mac, true));
        Ok(())
    }

    fn switch_off(&self) -> io::Result<()> {
        try!(self.protocol.borrow_mut().switch(self.mac, false));
        Ok(())
    }

    fn is_switched_on(&self) -> io::Result<bool> {
        let info = try!(self.protocol.borrow_mut().get_info(self.mac));
        Ok(info.relay_state)
    }

    fn get_actual_watt_usage(&self) -> io::Result<f64> {
        let power_usage = try!(self.protocol.borrow_mut().get_power_usage(self.mac));
        Ok(power_usage.pulse_8s.to_watts(self.calibration_data))
    }

    fn get_clock(&self) -> io::Result<time::Tm> {
        let info = try!(self.protocol.borrow_mut().get_info(self.mac));
        let clock = try!(self.protocol.borrow_mut().get_clock_info(self.mac));

        let mut tm = match info.datetime.to_tm() {
            Some(tm) => tm,
            None => return Err(io::Error::new(io::ErrorKind::Other, "circle returns an invalid timestamp"))
        };
        tm.tm_sec = clock.second as i32;
        tm.tm_min = clock.minute as i32;
        tm.tm_hour = clock.hour as i32;
        tm.tm_wday = (clock.day_of_week % 7) as i32;
        Ok(tm)
    }

    fn set_clock(&self, tm: time::Tm) -> io::Result<()> {
        let clock_set = protocol::ReqClockSet::new_from_tm(tm);
        try!(self.protocol.borrow_mut().set_clock(self.mac, clock_set));
        Ok(())
    }

    fn get_power_buffer(&self,
                        max_entries: Option<u32>)
                        -> io::Result<BTreeMap<time::Timespec, f64>> {
        let mut result = BTreeMap::<time::Timespec, f64>::new();
        let info = try!(self.protocol.borrow_mut().get_info(self.mac));
        let start = match max_entries {
            None => 0,
            Some(n) => {
                let n_of_calls = n / 4; // each power buffer request retrieves 4 power usage statics
                if info.last_logaddr > n_of_calls {
                    info.last_logaddr - n_of_calls
                } else {
                    0
                }
            }
        };

        for index in (start..(info.last_logaddr + 1)) {
            let buffer = try!(self.protocol.borrow_mut().get_power_buffer(self.mac, index));

            self.get_power_buffer_helper(&mut result, &buffer.datetime1, &buffer.pulses1);
            self.get_power_buffer_helper(&mut result, &buffer.datetime2, &buffer.pulses2);
            self.get_power_buffer_helper(&mut result, &buffer.datetime3, &buffer.pulses3);
            self.get_power_buffer_helper(&mut result, &buffer.datetime4, &buffer.pulses4);
        }

        Ok(result)
    }
}

impl <'a, I:Read+Write+'a>  CircleInner<'a, I> {
    fn get_power_buffer_helper(&self,
                               map: &mut BTreeMap<time::Timespec, f64>,
                               datetime: &protocol::DateTime,
                               pulses: &protocol::Pulses) {
        if let Some(tm) = datetime.to_tm() {
            let _ = map.insert(tm.to_timespec(), pulses.to_kwh(self.calibration_data));
        }
    }
}

/// Create a instance to communicate with the Plugwise USB stick and Circle/Circle+ devices.
fn plugwise_device<'a>(port: &str,
                       timeout: Duration,
                       retries: u8,
                       snoop: ProtocolSnoop<'a>) -> io::Result<Box<Plugwise<'a>+ 'a>> {
    let mut port = try!(serial::open(port));
    try!(port.configure(|settings| {
        settings.set_baud_rate(serial::Baud115200);
        settings.set_char_size(serial::Bits8);
        settings.set_parity(serial::ParityNone);
        settings.set_stop_bits(serial::Stop1);
    }));

    port.set_timeout(timeout);
    let plugwise = try!(PlugwiseInner::initialize(port));
    plugwise.set_snoop(snoop);
    plugwise.set_retries(retries);

    Ok(Box::new(plugwise))
}

/// Create a simulation instance for integration or test purposes to use this library without the
/// need of the real hardware.
fn plugwise_simulator<'a>() -> io::Result<Box<Plugwise<'a>+ 'a>> {
    let port = stub::Stub::new();

    let plugwise = try!(PlugwiseInner::initialize(port));

    Ok(Box::new(plugwise))
}

/// Specify which kind of Plugwise device to use
pub enum Device<'a> {
    /// Create a link to the Plugwise USB stick to communicate with the Circle/Circle+ wall
    /// outlets. The reference to the hardware device (i.e. `/dev/ttyUSB0`) must be provided.
    Serial(&'a str),
    /// Simular to `Serial` but with extra settings:
    ///
    SerialExt {
        /// USB serial device name
        port: &'a str,
        /// Timeout in milliseconds;
        timeout: time::Duration,
        /// Number of attempts to retry communication;
        retries: u8,
        /// Tracing settings (including a reference to a `io::Write` instance to log the
        /// communication)
        snoop: ProtocolSnoop<'a>
    },
    /// Create a simulation instance for development, testing and integration purposes
    Simulator,
}

/// Create instance to communicate against a (simulator) Plugwise USB stick and the associated
/// Circle/Circle+ devices.
///
/// Instantiate a link to a Plugwise device:
///
/// ```ignore
/// extern crate plugwise;
///
/// // Connect to a plugwise device
/// let serial = plugwise::plugwise(plugwise::Device::Serial("/dev/ttyUSB0")).unwrap();
/// // create a Circle (replace MAC address)
/// let circle = serial.create_circle(0x01234567890ABCDEF).unwrap();
/// // switch the Circle on
/// circle.switch_on().unwrap();
/// ```
///
/// Instantiate a simulation version:
///
/// ```
/// extern crate plugwise;
///
/// // instantiate a simulation version of Plugwise
/// let stub = plugwise::plugwise(plugwise::Device::Simulator).unwrap();
/// // create a Circle (simulation allows any MAC to be used)
/// let circle = stub.create_circle(0x01234567890ABCDEF).unwrap();
/// // switch the Circle on
/// circle.switch_on().unwrap();
/// ```
pub fn plugwise<'a>(device: Device<'a>) -> io::Result<Box<Plugwise<'a>+ 'a>> {
    match device {
        Device::Simulator => {
            plugwise_simulator()
        },
        Device::Serial(port) => {
            plugwise_device(port, Duration::milliseconds(1000), 3, ProtocolSnoop::Nothing)
        },
        Device::SerialExt{port, timeout, retries, snoop} => {
            let device = try!(plugwise_device(port, timeout, retries, snoop));

            Ok(device)
        },
    }
}

#[test]
fn smoke_external_stub() {
    let stub = plugwise(Device::Simulator).unwrap();
    let circle = stub.create_circle(0x01234567890ABCDEF).unwrap();
    circle.switch_on().unwrap();
    assert_eq!(circle.is_switched_on().unwrap(), true);
    circle.switch_off().unwrap();
    assert_eq!(circle.is_switched_on().unwrap(), false);
    circle.get_actual_watt_usage().unwrap();
    let tm = circle.get_clock().unwrap();
    circle.set_clock(tm).unwrap();
    circle.get_power_buffer(None).unwrap();
}
<commit_msg>Remove remnants of former external interface<commit_after>//! This crate implements a part of the Plugwise Circle and Plugwise Circle+ protocol (tested against
//! 2010 firmware). It still requires the official tooling to configure and to link the plugs. This
//! library supports the following operations:
//!
//! * switch a Circle on or off;
//! * retrieve the relay status of a Circle;
//! * actual power usage of a Circle (in Watts);
//! * power usage over time (retrieved per hour in kWh);
//! * set clock of a Circle;
//! * get actual clock of a Circle.
//!
//! This library is inspired on a
//! [Python implemention](https://bitbucket.org/hadara/python-plugwise/wiki/Home) which was based
//! on the analysis of the protocol by
//! [Maarten Damen](http://www.maartendamen.com/category/plugwise-unleashed/).
//!
//! This crate is tested against Linux, but since this crate is based on
//! [serial-rs](../serial/index.html) crate, it is expected this crate also works on Windows and
//! Mac OS X.
//!
//! Enable the relay of a Circle:
//!
//! ```ignore
//! extern crate plugwise;
//!
//! // Connect to a plugwise device
//! let serial = plugwise::plugwise(plugwise::Device::Serial("/dev/ttyUSB0")).unwrap();
//! // create a Circle (replace MAC address)
//! let circle = serial.create_circle(0x01234567890ABCDEF).unwrap();
//! // switch the Circle on
//! circle.switch_on().unwrap();
//! ```

extern crate crc16;
extern crate time;
extern crate serial;
extern crate num;

mod stub;
mod protocol;

use std::io::prelude::*;
use std::io;
use time::Duration;
use serial::prelude::*;
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::BTreeMap;

pub use protocol::ProtocolSnoop;

struct PlugwiseInner<'a, I> {
    protocol: Rc<RefCell<protocol::Protocol<'a, I>>>
}

struct CircleInner<'a, I> {
    protocol: Rc<RefCell<protocol::Protocol<'a, I>>>,
    mac: u64,
    calibration_data: protocol::ResCalibration
}

impl<'a, I: Read+Write+'a> PlugwiseInner<'a, I> {
    fn initialize(port: I) -> io::Result<PlugwiseInner<'a, I>> {
        let plugwise = PlugwiseInner {
            protocol: Rc::new(RefCell::new(protocol::Protocol::new(port)))
        };

        let result = try!(plugwise.protocol.borrow_mut().initialize());

        if !result.is_online {
            return Err(io::Error::new(io::ErrorKind::Other, "not online"));
        }

        Ok(plugwise)
    }

    fn set_snoop(&self, snoop: ProtocolSnoop<'a>) {
        self.protocol.borrow_mut().set_snoop(snoop);
    }

    fn set_retries(&self, retries: u8) {
        self.protocol.borrow_mut().set_retries(retries);
    }
}

/// A abstract representation of the Plugwise USB stick.
pub trait Plugwise<'a> {
    /// Register a Circle (a wall outlet switch) and returns a abstract representation of the
    /// Circle.
    fn create_circle(&self, mac: u64) -> io::Result<Box<Circle + 'a>>;
}

/// A abstract representation of the Plugwise Circle/Circle+.
pub trait Circle {
    /// Switch the relay of Circle on.
    fn switch_on(&self) -> io::Result<()>;
    /// Switch the relay of Circle off.
    fn switch_off(&self) -> io::Result<()>;
    /// Retrieve the relay status of the Circle.
    fn is_switched_on(&self) -> io::Result<bool>;
    /// Get actual power usage of the Circle in Watts (sampled over the last 8 seconds).
    fn get_actual_watt_usage(&self) -> io::Result<f64>;
    /// Get the actual clock state of the Circle (in UTC).
    fn get_clock(&self) -> io::Result<time::Tm>;
    /// Set the clock state of the Circle.
    fn set_clock(&self, tm: time::Tm) -> io::Result<()>;
    /// Retrieve a map of power usages over time. To retrieve only the last logged items specify
    /// the number of elements to retrieve in `max_entries`. Each entry contains the power usage of
    /// one hour.
    fn get_power_buffer(&self, max_entries: Option<u32>) -> io::Result<BTreeMap<time::Timespec, f64>>;
}

impl<'a, I:Read+Write+'a> Plugwise<'a> for PlugwiseInner<'a, I> {
    fn create_circle(&self, mac: u64) -> io::Result<Box<Circle+ 'a>> {
        let calibration_data = try!(self.protocol.borrow_mut().calibrate(mac));
        Ok(Box::new(CircleInner {
            protocol: self.protocol.clone(),
            mac: mac,
            calibration_data: calibration_data
        }))
    }
}

impl<'a, I:Read+Write+'a> Circle for CircleInner<'a, I> {
    fn switch_on(&self) -> io::Result<()> {
        try!(self.protocol.borrow_mut().switch(self.mac, true));
        Ok(())
    }

    fn switch_off(&self) -> io::Result<()> {
        try!(self.protocol.borrow_mut().switch(self.mac, false));
        Ok(())
    }

    fn is_switched_on(&self) -> io::Result<bool> {
        let info = try!(self.protocol.borrow_mut().get_info(self.mac));
        Ok(info.relay_state)
    }

    fn get_actual_watt_usage(&self) -> io::Result<f64> {
        let power_usage = try!(self.protocol.borrow_mut().get_power_usage(self.mac));
        Ok(power_usage.pulse_8s.to_watts(self.calibration_data))
    }

    fn get_clock(&self) -> io::Result<time::Tm> {
        let info = try!(self.protocol.borrow_mut().get_info(self.mac));
        let clock = try!(self.protocol.borrow_mut().get_clock_info(self.mac));

        let mut tm = match info.datetime.to_tm() {
            Some(tm) => tm,
            None => return Err(io::Error::new(io::ErrorKind::Other, "circle returns an invalid timestamp"))
        };
        tm.tm_sec = clock.second as i32;
        tm.tm_min = clock.minute as i32;
        tm.tm_hour = clock.hour as i32;
        tm.tm_wday = (clock.day_of_week % 7) as i32;
        Ok(tm)
    }

    fn set_clock(&self, tm: time::Tm) -> io::Result<()> {
        let clock_set = protocol::ReqClockSet::new_from_tm(tm);
        try!(self.protocol.borrow_mut().set_clock(self.mac, clock_set));
        Ok(())
    }

    fn get_power_buffer(&self,
                        max_entries: Option<u32>)
                        -> io::Result<BTreeMap<time::Timespec, f64>> {
        let mut result = BTreeMap::<time::Timespec, f64>::new();
        let info = try!(self.protocol.borrow_mut().get_info(self.mac));
        let start = match max_entries {
            None => 0,
            Some(n) => {
                let n_of_calls = n / 4; // each power buffer request retrieves 4 power usage statics
                if info.last_logaddr > n_of_calls {
                    info.last_logaddr - n_of_calls
                } else {
                    0
                }
            }
        };

        for index in (start..(info.last_logaddr + 1)) {
            let buffer = try!(self.protocol.borrow_mut().get_power_buffer(self.mac, index));

            self.get_power_buffer_helper(&mut result, &buffer.datetime1, &buffer.pulses1);
            self.get_power_buffer_helper(&mut result, &buffer.datetime2, &buffer.pulses2);
            self.get_power_buffer_helper(&mut result, &buffer.datetime3, &buffer.pulses3);
            self.get_power_buffer_helper(&mut result, &buffer.datetime4, &buffer.pulses4);
        }

        Ok(result)
    }
}

impl <'a, I:Read+Write+'a>  CircleInner<'a, I> {
    fn get_power_buffer_helper(&self,
                               map: &mut BTreeMap<time::Timespec, f64>,
                               datetime: &protocol::DateTime,
                               pulses: &protocol::Pulses) {
        if let Some(tm) = datetime.to_tm() {
            let _ = map.insert(tm.to_timespec(), pulses.to_kwh(self.calibration_data));
        }
    }
}

/// Specify which kind of Plugwise device to use
pub enum Device<'a> {
    /// Create a link to the Plugwise USB stick to communicate with the Circle/Circle+ wall
    /// outlets. The reference to the hardware device (i.e. `/dev/ttyUSB0`) must be provided.
    Serial(&'a str),
    /// Simular to `Serial` but with extra settings:
    ///
    SerialExt {
        /// USB serial device name
        port: &'a str,
        /// Timeout in milliseconds;
        timeout: time::Duration,
        /// Number of attempts to retry communication;
        retries: u8,
        /// Tracing settings (including a reference to a `io::Write` instance to log the
        /// communication)
        snoop: ProtocolSnoop<'a>
    },
    /// Create a simulation instance for development, testing and integration purposes
    Simulator,
}

/// Create instance to communicate against a (simulator) Plugwise USB stick and the associated
/// Circle/Circle+ devices.
///
/// Instantiate a link to a Plugwise device:
///
/// ```ignore
/// extern crate plugwise;
///
/// // Connect to a plugwise device
/// let serial = plugwise::plugwise(plugwise::Device::Serial("/dev/ttyUSB0")).unwrap();
/// // create a Circle (replace MAC address)
/// let circle = serial.create_circle(0x01234567890ABCDEF).unwrap();
/// // switch the Circle on
/// circle.switch_on().unwrap();
/// ```
///
/// Instantiate a simulation version:
///
/// ```
/// extern crate plugwise;
///
/// // instantiate a simulation version of Plugwise
/// let stub = plugwise::plugwise(plugwise::Device::Simulator).unwrap();
/// // create a Circle (simulation allows any MAC to be used)
/// let circle = stub.create_circle(0x01234567890ABCDEF).unwrap();
/// // switch the Circle on
/// circle.switch_on().unwrap();
/// ```
pub fn plugwise<'a>(device: Device<'a>) -> io::Result<Box<Plugwise<'a>+ 'a>> {
    match device {
        Device::Simulator => {
            let port = stub::Stub::new();
            let plugwise = try!(PlugwiseInner::initialize(port));
            Ok(Box::new(plugwise))
        },
        Device::Serial(port) => {
            plugwise(Device::SerialExt {
                port: port,
                timeout: Duration::milliseconds(1000),
                retries: 3,
                snoop: ProtocolSnoop::Nothing
            })
        },
        Device::SerialExt{port, timeout, retries, snoop} => {
            let mut port = try!(serial::open(port));
            try!(port.configure(|settings| {
                settings.set_baud_rate(serial::Baud115200);
                settings.set_char_size(serial::Bits8);
                settings.set_parity(serial::ParityNone);
                settings.set_stop_bits(serial::Stop1);
            }));

            port.set_timeout(timeout);
            let plugwise = try!(PlugwiseInner::initialize(port));
            plugwise.set_snoop(snoop);
            plugwise.set_retries(retries);

            Ok(Box::new(plugwise))
        },
    }
}

#[test]
fn smoke_external_stub() {
    let stub = plugwise(Device::Simulator).unwrap();
    let circle = stub.create_circle(0x01234567890ABCDEF).unwrap();
    circle.switch_on().unwrap();
    assert_eq!(circle.is_switched_on().unwrap(), true);
    circle.switch_off().unwrap();
    assert_eq!(circle.is_switched_on().unwrap(), false);
    circle.get_actual_watt_usage().unwrap();
    let tm = circle.get_clock().unwrap();
    circle.set_clock(tm).unwrap();
    circle.get_power_buffer(None).unwrap();
}
<|endoftext|>


<commit_before>// Hound -- A WAV encoding and decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License only.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Hound, a WAV encoding and decoding library.
//!
//! TODO: Add some introductory text here.
//!
//! Examples
//! ========
//!
//! The following example renders a 440 Hz sine wave, and stores it as as a
//! mono wav file with a sample rate of 44.1 kHz and 16 bits per sample.
//!
//! ```
//! use std::f32::consts::PI;
//! use std::i16;
//! use hound;
//!
//! let spec = hound::WavSpec {
//!     channels: 1,
//!     sample_rate: 44100,
//!     bits_per_sample: 16
//! };
//! let mut writer = hound::WavWriter::create("sine.wav", spec).unwrap();
//! for t in (0 .. 44100).map(|x| x as f32 / 44100.0) {
//!     let sample = (t * 440.0 * 2.0 * PI).sin();
//!     let amplitude = i16::MAX as f32;
//!     writer.write_sample((sample * amplitude) as i16).unwrap();
//! }
//! writer.finalize().unwrap();
//! ```
//!
//! The following example computes the RMS (root mean square) of an audio file.
//!
//! ```
//! use hound;
//!
//! let mut reader = hound::WavReader::open("testsamples/pop.wav").unwrap();
//! let (sqr_sum, n) = reader.samples::<i16>()
//!                          .fold((0_f64, 0_u32), |(sqr_sum, n), s| {
//!     let sample = s.unwrap() as f64;
//!     (sqr_sum + sample * sample, n + 1)
//! });
//! println!("RMS is {}", (sqr_sum / n as f64).sqrt());
//! ```

#![warn(missing_docs)]

use std::error;
use std::fmt;
use std::io;
use std::io::Write;
use std::result;
use read::ReadExt;
use write::WriteExt;

mod read;
mod write;

pub use read::{WavReader, WavSamples};
pub use write::WavWriter;

/// A type that can be used to represent audio samples.
pub trait Sample {
    /// Writes the audio sample to the WAVE data chunk.
    fn write<W: io::Write>(self, writer: &mut W, bits: u16) -> Result<()>;

    /// Reads the audio sample from the WAVE data chunk.
    fn read<R: io::Read>(reader: &mut R, bytes: u16, bits: u16) -> Result<Self>;
}

/// Converts an unsigned integer in the range 0-255 to a signed one in the range -128-127.
///
/// Presumably, the designers of the WAVE format did not like consistency. For
/// all bit depths except 8, samples are stored as little-endian _signed_
/// integers. However, an 8-bit sample is instead stored as an _unsigned_
/// integer. Hound abstracts away this idiosyncrasy by providing only signed
/// sample types.
fn signed_from_u8(x: u8) -> i8 {
    (x as i16 - 128) as i8
}

/// Converts a signed integer in the range -128-127 to an unsigned one in the range 0-255.
fn u8_from_signed(x: i8) -> u8 {
    (x as i16 + 128) as u8
}

#[test]
fn u8_sign_conversion_is_bijective() {
    for x in (0 .. 255) {
        assert_eq!(x, u8_from_signed(signed_from_u8(x)));
    }
    for x in (-128 .. 127) {
        assert_eq!(x, signed_from_u8(u8_from_signed(x)));
    }
}

impl Sample for i16 {
    fn write<W: io::Write>(self, writer: &mut W, bits: u16) -> Result<()> {
        match bits {
            // TODO: do a bounds check on the downcast, or disallow writing
            // wider types than the bits per sample in the spec beforehand.
            8 => Ok(try!(writer.write_u8(u8_from_signed(self as i8)))),
            16 => Ok(try!(writer.write_le_i16(self))),
            _ => Err(Error::Unsupported)
        }
    }

    fn read<R: io::Read>(reader: &mut R, bytes: u16, bits: u16) -> Result<i16> {
        match (bytes, bits) {
            (1, 8) => Ok(try!(reader.read_u8().map(signed_from_u8).map(|x| x as i16))),
            (2, 16) => Ok(try!(reader.read_le_i16())),
            // TODO: add a generic decoder for any bit depth.
            // TODO: differentiate between too wide and unsupported.
            _ => Err(Error::TooWide)
        }
    }
}

/// Specifies properties of the audio data.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct WavSpec {
    /// The number of channels.
    pub channels: u16,

    /// The number of samples per second.
    ///
    /// A common value is 44100, this is 44.1 kHz which is used for CD audio.
    pub sample_rate: u32,

    /// The number of bits per sample.
    ///
    /// A common value is 16 bits per sample, which is used for CD audio.
    pub bits_per_sample: u16
}

/// The error type for operations on `WavReader` and `WavWriter`.
#[derive(Debug)]
pub enum Error {
    /// An IO error occured in the underlying reader or writer.
    IoError(io::Error),
    /// Ill-formed WAVE data was encountered.
    FormatError(&'static str),
    /// The sample has more bits than the data type of the sample iterator.
    TooWide,
    /// The number of samples written is not a multiple of the number of channels.
    UnfinishedSample,
    /// The format is not supported.
    Unsupported
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter)
           -> result::Result<(), fmt::Error> {
        match *self {
            Error::IoError(ref err) => err.fmt(formatter),
            Error::FormatError(reason) => {
                try!(formatter.write_str("Ill-formed WAVE file: "));
                formatter.write_str(reason)
            },
            Error::TooWide => {
                formatter.write_str("The sample has more bits than the data type of the sample iterator.")
            },
            Error::UnfinishedSample => {
                formatter.write_str("The number of samples written is not a multiple of the number of channels.")
            },
            Error::Unsupported => {
                formatter.write_str("The wave format of the file is not supported.")
            }
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::IoError(ref err) => err.description(),
            Error::FormatError(reason) => reason,
            Error::TooWide => "the sample has more bits than the data type of the sample iterator",
            Error::UnfinishedSample => "the number of samples written is not a multiple of the number of channels",
            Error::Unsupported => "the wave format of the file is not supported"
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::IoError(ref err) => Some(err),
            Error::FormatError(_) => None,
            Error::TooWide => None,
            Error::UnfinishedSample => None,
            Error::Unsupported => None
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

/// A type for results generated by Hound where the error type is hard-wired.
pub type Result<T> = result::Result<T, Error>;

#[test]
fn write_read_is_lossless() {
    let mut buffer = io::Cursor::new(Vec::new());
    let write_spec = WavSpec {
        channels: 2,
        sample_rate: 44100,
        bits_per_sample: 16
    };

    {
        let mut writer = WavWriter::new(&mut buffer, write_spec);
        for s in (-1024_i16 .. 1024) {
            writer.write_sample(s).unwrap();
        }
        writer.finalize().unwrap();
    }

    {
        buffer.set_position(0);
        let mut reader = WavReader::new(&mut buffer).unwrap();
        assert_eq!(&write_spec, reader.spec());
        for (expected, read) in (-1024_i16 .. 1024).zip(reader.samples()) {
            assert_eq!(expected, read.unwrap());
        }
    }
}
<commit_msg>add test for reading and writing 8-bit data<commit_after>// Hound -- A WAV encoding and decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License only.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Hound, a WAV encoding and decoding library.
//!
//! TODO: Add some introductory text here.
//!
//! Examples
//! ========
//!
//! The following example renders a 440 Hz sine wave, and stores it as as a
//! mono wav file with a sample rate of 44.1 kHz and 16 bits per sample.
//!
//! ```
//! use std::f32::consts::PI;
//! use std::i16;
//! use hound;
//!
//! let spec = hound::WavSpec {
//!     channels: 1,
//!     sample_rate: 44100,
//!     bits_per_sample: 16
//! };
//! let mut writer = hound::WavWriter::create("sine.wav", spec).unwrap();
//! for t in (0 .. 44100).map(|x| x as f32 / 44100.0) {
//!     let sample = (t * 440.0 * 2.0 * PI).sin();
//!     let amplitude = i16::MAX as f32;
//!     writer.write_sample((sample * amplitude) as i16).unwrap();
//! }
//! writer.finalize().unwrap();
//! ```
//!
//! The following example computes the RMS (root mean square) of an audio file.
//!
//! ```
//! use hound;
//!
//! let mut reader = hound::WavReader::open("testsamples/pop.wav").unwrap();
//! let (sqr_sum, n) = reader.samples::<i16>()
//!                          .fold((0_f64, 0_u32), |(sqr_sum, n), s| {
//!     let sample = s.unwrap() as f64;
//!     (sqr_sum + sample * sample, n + 1)
//! });
//! println!("RMS is {}", (sqr_sum / n as f64).sqrt());
//! ```

#![warn(missing_docs)]

use std::error;
use std::fmt;
use std::io;
use std::io::Write;
use std::result;
use read::ReadExt;
use write::WriteExt;

mod read;
mod write;

pub use read::{WavReader, WavSamples};
pub use write::WavWriter;

/// A type that can be used to represent audio samples.
pub trait Sample {
    /// Writes the audio sample to the WAVE data chunk.
    fn write<W: io::Write>(self, writer: &mut W, bits: u16) -> Result<()>;

    /// Reads the audio sample from the WAVE data chunk.
    fn read<R: io::Read>(reader: &mut R, bytes: u16, bits: u16) -> Result<Self>;
}

/// Converts an unsigned integer in the range 0-255 to a signed one in the range -128-127.
///
/// Presumably, the designers of the WAVE format did not like consistency. For
/// all bit depths except 8, samples are stored as little-endian _signed_
/// integers. However, an 8-bit sample is instead stored as an _unsigned_
/// integer. Hound abstracts away this idiosyncrasy by providing only signed
/// sample types.
fn signed_from_u8(x: u8) -> i8 {
    (x as i16 - 128) as i8
}

/// Converts a signed integer in the range -128-127 to an unsigned one in the range 0-255.
fn u8_from_signed(x: i8) -> u8 {
    (x as i16 + 128) as u8
}

#[test]
fn u8_sign_conversion_is_bijective() {
    for x in (0 .. 255) {
        assert_eq!(x, u8_from_signed(signed_from_u8(x)));
    }
    for x in (-128 .. 127) {
        assert_eq!(x, signed_from_u8(u8_from_signed(x)));
    }
}

impl Sample for i16 {
    fn write<W: io::Write>(self, writer: &mut W, bits: u16) -> Result<()> {
        match bits {
            // TODO: do a bounds check on the downcast, or disallow writing
            // wider types than the bits per sample in the spec beforehand.
            8 => Ok(try!(writer.write_u8(u8_from_signed(self as i8)))),
            16 => Ok(try!(writer.write_le_i16(self))),
            _ => Err(Error::Unsupported)
        }
    }

    fn read<R: io::Read>(reader: &mut R, bytes: u16, bits: u16) -> Result<i16> {
        match (bytes, bits) {
            (1, 8) => Ok(try!(reader.read_u8().map(signed_from_u8).map(|x| x as i16))),
            (2, 16) => Ok(try!(reader.read_le_i16())),
            // TODO: add a generic decoder for any bit depth.
            // TODO: differentiate between too wide and unsupported.
            _ => Err(Error::TooWide)
        }
    }
}

/// Specifies properties of the audio data.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct WavSpec {
    /// The number of channels.
    pub channels: u16,

    /// The number of samples per second.
    ///
    /// A common value is 44100, this is 44.1 kHz which is used for CD audio.
    pub sample_rate: u32,

    /// The number of bits per sample.
    ///
    /// A common value is 16 bits per sample, which is used for CD audio.
    pub bits_per_sample: u16
}

/// The error type for operations on `WavReader` and `WavWriter`.
#[derive(Debug)]
pub enum Error {
    /// An IO error occured in the underlying reader or writer.
    IoError(io::Error),
    /// Ill-formed WAVE data was encountered.
    FormatError(&'static str),
    /// The sample has more bits than the data type of the sample iterator.
    TooWide,
    /// The number of samples written is not a multiple of the number of channels.
    UnfinishedSample,
    /// The format is not supported.
    Unsupported
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter)
           -> result::Result<(), fmt::Error> {
        match *self {
            Error::IoError(ref err) => err.fmt(formatter),
            Error::FormatError(reason) => {
                try!(formatter.write_str("Ill-formed WAVE file: "));
                formatter.write_str(reason)
            },
            Error::TooWide => {
                formatter.write_str("The sample has more bits than the data type of the sample iterator.")
            },
            Error::UnfinishedSample => {
                formatter.write_str("The number of samples written is not a multiple of the number of channels.")
            },
            Error::Unsupported => {
                formatter.write_str("The wave format of the file is not supported.")
            }
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::IoError(ref err) => err.description(),
            Error::FormatError(reason) => reason,
            Error::TooWide => "the sample has more bits than the data type of the sample iterator",
            Error::UnfinishedSample => "the number of samples written is not a multiple of the number of channels",
            Error::Unsupported => "the wave format of the file is not supported"
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::IoError(ref err) => Some(err),
            Error::FormatError(_) => None,
            Error::TooWide => None,
            Error::UnfinishedSample => None,
            Error::Unsupported => None
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

/// A type for results generated by Hound where the error type is hard-wired.
pub type Result<T> = result::Result<T, Error>;

#[test]
fn write_read_i16_is_lossless() {
    let mut buffer = io::Cursor::new(Vec::new());
    let write_spec = WavSpec {
        channels: 2,
        sample_rate: 44100,
        bits_per_sample: 16
    };

    {
        let mut writer = WavWriter::new(&mut buffer, write_spec);
        for s in (-1024_i16 .. 1024) {
            writer.write_sample(s).unwrap();
        }
        writer.finalize().unwrap();
    }

    {
        buffer.set_position(0);
        let mut reader = WavReader::new(&mut buffer).unwrap();
        assert_eq!(&write_spec, reader.spec());
        for (expected, read) in (-1024_i16 .. 1024).zip(reader.samples()) {
            assert_eq!(expected, read.unwrap());
        }
    }
}

#[test]
fn write_read_i8_is_lossless() {
    let mut buffer = io::Cursor::new(Vec::new());
    let write_spec = WavSpec {
        channels: 16,
        sample_rate: 48000,
        bits_per_sample: 8
    };

    // Write `i8` samples.
    {
        let mut writer = WavWriter::new(&mut buffer, write_spec);
        for s in (-128 .. 127 + 1) {
            // TODO: implement `Sample` for `i8`.
            writer.write_sample(s as i16).unwrap();
        }
        writer.finalize().unwrap();
    }

    // Then read them into `i16`.
    {
        buffer.set_position(0);
        let mut reader = WavReader::new(&mut buffer).unwrap();
        assert_eq!(&write_spec, reader.spec());
        for (expected, read) in (-128_i16 .. 127 + 1).zip(reader.samples()) {
            assert_eq!(expected, read.unwrap());
        }
    }
}
<|endoftext|>


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

#![feature(test)]
//extern crate rand;
extern crate test;

use test::Bencher;

#[test]
fn is_it_a_prime_number() {
    assert!(is_prime(5));
    assert!(is_prime_why_not(5));
}

#[test]
fn should_not_be_a_prime_number() {
    assert_eq!(false, is_prime(4));
    assert_eq!(false, is_prime_why_not(4));
}

#[test]
fn prime_factorization_test(){
    let mut vec = Vec::new();
    vec.push(2);
    vec.push(2);
    vec.push(2);
    vec.push(3);
    vec.push(7);
    assert_eq!(vec, prime_factorization(168));
    vec = Vec::new();
    vec.push(2);
    vec.push(3);
    vec.push(17);
    assert_eq!(vec, prime_factorization(102));
}

#[test]
fn get_next_prime_number_test() {
    assert_eq!(79, get_next_prime_number(73));
}

#[test]
fn get_twin_primes_test() {
    assert_eq!((5, 7), get_twin_primes(5));
}

#[test]
fn greatest_common_factor_test() {
    assert_eq!(6, greatest_common_factor(18,24));
}

#[test]
fn least_common_multiple_test() {
    assert_eq!(90, least_common_multiple(18,30));
}

#[test]
fn number_of_primes_test() {
    assert_eq!(489, number_of_primes(1,3500));
}

#[test]
fn number_of_factors_test() {
    assert_eq!(12, number_of_factors(72));
}

#[test]
fn mersenne_prime_test() {
    let mersenne_prime = mersenne_prime(5);
    assert_eq!(31, mersenne_prime);
}

#[test]
fn generate_primes_test() {
    let result = generate_primes(3500);
    assert_eq!(489, result.len());
}

//#[bench]
//fn bench_is_prime(b: &mut Bencher) {
//    b.iter(|| is_prime(rand::random::<i32>()));
//}

/// Tests for prime numbers.
///
/// # Examples
///
/// ```
/// use primapalooza::is_prime;
///
/// println!("{}", primapalooza::is_prime(5));
///
pub fn is_prime(x: i32) -> bool {
    if x < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let mut start: i64 = 2;
    while start <= (x as f64).sqrt() as i64 {
        if (x as i64) % start < 1 {
            return false;
        }
        start += 1;
    }
    return x > 1;
}

//#[bench]
//fn bench_is_prime_why_not(b: &mut Bencher) {
//      b.iter(||
//             for n in (0..10) {
//                test::black_box(is_prime_why_not(n));
//             });
//}

/// Tests for prime numbers and state why its not a prime number.
///
/// # Examples
///
/// ```
/// use primapalooza::is_prime_why_not;
///
/// println!("{}", primapalooza::is_prime_why_not(9));
///
pub fn is_prime_why_not(x: i32) -> bool {
    if x < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let mut start: i64 = 2;
    let mut return_value: bool = true;
    while start <= (x as f64).sqrt() as i64 {
        let m = (x as i64) % start;
        if m < 1 {
            println!("{} is divisible by {}.  {} * {} = {}", x, start, start, ((x as i64) / start), x);
            return_value = false;
        }
        start += 1;
    }
    if return_value == true {
        return_value = x > 1;
    }
    return return_value;
}

//#[bench]
//fn bench_get_next_prime_number(b: &mut Bencher) {
//    b.iter(||
//           for n in (1..10) {
//               test::black_box(get_next_prime_number(n));
//           });
//}

/// Returns the next available prime number.
///
/// # Examples
///
/// ```
/// use primapalooza::get_next_prime_number;
///
/// println!("{}", primapalooza::get_next_prime_number(9));
///
pub fn get_next_prime_number(n:i32) -> i32 {
    if n < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let mut x: i32 = n;
    x += 1;
    while !is_prime(x) {
        x += 1;
    }
    return x;
}

/// Returns the twin primes.  A pair of prime numbers that differ by 2.
///
/// # Examples
///
/// ```
/// use primapalooza::get_twin_primes;
///
/// println!("{:?}", primapalooza::get_twin_primes(5));
///
pub fn get_twin_primes(n: i32) -> (i32, i32){
    if !is_prime(n) {
        panic!("prime number required as input");
    }
    return (n, get_next_prime_number(n));
}

//#[bench]
//fn bench_prime_factorization(b: &mut Bencher) {
//    b.iter(||
//           for n in (1..10) {
//                test::black_box(prime_factorization(n));
//           });
//}

/// Perform a prime factorization.
///
/// # Examples
///
/// ```
/// use primapalooza::prime_factorization;
///
/// println!("{:?}", primapalooza::prime_factorization(168));
///
pub fn prime_factorization(n:i32) -> Vec<i64> {
    if n < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let mut x:i64 = n as i64;
    let mut return_value = Vec::new();
    let mut start:i64 = 2;
    while !is_prime(x as i32) {
        let m = x % start;
        if m < 1 {
            return_value.push(start);
            x = x / start;
        } else {
            let s = start as i32;
            start = get_next_prime_number(s) as i64;                                                                  }
    }
    return_value.push(x);
    return return_value;
}

/// Perform a greatest common factor(gcf) calculation.
///
/// # Examples
///
/// ```
/// use primapalooza::greatest_common_factor;
///
/// println!("{}", primapalooza::greatest_common_factor(18, 24));
///
pub fn greatest_common_factor(x:i32, y:i32) -> i32 {
    if x < 2 || y < 2 {
        panic!("requires a positive integers greater then 1");
    }
    let mut vec_x = prime_factorization(x);
    let mut vec_y = prime_factorization(y);
    vec_x.dedup();
    vec_y.dedup();
    let mut m:Vec<i32> = Vec::new();
    for p in vec_x.iter() {
        for q in vec_y.iter() {
            if p == q {
                m.push(*p as i32);
            }
        }
    }
    let mut return_value = 1;
    for k in &m {
        return_value = return_value * k;
    }
    return return_value;
}

/// Perform a least common multiple(lcm) calculation.
///
/// # Examples
///
/// ```
/// use primapalooza::least_common_multiple;
///
/// println!("{}", primapalooza::least_common_multiple(18, 24));
///
pub fn least_common_multiple(x:i32, y:i32) -> i32 {
    if x < 2 || y < 2 {
        panic!("requires a positive integers greater then 1");
    }
    let gcf = greatest_common_factor(x, y);
    if x % gcf < 1 {
        (x/gcf) * y
    } else {
        (y/gcf) * x
    }
}

/// Number of prime numbers within a range.
///
/// # Examples
///
/// ```
/// use primapalooza::number_of_primes;
///
/// println!("{}", primapalooza::number_of_primes(1, 3500));
///
pub fn number_of_primes(x: i32, y: i32) -> i32 {
    if x < 1 {
        panic!("requires a positive integers");
    }
    if y < 2 {
        panic!("requires a positive integer greater than 1");
    }
    let mut a = x;
    if a == 1 {
        a += 1;
    }
    let mut z = 0;
    for n in a..y {
        if is_prime(n) {
            z += 1
        }
    }
    return z;
}

/// The number of factors in a number.
///
/// # Examples
///
/// ```
/// use primapalooza::number_of_factors;
///
/// println!("{}", primapalooza::number_of_factors(72));
///
pub fn number_of_factors(n: i32) -> i32 {
    if n < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let prime_factors = prime_factorization(n);
    let mut factors = prime_factors.clone();
    factors.dedup();
    let mut return_value = 1;
    for f in factors.iter() {
        let mut count = 1;
        for pf in prime_factors.iter() {
            if pf == f {
                count += 1;
            }
        }
        return_value = return_value * count;
    }
    return return_value;
}

/// Generate a mersenne prime from a prime number.
///
/// # Examples
///
/// ```
/// use primapalooza::mersenne_prime;
///
/// let results = primapalooza::mersenne_prime(5);
pub fn mersenne_prime(n: i32) -> i32 {
    if n < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let two:i32 = 2;
    let result:i32 = (two.pow(n as u32)) - 1;
    return result;
}

/// Generate a collection of prime numbers up to a particular limit.
///
/// # Examples
///
/// ```
/// use primapalooza::generate_primes;
///
/// let results = primapalooza::generate_primes(1000);
/// for x in results.iter() {
///     println!("{}", x);
/// }
pub fn generate_primes(limit: i64) -> Vec<i64> {
    if limit < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let sqrtlim: i64 = (limit as f64).sqrt() as i64;
    let mut pp: i64 = 2;
    let mut ss = vec![pp];
    let mut ep = vec![pp];
    pp += 1;
    let mut rss = vec![ss[0]];
    let mut tp = vec![pp];
    let mut i = 0;
    let ssr = rss[i] * tp[0];
    rss.push(ssr);
    let mut xp = vec![];
    pp += ss[0];
    let mut npp: i64 = pp;
    tp.push(npp);
    while npp < limit {
        i += 1;
        while npp < (rss[i] + 1) {
            for n in ss.iter() {
                npp = pp + n;
                if npp > limit {
                    break;
                }
                if npp <= (rss[i] + 1) {
                    pp = npp;
                }
                let sqrtnpp = (npp as f64).sqrt();
                let mut test = true;
                for q in tp.iter() {
                    if sqrtnpp < (*q as f64) {
                        break;
                    } else if npp % q == 0 {
                        test = false;
                        break;
                    }
                }
                if test {
                    if npp <= sqrtlim {
                        tp.push(npp);
                    } else {
                        xp.push(npp);
                    }
                }
            }
            if npp > limit {
                break;
            }
        }
        if npp > limit {
            break;
        }
        let mut lrpp = pp;
        let mut nss = vec![];
        while pp < (rss[i] + 1) * 2 - 1 {
            for n in ss.iter() {
                npp = pp + n;
                    if npp > limit {
                        break;
                    }
                    let sqrtnpp = (npp as f64).sqrt();
                    let mut test = true;
                    for q in tp.iter() {
                        if sqrtnpp < (*q as f64) {
                            break;
                        } else if npp % q == 0 {
                            test = false;
                            break;
                        }
                    }
                    if test {
                        if npp <= sqrtlim {
                            tp.push(npp);
                        } else {
                            xp.push(npp);
                        }
                    }
                    if npp % tp[0] != 0 {
                        nss.push(npp - lrpp);
                        lrpp = npp;
                    }
                    pp = npp;
                    if npp % tp[0] != 0 {
                        nss.push(npp - lrpp);
                        lrpp = npp;
                    }
                if npp > limit {
                    break;
                }
            }
            if npp > limit {
                break;
            }
        }
        ss = nss;
        ep.push(tp[0]);
        tp.remove(0);
        let ssr = rss[i] * tp[0];
        rss.push(ssr);
        npp = lrpp;
    }
    ep.reverse();
    for a in ep.iter() {
        tp.insert(0, *a);
    }
    tp.reverse();
    for a in tp.iter() {
        xp.insert(0, *a);
    }
    xp.dedup();
    return xp;
}
<commit_msg>added perfect_number<commit_after>#![allow(dead_code)]
#![allow(unused_imports)]

#![feature(test)]
//extern crate rand;
extern crate test;

use test::Bencher;

#[test]
fn is_it_a_prime_number() {
    assert!(is_prime(5));
    assert!(is_prime_why_not(5));
}

#[test]
fn should_not_be_a_prime_number() {
    assert_eq!(false, is_prime(4));
    assert_eq!(false, is_prime_why_not(4));
}

#[test]
fn prime_factorization_test(){
    let mut vec = Vec::new();
    vec.push(2);
    vec.push(2);
    vec.push(2);
    vec.push(3);
    vec.push(7);
    assert_eq!(vec, prime_factorization(168));
    vec = Vec::new();
    vec.push(2);
    vec.push(3);
    vec.push(17);
    assert_eq!(vec, prime_factorization(102));
}

#[test]
fn get_next_prime_number_test() {
    assert_eq!(79, get_next_prime_number(73));
}

#[test]
fn get_twin_primes_test() {
    assert_eq!((5, 7), get_twin_primes(5));
}

#[test]
fn greatest_common_factor_test() {
    assert_eq!(6, greatest_common_factor(18,24));
}

#[test]
fn least_common_multiple_test() {
    assert_eq!(90, least_common_multiple(18,30));
}

#[test]
fn number_of_primes_test() {
    assert_eq!(489, number_of_primes(1,3500));
}

#[test]
fn number_of_factors_test() {
    assert_eq!(12, number_of_factors(72));
}

#[test]
fn mersenne_prime_test() {
    let mersenne_prime = mersenne_prime(5);
    assert_eq!(31, mersenne_prime);
}

#[test]
fn perfect_number_test() {
    assert!(perfect_number(5));
    assert_eq!(false, perfect_number(11));
}

#[test]
fn generate_primes_test() {
    let result = generate_primes(3500);
    assert_eq!(489, result.len());
}

//#[bench]
//fn bench_is_prime(b: &mut Bencher) {
//    b.iter(|| is_prime(rand::random::<i32>()));
//}

/// Tests for prime numbers.
///
/// # Examples
///
/// ```
/// use primapalooza::is_prime;
///
/// println!("{}", primapalooza::is_prime(5));
///
pub fn is_prime(x: i32) -> bool {
    if x < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let mut start: i64 = 2;
    while start <= (x as f64).sqrt() as i64 {
        if (x as i64) % start < 1 {
            return false;
        }
        start += 1;
    }
    return x > 1;
}

//#[bench]
//fn bench_is_prime_why_not(b: &mut Bencher) {
//      b.iter(||
//             for n in (0..10) {
//                test::black_box(is_prime_why_not(n));
//             });
//}

/// Tests for prime numbers and state why its not a prime number.
///
/// # Examples
///
/// ```
/// use primapalooza::is_prime_why_not;
///
/// println!("{}", primapalooza::is_prime_why_not(9));
///
pub fn is_prime_why_not(x: i32) -> bool {
    if x < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let mut start: i64 = 2;
    let mut return_value: bool = true;
    while start <= (x as f64).sqrt() as i64 {
        let m = (x as i64) % start;
        if m < 1 {
            println!("{} is divisible by {}.  {} * {} = {}", x, start, start, ((x as i64) / start), x);
            return_value = false;
        }
        start += 1;
    }
    if return_value == true {
        return_value = x > 1;
    }
    return return_value;
}

//#[bench]
//fn bench_get_next_prime_number(b: &mut Bencher) {
//    b.iter(||
//           for n in (1..10) {
//               test::black_box(get_next_prime_number(n));
//           });
//}

/// Returns the next available prime number.
///
/// # Examples
///
/// ```
/// use primapalooza::get_next_prime_number;
///
/// println!("{}", primapalooza::get_next_prime_number(9));
///
pub fn get_next_prime_number(n:i32) -> i32 {
    if n < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let mut x: i32 = n;
    x += 1;
    while !is_prime(x) {
        x += 1;
    }
    return x;
}

/// Returns the twin primes.  A pair of prime numbers that differ by 2.
///
/// # Examples
///
/// ```
/// use primapalooza::get_twin_primes;
///
/// println!("{:?}", primapalooza::get_twin_primes(5));
///
pub fn get_twin_primes(n: i32) -> (i32, i32){
    if !is_prime(n) {
        panic!("prime number required as input");
    }
    return (n, get_next_prime_number(n));
}

//#[bench]
//fn bench_prime_factorization(b: &mut Bencher) {
//    b.iter(||
//           for n in (1..10) {
//                test::black_box(prime_factorization(n));
//           });
//}

/// Perform a prime factorization.
///
/// # Examples
///
/// ```
/// use primapalooza::prime_factorization;
///
/// println!("{:?}", primapalooza::prime_factorization(168));
///
pub fn prime_factorization(n:i32) -> Vec<i64> {
    if n < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let mut x:i64 = n as i64;
    let mut return_value = Vec::new();
    let mut start:i64 = 2;
    while !is_prime(x as i32) {
        let m = x % start;
        if m < 1 {
            return_value.push(start);
            x = x / start;
        } else {
            let s = start as i32;
            start = get_next_prime_number(s) as i64;                                                                  }
    }
    return_value.push(x);
    return return_value;
}

/// Perform a greatest common factor(gcf) calculation.
///
/// # Examples
///
/// ```
/// use primapalooza::greatest_common_factor;
///
/// println!("{}", primapalooza::greatest_common_factor(18, 24));
///
pub fn greatest_common_factor(x:i32, y:i32) -> i32 {
    if x < 2 || y < 2 {
        panic!("requires a positive integers greater then 1");
    }
    let mut vec_x = prime_factorization(x);
    let mut vec_y = prime_factorization(y);
    vec_x.dedup();
    vec_y.dedup();
    let mut m:Vec<i32> = Vec::new();
    for p in vec_x.iter() {
        for q in vec_y.iter() {
            if p == q {
                m.push(*p as i32);
            }
        }
    }
    let mut return_value = 1;
    for k in &m {
        return_value = return_value * k;
    }
    return return_value;
}

/// Perform a least common multiple(lcm) calculation.
///
/// # Examples
///
/// ```
/// use primapalooza::least_common_multiple;
///
/// println!("{}", primapalooza::least_common_multiple(18, 24));
///
pub fn least_common_multiple(x:i32, y:i32) -> i32 {
    if x < 2 || y < 2 {
        panic!("requires a positive integers greater then 1");
    }
    let gcf = greatest_common_factor(x, y);
    if x % gcf < 1 {
        (x/gcf) * y
    } else {
        (y/gcf) * x
    }
}

/// Number of prime numbers within a range.
///
/// # Examples
///
/// ```
/// use primapalooza::number_of_primes;
///
/// println!("{}", primapalooza::number_of_primes(1, 3500));
///
pub fn number_of_primes(x: i32, y: i32) -> i32 {
    if x < 1 {
        panic!("requires a positive integers");
    }
    if y < 2 {
        panic!("requires a positive integer greater than 1");
    }
    let mut a = x;
    if a == 1 {
        a += 1;
    }
    let mut z = 0;
    for n in a..y {
        if is_prime(n) {
            z += 1
        }
    }
    return z;
}

/// The number of factors in a number.
///
/// # Examples
///
/// ```
/// use primapalooza::number_of_factors;
///
/// println!("{}", primapalooza::number_of_factors(72));
///
pub fn number_of_factors(n: i32) -> i32 {
    if n < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let prime_factors = prime_factorization(n);
    let mut factors = prime_factors.clone();
    factors.dedup();
    let mut return_value = 1;
    for f in factors.iter() {
        let mut count = 1;
        for pf in prime_factors.iter() {
            if pf == f {
                count += 1;
            }
        }
        return_value = return_value * count;
    }
    return return_value;
}

/// Generate a mersenne prime from a prime number.
///
/// # Examples
///
/// ```
/// use primapalooza::mersenne_prime;
///
/// let results = primapalooza::mersenne_prime(5);
pub fn mersenne_prime(n: i32) -> i32 {
    if n < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let two:i32 = 2;
    let result:i32 = (two.pow(n as u32)) - 1;
    return result;
}

/// Is a number a perfect number.  The sum of its factors is the number itself.
///
/// # Examples
///
/// ```
/// use primapalooza::perfect_number;
///
/// println!("{}", primapalooza::perfect_number(5));
pub fn perfect_number(n:i32) -> bool {
    return is_prime(mersenne_prime(n));
}

/// Generate a collection of prime numbers up to a particular limit.
///
/// # Examples
///
/// ```
/// use primapalooza::generate_primes;
///
/// let results = primapalooza::generate_primes(1000);
/// for x in results.iter() {
///     println!("{}", x);
/// }
pub fn generate_primes(limit: i64) -> Vec<i64> {
    if limit < 2 {
        panic!("requires a positive integer greater then 1");
    }
    let sqrtlim: i64 = (limit as f64).sqrt() as i64;
    let mut pp: i64 = 2;
    let mut ss = vec![pp];
    let mut ep = vec![pp];
    pp += 1;
    let mut rss = vec![ss[0]];
    let mut tp = vec![pp];
    let mut i = 0;
    let ssr = rss[i] * tp[0];
    rss.push(ssr);
    let mut xp = vec![];
    pp += ss[0];
    let mut npp: i64 = pp;
    tp.push(npp);
    while npp < limit {
        i += 1;
        while npp < (rss[i] + 1) {
            for n in ss.iter() {
                npp = pp + n;
                if npp > limit {
                    break;
                }
                if npp <= (rss[i] + 1) {
                    pp = npp;
                }
                let sqrtnpp = (npp as f64).sqrt();
                let mut test = true;
                for q in tp.iter() {
                    if sqrtnpp < (*q as f64) {
                        break;
                    } else if npp % q == 0 {
                        test = false;
                        break;
                    }
                }
                if test {
                    if npp <= sqrtlim {
                        tp.push(npp);
                    } else {
                        xp.push(npp);
                    }
                }
            }
            if npp > limit {
                break;
            }
        }
        if npp > limit {
            break;
        }
        let mut lrpp = pp;
        let mut nss = vec![];
        while pp < (rss[i] + 1) * 2 - 1 {
            for n in ss.iter() {
                npp = pp + n;
                    if npp > limit {
                        break;
                    }
                    let sqrtnpp = (npp as f64).sqrt();
                    let mut test = true;
                    for q in tp.iter() {
                        if sqrtnpp < (*q as f64) {
                            break;
                        } else if npp % q == 0 {
                            test = false;
                            break;
                        }
                    }
                    if test {
                        if npp <= sqrtlim {
                            tp.push(npp);
                        } else {
                            xp.push(npp);
                        }
                    }
                    if npp % tp[0] != 0 {
                        nss.push(npp - lrpp);
                        lrpp = npp;
                    }
                    pp = npp;
                    if npp % tp[0] != 0 {
                        nss.push(npp - lrpp);
                        lrpp = npp;
                    }
                if npp > limit {
                    break;
                }
            }
            if npp > limit {
                break;
            }
        }
        ss = nss;
        ep.push(tp[0]);
        tp.remove(0);
        let ssr = rss[i] * tp[0];
        rss.push(ssr);
        npp = lrpp;
    }
    ep.reverse();
    for a in ep.iter() {
        tp.insert(0, *a);
    }
    tp.reverse();
    for a in tp.iter() {
        xp.insert(0, *a);
    }
    xp.dedup();
    return xp;
}
<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate libc;

use std::ffi::{ CString, c_str_to_bytes};
use std::str::from_utf8;
use std::ops::Drop;
use self::libc::{ c_void };

mod dt;

pub struct Zjs {
    vm: *const c_void
}

impl Zjs {
    pub fn new() -> Zjs {
        let vm = unsafe { dt::create_vm() };
        Zjs { vm: vm }
    }
    pub fn run(&self, javascript: &str) -> String {
        let c_code = CString::from_slice(javascript.as_bytes());
        let c_code_ptr = c_code.as_ptr();
        let c_result = unsafe { dt::eval(self.vm, c_code_ptr) };
        let result_bytes = unsafe { c_str_to_bytes(&c_result) };

        // FIXME: CESU-8 to UTF-8 conversion
        // TODO: handle error states
        let result = from_utf8(result_bytes);
        assert_eq!(result.is_ok(), true);
        let result_option = result.ok();
        assert_eq!(result_option.is_some(), true);
        String::from_str(result_option.unwrap())
    }
}

impl Drop for Zjs {
    fn drop(&mut self) {
        unsafe {
            dt::destroy_vm(self.vm);
        }
    }
}

#[test]
fn test_public_api() {
    let code = "(function () { return '12'; })()";
    let zjs = Zjs::new();
    let result: String = zjs.run(code);
    assert_eq!(result.as_slice(), "12");
}

pub fn dt_hello_world() {
    unsafe {
        let vm = dt::create_vm();
        let code = "(function () { return '12'; })()";
        let c_code = CString::from_slice(code.as_bytes());
        let c_result = dt::eval(vm, c_code.as_ptr());
        // FIXME: CESU-8 to UTF-8 conversion
        // TODO: handle error states
        let result = String::from_str(from_utf8(c_str_to_bytes(&c_result)).ok().unwrap());
        assert_eq!(result.as_slice(), "12");
        dt::destroy_vm(vm);
    }
}

#[test]
fn test_binding() {
    dt_hello_world();
}
<commit_msg>Remove low-level test<commit_after>#![allow(unstable)]

extern crate libc;

use std::ffi::{ CString, c_str_to_bytes};
use std::str::from_utf8;
use std::ops::Drop;
use self::libc::{ c_void };

mod dt;

pub struct Zjs {
    vm: *const c_void
}

impl Zjs {
    pub fn new() -> Zjs {
        let vm = unsafe { dt::create_vm() };
        Zjs { vm: vm }
    }
    pub fn run(&self, javascript: &str) -> String {
        let c_code = CString::from_slice(javascript.as_bytes());
        let c_code_ptr = c_code.as_ptr();
        let c_result = unsafe { dt::eval(self.vm, c_code_ptr) };
        let result_bytes = unsafe { c_str_to_bytes(&c_result) };

        // FIXME: CESU-8 to UTF-8 conversion
        // TODO: handle error states
        let result = from_utf8(result_bytes);
        assert_eq!(result.is_ok(), true);
        let result_option = result.ok();
        assert_eq!(result_option.is_some(), true);
        String::from_str(result_option.unwrap())
    }
}

impl Drop for Zjs {
    fn drop(&mut self) {
        unsafe {
            dt::destroy_vm(self.vm);
        }
    }
}

#[test]
fn test_public_api() {
    let code = "(function () { return '12'; })()";
    let zjs = Zjs::new();
    let result: String = zjs.run(code);
    assert_eq!(result.as_slice(), "12");
}
<|endoftext|>


<commit_before>#![allow(clippy::non_ascii_literal)]

#[macro_use]
extern crate seed;

use seed::prelude::*;

pub mod pages;

#[derive(Copy, Clone)]
pub enum Page {
    ContactUs,
    Downloads,
    Faq,
    Home,
    Status,
    FermatArchive,
    /*
    NumberCruncher,
    PrimalityChecker,
    PrimeNumbersArchive,
    MersennePrimeArchive,
    PerfectArchive,
    FibonacciArchive*/
    //Article(article::slug::Slug),
}

// Model
struct Model {
    page: Page,
}

// Setup a default here, for initialization later.
impl Default for Model {
    fn default() -> Self {
        Self {
            page: Page::Home,
        }
    }
}

// Update
#[derive(Clone)]
pub enum Msg {
    ChangePage(Page),
}

/// The sole source of updating the model
fn update(msg: Msg, model: &mut Model, _: &mut Orders<Msg>) {
    match msg {
        Msg::ChangePage(page) => model.page = page
    }
}

/// The top-level component we pass to the virtual dom. Must accept the model as its
/// only argument, and output has to implement trait `ElContainer`.
fn view(model: &Model) -> impl View<Msg> {
    match model.page {
        Page::ContactUs => pages::contact::render(),
        Page::Downloads => pages::downloads::render(),
        Page::Faq => pages::faq::render(),
        Page::FermatArchive => pages::archive::fermat::render(),
        Page::Home => pages::home::render(),
        Page::Status => pages::status::render(),
    }
}

impl ToString for Page {
    fn to_string(&self) -> String {
        // Eg for url routing
        match self {
            Page::ContactUs => "contactus".into(),
            Page::Downloads => "downloads".into(),
            Page::Faq => "faq".into(),
            Page::FermatArchive => "fermat".into(),
            Page::Home => "home".into(),
            Page::Status => "status".into(),
        }
    }
}

fn routes(url: seed::Url) -> Msg {
    if url.path.is_empty() {
        return Msg::ChangePage(Page::Home)
    }

    match url.path[0].as_ref() {
        "archive" => {
            // Determine if we are at the archive page, or a subpage
            match url.path[1].as_ref() {
                "fermat" => Msg::ChangePage(Page::FermatArchive),
                _ => Msg::ChangePage(Page::Home)//TODO: add archive page
            }
        },
        "archive/fermat" => Msg::ChangePage(Page::FermatArchive),
        "contactus" => Msg::ChangePage(Page::ContactUs),
        "downloads" => Msg::ChangePage(Page::Downloads),
        "faq" => Msg::ChangePage(Page::Faq),
        "status" => Msg::ChangePage(Page::Status),
        _ => Msg::ChangePage(Page::Home)
    }
}

#[wasm_bindgen(start)]
pub fn render() {
    seed::App::build(Model::default(), update, view)
        .mount("app")
        .routes(routes)
        //.window_events(window_events)
        .finish()
        .run();
}<commit_msg>Removed superfloud/duplicate entry for fermat url<commit_after>#![allow(clippy::non_ascii_literal)]

#[macro_use]
extern crate seed;

use seed::prelude::*;

pub mod pages;

#[derive(Copy, Clone)]
pub enum Page {
    ContactUs,
    Downloads,
    Faq,
    Home,
    Status,
    FermatArchive,
    /*
    NumberCruncher,
    PrimalityChecker,
    PrimeNumbersArchive,
    MersennePrimeArchive,
    PerfectArchive,
    FibonacciArchive*/
    //Article(article::slug::Slug),
}

// Model
struct Model {
    page: Page,
}

// Setup a default here, for initialization later.
impl Default for Model {
    fn default() -> Self {
        Self {
            page: Page::Home,
        }
    }
}

// Update
#[derive(Clone)]
pub enum Msg {
    ChangePage(Page),
}

/// The sole source of updating the model
fn update(msg: Msg, model: &mut Model, _: &mut Orders<Msg>) {
    match msg {
        Msg::ChangePage(page) => model.page = page
    }
}

/// The top-level component we pass to the virtual dom. Must accept the model as its
/// only argument, and output has to implement trait `ElContainer`.
fn view(model: &Model) -> impl View<Msg> {
    match model.page {
        Page::ContactUs => pages::contact::render(),
        Page::Downloads => pages::downloads::render(),
        Page::Faq => pages::faq::render(),
        Page::FermatArchive => pages::archive::fermat::render(),
        Page::Home => pages::home::render(),
        Page::Status => pages::status::render(),
    }
}

impl ToString for Page {
    fn to_string(&self) -> String {
        // Eg for url routing
        match self {
            Page::ContactUs => "contactus".into(),
            Page::Downloads => "downloads".into(),
            Page::Faq => "faq".into(),
            Page::FermatArchive => "fermat".into(),
            Page::Home => "home".into(),
            Page::Status => "status".into(),
        }
    }
}

fn routes(url: seed::Url) -> Msg {
    if url.path.is_empty() {
        return Msg::ChangePage(Page::Home)
    }

    match url.path[0].as_ref() {
        "archive" => {
            // Determine if we are at the archive page, or a subpage
            match url.path[1].as_ref() {
                "fermat" => Msg::ChangePage(Page::FermatArchive),
                _ => Msg::ChangePage(Page::Home)//TODO: add archive page
            }
        },
        "contactus" => Msg::ChangePage(Page::ContactUs),
        "downloads" => Msg::ChangePage(Page::Downloads),
        "faq" => Msg::ChangePage(Page::Faq),
        "status" => Msg::ChangePage(Page::Status),
        _ => Msg::ChangePage(Page::Home)
    }
}

#[wasm_bindgen(start)]
pub fn render() {
    seed::App::build(Model::default(), update, view)
        .mount("app")
        .routes(routes)
        //.window_events(window_events)
        .finish()
        .run();
}<|endoftext|>


<commit_before>//! A crate that re-exports various types defined in both `libc` and `winapi`.
//!
//! Stop having to write code like this:
//!
//! ```ignore
//! #[cfg(unix)]
//! use libc::some_type;
//!
//! #[cfg(windows)]
//! use winapi::some_type;
//! ```
//!
//! Instead, write code like this:
//!
//! ```ignore
//! use c_types::some_type;
//! ```
#![allow(non_camel_case_types)]

#[cfg(unix)]
mod unix {
  extern crate libc;

  pub type fd_set = libc::fd_set;

  #[repr(C)]
  #[derive(Debug)]
  #[allow(raw_pointer_derive)]
  pub struct hostent {
      pub h_name: *mut libc::c_char,
      pub h_aliases: *mut *mut libc::c_char,
      pub h_addrtype: libc::c_int,
      pub h_length: libc::c_int,
      pub h_addr_list: *mut *mut libc::c_char,
  }

  pub type in_addr = libc::in_addr;
  pub type in6_addr = libc::in6_addr;
  pub type sa_family_t = libc::sa_family_t;
  pub type sockaddr = libc::sockaddr;
  pub type sockaddr_in = libc::sockaddr_in;
  pub type sockaddr_in6 = libc::sockaddr_in6;
  pub type socklen_t = libc::socklen_t;

  pub const AF_INET: i32 = libc::AF_INET;
  pub const AF_INET6: i32 = libc::AF_INET6;
}

#[cfg(windows)]
mod windows {
  extern crate winapi;

  pub type fd_set = winapi::fd_set;
  pub type hostent = winapi::winsock2::hostent;
  pub type in_addr = winapi::in_addr;
  pub type in6_addr = winapi::in6_addr;
  pub type sa_family_t = winapi::ws2def::ADDRESS_FAMILY;
  pub type sockaddr = winapi::SOCKADDR;
  pub type sockaddr_in = winapi::ws2def::SOCKADDR_IN;
  pub type sockaddr_in6 = winapi::ws2ipdef::sockaddr_in6;
  pub type socklen_t = winapi::socklen_t;

  pub const AF_INET: i32 = winapi::ws2def::AF_INET;
  pub const AF_INET6: i32 = winapi::ws2def::AF_INET6;
}

#[cfg(unix)]
pub use self::unix::*;

#[cfg(windows)]
pub use self::windows::*;
<commit_msg>libc 0.2.3<commit_after>//! A crate that re-exports various types defined in both `libc` and `winapi`.
//!
//! Stop having to write code like this:
//!
//! ```ignore
//! #[cfg(unix)]
//! use libc::some_type;
//!
//! #[cfg(windows)]
//! use winapi::some_type;
//! ```
//!
//! Instead, write code like this:
//!
//! ```ignore
//! use c_types::some_type;
//! ```
#![allow(non_camel_case_types)]

#[cfg(unix)]
mod unix {
  extern crate libc;

  pub type fd_set = libc::fd_set;
  pub type hostent = libc::hostent;
  pub type in_addr = libc::in_addr;
  pub type in6_addr = libc::in6_addr;
  pub type sa_family_t = libc::sa_family_t;
  pub type sockaddr = libc::sockaddr;
  pub type sockaddr_in = libc::sockaddr_in;
  pub type sockaddr_in6 = libc::sockaddr_in6;
  pub type socklen_t = libc::socklen_t;

  pub const AF_INET: i32 = libc::AF_INET;
  pub const AF_INET6: i32 = libc::AF_INET6;
}

#[cfg(windows)]
mod windows {
  extern crate winapi;

  pub type fd_set = winapi::fd_set;
  pub type hostent = winapi::winsock2::hostent;
  pub type in_addr = winapi::in_addr;
  pub type in6_addr = winapi::in6_addr;
  pub type sa_family_t = winapi::ws2def::ADDRESS_FAMILY;
  pub type sockaddr = winapi::SOCKADDR;
  pub type sockaddr_in = winapi::ws2def::SOCKADDR_IN;
  pub type sockaddr_in6 = winapi::ws2ipdef::sockaddr_in6;
  pub type socklen_t = winapi::socklen_t;

  pub const AF_INET: i32 = winapi::ws2def::AF_INET;
  pub const AF_INET6: i32 = winapi::ws2def::AF_INET6;
}

#[cfg(unix)]
pub use self::unix::*;

#[cfg(windows)]
pub use self::windows::*;
<|endoftext|>