<commit_before>#![allow(unstable)]

use std::ops::Index;

#[derive(Copy, Clone, PartialEq)]
pub struct Matrix4([[f32; 4]; 4]);

impl Index<usize> for Matrix4 {
    type Output = [f32; 4];

    fn index<'a>(&'a self, row: &usize) -> &'a [f32; 4] {
        &self.0[*row]
    }
}

impl Matrix4 {
    pub fn as_array(&self) -> &[[f32; 4]; 4] {
        &self.0
    }

    pub fn from_array(array: [[f32; 4]; 4]) -> Self {
        Matrix4(array)
    }

    pub fn identity() -> Self {
        Matrix4::from_array([[1.0, 0.0, 0.0, 0.0],
                             [0.0, 1.0, 0.0, 0.0],
                             [0.0, 0.0, 1.0, 0.0],
                             [0.0, 0.0, 0.0, 1.0]])
    }

	/// Builds a scale 4 * 4 matrix created from 3 scalars.
	/// Input matrix multiplied by this scale matrix.
    pub fn scale(&mut self, x: f32, y: f32, z: f32) {
        self.0[0][0] *= x;
        self.0[0][1] *= x;
        self.0[0][2] *= x;
        self.0[0][3] *= x;

        self.0[1][0] *= y;
        self.0[1][1] *= y;
        self.0[1][2] *= y;
        self.0[1][3] *= y;

        self.0[2][0] *= z;
        self.0[2][1] *= z;
        self.0[2][2] *= z;
        self.0[2][3] *= z;
    }

    pub fn scale_by_vector(&mut self, v: &Vector4) {
        self.scale(v[0], v[1], v[2])
    }

	/// Builds a translation 4 * 4 matrix created from a vector of 3 components.
	/// Input matrix multiplied by this translation matrix.
    pub fn translate(&mut self, x: f32, y: f32, z: f32) {
        self.0[3][0] += self.0[0][0] * x + self.0[1][0] * y + self.0[2][0] * z;
        self.0[3][1] += self.0[0][1] * x + self.0[1][1] * y + self.0[2][1] * z;
        self.0[3][2] += self.0[0][2] * x + self.0[1][2] * y + self.0[2][2] * z;
    }

    pub fn translate_by_vector(&mut self, v: &Vector4) {
        self.translate(v[0], v[1], v[2])
    }
}

#[derive(Copy, Clone, PartialEq)]
pub struct Vector4([f32; 4]);

impl Index<usize> for Vector4 {
    type Output = f32;

    fn index<'a>(&'a self, index: &usize) -> &'a f32 {
        &self.0[*index]
    }
}

impl Vector4 {
    pub fn as_array(&self) -> &[f32; 4] {
        &self.0
    }

    pub fn from_array(array: [f32; 4]) -> Self {
        Vector4(array)
    }

    pub fn new(x: f32, y: f32, z: f32) -> Self {
        Vector4::from_array([x, y, z, 1.0])
    }

    pub fn from_scalar(scalar: f32) -> Self {
        Vector4::from_array([scalar, scalar, scalar, 1.0])
    }
}

#[test]
fn test_matrix_to_array() {
    let array = {
        let foo = Matrix4::from_array([[1.0, 0.0, 0.0, 0.0],
                                       [0.0, 1.0, 0.0, 0.0],
                                       [0.0, 0.0, 1.0, 0.0],
                                       [0.0, 0.0, 0.0, 1.0]]);
        assert_eq!(foo.as_array()[0][0], 1.0);
        *foo.as_array()
    };
    assert_eq!(array[1][1], 1.0);
}

#[test]
fn test_scale() {
    let mut m = Matrix4::identity();
    assert_eq!(m[2][2], 1.0);
    m.scale(3.0, 3.0, 3.0);
    assert_eq!(m[2][2], 3.0);
    m.scale_by_vector(&Vector4::new(2.0, 4.0, 3.0));
    assert_eq!(m[2][2], 9.0);
}

#[test]
fn test_translate() {
    let mut m = Matrix4::identity();
    m.translate(1.0, 2.0, 3.0);
    assert_eq!(m[3][0], 1.0);
    assert_eq!(m[3][1], 2.0);
    assert_eq!(m[3][2], 3.0);
}
<commit_msg>types implement IndexMut<commit_after>#![allow(unstable)]

use std::ops::{Index, IndexMut};

#[derive(Copy, Clone, PartialEq)]
pub struct Matrix4([[f32; 4]; 4]);

impl Index<usize> for Matrix4 {
    type Output = [f32; 4];

    fn index<'a>(&'a self, row: &usize) -> &'a [f32; 4] {
        &self.0[*row]
    }
}

impl IndexMut<usize> for Matrix4 {
    type Output = [f32; 4];

    fn index_mut<'a>(&'a mut self, row: &usize) -> &'a mut [f32; 4] {
        &mut self.0[*row]
    }
}

impl Matrix4 {
    pub fn as_array(&self) -> &[[f32; 4]; 4] {
        &self.0
    }

    pub fn from_array(array: [[f32; 4]; 4]) -> Self {
        Matrix4(array)
    }

    pub fn identity() -> Self {
        Matrix4::from_array([[1.0, 0.0, 0.0, 0.0],
                             [0.0, 1.0, 0.0, 0.0],
                             [0.0, 0.0, 1.0, 0.0],
                             [0.0, 0.0, 0.0, 1.0]])
    }

	/// Builds a scale 4 * 4 matrix created from 3 scalars.
	/// Input matrix multiplied by this scale matrix.
    pub fn scale(&mut self, x: f32, y: f32, z: f32) {
        self.0[0][0] *= x;
        self.0[0][1] *= x;
        self.0[0][2] *= x;
        self.0[0][3] *= x;

        self.0[1][0] *= y;
        self.0[1][1] *= y;
        self.0[1][2] *= y;
        self.0[1][3] *= y;

        self.0[2][0] *= z;
        self.0[2][1] *= z;
        self.0[2][2] *= z;
        self.0[2][3] *= z;
    }

    pub fn scale_by_vector(&mut self, v: &Vector4) {
        self.scale(v[0], v[1], v[2])
    }

	/// Builds a translation 4 * 4 matrix created from a vector of 3 components.
	/// Input matrix multiplied by this translation matrix.
    pub fn translate(&mut self, x: f32, y: f32, z: f32) {
        self.0[3][0] += self.0[0][0] * x + self.0[1][0] * y + self.0[2][0] * z;
        self.0[3][1] += self.0[0][1] * x + self.0[1][1] * y + self.0[2][1] * z;
        self.0[3][2] += self.0[0][2] * x + self.0[1][2] * y + self.0[2][2] * z;
    }

    pub fn translate_by_vector(&mut self, v: &Vector4) {
        self.translate(v[0], v[1], v[2])
    }
}

#[derive(Copy, Clone, PartialEq)]
pub struct Vector4([f32; 4]);

impl Index<usize> for Vector4 {
    type Output = f32;

    fn index<'a>(&'a self, index: &usize) -> &'a f32 {
        &self.0[*index]
    }
}

impl IndexMut<usize> for Vector4 {
    type Output = f32;

    fn index_mut<'a>(&'a mut self, index: &usize) -> &'a mut f32 {
        &mut self.0[*index]
    }
}

impl Vector4 {
    pub fn as_array(&self) -> &[f32; 4] {
        &self.0
    }

    pub fn from_array(array: [f32; 4]) -> Self {
        Vector4(array)
    }

    pub fn new(x: f32, y: f32, z: f32) -> Self {
        Vector4::from_array([x, y, z, 1.0])
    }

    pub fn from_scalar(scalar: f32) -> Self {
        Vector4::from_array([scalar, scalar, scalar, 1.0])
    }
}

#[test]
fn test_matrix_to_array() {
    let array = {
        let foo = Matrix4::from_array([[1.0, 0.0, 0.0, 0.0],
                                       [0.0, 1.0, 0.0, 0.0],
                                       [0.0, 0.0, 1.0, 0.0],
                                       [0.0, 0.0, 0.0, 1.0]]);
        assert_eq!(foo.as_array()[0][0], 1.0);
        *foo.as_array()
    };
    assert_eq!(array[1][1], 1.0);
}

#[test]
fn test_scale() {
    let mut m = Matrix4::identity();
    assert_eq!(m[2][2], 1.0);
    m.scale(3.0, 3.0, 3.0);
    assert_eq!(m[2][2], 3.0);
    m.scale_by_vector(&Vector4::new(2.0, 4.0, 3.0));
    assert_eq!(m[2][2], 9.0);
}

#[test]
fn test_translate() {
    let mut m = Matrix4::identity();
    m.translate(1.0, 2.0, 3.0);
    assert_eq!(m[3][0], 1.0);
    assert_eq!(m[3][1], 2.0);
    assert_eq!(m[3][2], 3.0);
}
<|endoftext|>


<commit_before>extern crate time;

use std::time::Duration;
use std::default::Default;
use std::fmt;

#[deriving(Copy)]
pub struct Stopwatch {
	start_time: Option<u64>,
	elapsed: Duration,
}

impl Default for Stopwatch {
	fn default () -> Stopwatch {
		Stopwatch {
			start_time: None,
			elapsed: Duration::zero(),
		}
	}
}

impl fmt::Show for Stopwatch {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		return write!(f, "{}", self.elapsed());
	}
}

fn current_time() -> u64 {
	return time::precise_time_ns();
}

// This only works under the assumption that less than 2^63 ns have passed between t1 and t2 (~292 years)
fn ns_times_to_duration(t1: u64, t2: u64) -> Duration {
	let diff_u = t2 - t1; // works even if there's wraparound
	let diff_i = match diff_u.to_i64() {
		Some(i) => i,
		None => {
			debug_assert!(false, "Stopwatch saw a time of more than 292 years, this probably indicates a bug");
			0
		}
	};
	return Duration::nanoseconds(diff_i);
}

impl Stopwatch {
	pub fn new() -> Stopwatch {
		let sw: Stopwatch = Default::default();
		return sw;
	}
	pub fn start_new() -> Stopwatch {
		let mut sw = Stopwatch::new();
		sw.start();
		return sw;
	}

	pub fn start(&mut self) {
		self.start_time = Some(current_time());
	}
	pub fn stop(&mut self) {
		self.elapsed = self.elapsed();
		self.start_time = None;
	}
	pub fn reset(&mut self) {
		self.start_time = None;
		self.elapsed = Duration::zero();
	}
	pub fn restart(&mut self) {
		self.reset();
		self.start();
	}

	pub fn is_running(&self) -> bool {
		return self.start_time.is_some();
	}

	pub fn elapsed(&self) -> Duration {
		match self.start_time {
			Some(t1) => {
				let t2 = current_time();
				let new_duration = ns_times_to_duration(t1, t2);
				return new_duration + self.elapsed;
			},
			None => {
				return self.elapsed;
			},
		}
	}
	pub fn elapsed_ms(&self) -> i64 {
		return self.elapsed().num_milliseconds();
	}
}
<commit_msg>fixing some things to work in latest version of rust<commit_after>extern crate time;

use std::time::Duration;
use std::default::Default;
use std::fmt;
use std::num::ToPrimitive;

#[derive(Copy)]
pub struct Stopwatch {
	start_time: Option<u64>,
	elapsed: Duration,
}

impl Default for Stopwatch {
	fn default () -> Stopwatch {
		Stopwatch {
			start_time: None,
			elapsed: Duration::zero(),
		}
	}
}

impl fmt::Show for Stopwatch {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		return write!(f, "{}", self.elapsed());
	}
}

fn current_time() -> u64 {
	return time::precise_time_ns();
}

// This only works under the assumption that less than 2^63 ns have passed between t1 and t2 (~292 years)
fn ns_times_to_duration(t1: u64, t2: u64) -> Duration {
	let diff_u = t2 - t1; // works even if there's wraparound
	let diff_i = match diff_u.to_i64() {
		Some(i) => i,
		None => {
			debug_assert!(false, "Stopwatch saw a time of more than 292 years, this probably indicates a bug");
			0
		}
	};
	return Duration::nanoseconds(diff_i);
}

impl Stopwatch {
	pub fn new() -> Stopwatch {
		let sw: Stopwatch = Default::default();
		return sw;
	}
	pub fn start_new() -> Stopwatch {
		let mut sw = Stopwatch::new();
		sw.start();
		return sw;
	}

	pub fn start(&mut self) {
		self.start_time = Some(current_time());
	}
	pub fn stop(&mut self) {
		self.elapsed = self.elapsed();
		self.start_time = None;
	}
	pub fn reset(&mut self) {
		self.start_time = None;
		self.elapsed = Duration::zero();
	}
	pub fn restart(&mut self) {
		self.reset();
		self.start();
	}

	pub fn is_running(&self) -> bool {
		return self.start_time.is_some();
	}

	pub fn elapsed(&self) -> Duration {
		match self.start_time {
			Some(t1) => {
				let t2 = current_time();
				let new_duration = ns_times_to_duration(t1, t2);
				return new_duration + self.elapsed;
			},
			None => {
				return self.elapsed;
			},
		}
	}
	pub fn elapsed_ms(&self) -> i64 {
		return self.elapsed().num_milliseconds();
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//!
//! An implementation of the [Roughtime](https://roughtime.googlesource.com/roughtime)
//! secure time synchronization protocol.
//!
//! Roughtime aims to achieve rough time synchronisation in a secure way that doesn't
//! depend on any particular time server, and in such a way that, if a time server does
//! misbehave, clients end up with cryptographic proof of it.
//!
//! # Protocol
//!
//! Roughtime messages are represetned by [`RtMessage`](struct.RtMessage.html) which
//! implements the mapping of Roughtime `u32` [`tags`](enum.Tag.html) to byte-strings.
//!
//! # Client
//!
//! A Roughtime client can be found in `src/bin/client.rs`. To run the client:
//!
//! ```bash
//! $ cargo run --release --bin client roughtime.int08h.com 2002
//! ```
//!
//! Consult the client's `--help` output for all runtime options.
//!
//! # Server
//!
//! A Roughtime server implementation is in `src/bin/server.rs`. The server is
//! configured via a yaml file:
//!
//! ```yaml
//! interface: 127.0.0.1
//! port: 8686
//! seed: f61075c988feb9cb700a4a6a3291bfbc9cab11b9c9eca8c802468eb38a43d7d3
//! batch_size: 64
//! ```
//!
//! Where:
//!
//!   * **interface** - IP address or interface name for listening to client requests
//!   * **port** - UDP port to listen to requests
//!   * **seed** - A 32-byte hexadecimal value used as the seed to generate the
//!                server's long-term key pair. **This is a secret value**, treat it
//!                with care.
//!   * **batch_size** - The number of requests to process in one batch. All nonces
//!                      in a batch are used to build a Merkle tree, the root of which
//!                      is signed.
//!
//! To run the server:
//!
//! ```bash
//! $ cargo run --release --bin server /path/to/config.file
//! ```
//!

extern crate byteorder;

mod error;
mod tag;
mod message;

pub mod sign;
pub mod merkle;

pub use error::Error;
pub use tag::Tag;
pub use message::RtMessage;

/// Version of Roughenough
pub const VERSION: &str = "0.3.1";

//  Constants and magic numbers of the Roughtime protocol

/// Minimum size (in bytes) of a client request
pub const MIN_REQUEST_LENGTH: u32 = 1024;

/// Minimum size (in bytes) of seeds used to derive private keys
pub const MIN_SEED_LENGTH: u32 = 32;

/// Size (in bytes) of an Ed25519 public key
pub const PUBKEY_LENGTH: u32 = 32;

/// Size (in bytes) of the client's nonce
pub const NONCE_LENGTH: u32 = 64;

/// Size (in bytes) of an Ed25519 signature
pub const SIGNATURE_LENGTH: u32 = 64;

/// Size (in bytes) of a SHA-512 hash
pub const HASH_LENGTH: u32 = 64;

/// Size (in bytes) of server's timestamp value
pub const TIMESTAMP_LENGTH: u32 = 8;

/// Size (in bytes) of server's time uncertainty value
pub const RADIUS_LENGTH: u32 = 4;

/// Prefixed to the server's certificate before generating or verifying certificate's signature
pub const CERTIFICATE_CONTEXT: &str = "RoughTime v1 delegation signature--\x00";

/// Prefixed to the server's response before generating or verifying the server's signature
pub const SIGNED_RESPONSE_CONTEXT: &str = "RoughTime v1 response signature\x00";

/// Value prepended to leaves prior to hashing
pub const TREE_LEAF_TWEAK: &[u8] = &[0x00];

/// Value prepended to nodes prior to hashing
pub const TREE_NODE_TWEAK: &[u8] = &[0x01];
<commit_msg>Missed updating lib.rs version constant to 1.0.0<commit_after>// Copyright 2017 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//!
//! An implementation of the [Roughtime](https://roughtime.googlesource.com/roughtime)
//! secure time synchronization protocol.
//!
//! Roughtime aims to achieve rough time synchronisation in a secure way that doesn't
//! depend on any particular time server, and in such a way that, if a time server does
//! misbehave, clients end up with cryptographic proof of it.
//!
//! # Protocol
//!
//! Roughtime messages are represetned by [`RtMessage`](struct.RtMessage.html) which
//! implements the mapping of Roughtime `u32` [`tags`](enum.Tag.html) to byte-strings.
//!
//! # Client
//!
//! A Roughtime client can be found in `src/bin/client.rs`. To run the client:
//!
//! ```bash
//! $ cargo run --release --bin client roughtime.int08h.com 2002
//! ```
//!
//! Consult the client's `--help` output for all runtime options.
//!
//! # Server
//!
//! A Roughtime server implementation is in `src/bin/server.rs`. The server is
//! configured via a yaml file:
//!
//! ```yaml
//! interface: 127.0.0.1
//! port: 8686
//! seed: f61075c988feb9cb700a4a6a3291bfbc9cab11b9c9eca8c802468eb38a43d7d3
//! batch_size: 64
//! ```
//!
//! Where:
//!
//!   * **interface** - IP address or interface name for listening to client requests
//!   * **port** - UDP port to listen to requests
//!   * **seed** - A 32-byte hexadecimal value used as the seed to generate the
//!                server's long-term key pair. **This is a secret value**, treat it
//!                with care.
//!   * **batch_size** - The number of requests to process in one batch. All nonces
//!                      in a batch are used to build a Merkle tree, the root of which
//!                      is signed.
//!
//! To run the server:
//!
//! ```bash
//! $ cargo run --release --bin server /path/to/config.file
//! ```
//!

extern crate byteorder;

mod error;
mod tag;
mod message;

pub mod sign;
pub mod merkle;

pub use error::Error;
pub use tag::Tag;
pub use message::RtMessage;

/// Version of Roughenough
pub const VERSION: &str = "1.0.0";

//  Constants and magic numbers of the Roughtime protocol

/// Minimum size (in bytes) of a client request
pub const MIN_REQUEST_LENGTH: u32 = 1024;

/// Minimum size (in bytes) of seeds used to derive private keys
pub const MIN_SEED_LENGTH: u32 = 32;

/// Size (in bytes) of an Ed25519 public key
pub const PUBKEY_LENGTH: u32 = 32;

/// Size (in bytes) of the client's nonce
pub const NONCE_LENGTH: u32 = 64;

/// Size (in bytes) of an Ed25519 signature
pub const SIGNATURE_LENGTH: u32 = 64;

/// Size (in bytes) of a SHA-512 hash
pub const HASH_LENGTH: u32 = 64;

/// Size (in bytes) of server's timestamp value
pub const TIMESTAMP_LENGTH: u32 = 8;

/// Size (in bytes) of server's time uncertainty value
pub const RADIUS_LENGTH: u32 = 4;

/// Prefixed to the server's certificate before generating or verifying certificate's signature
pub const CERTIFICATE_CONTEXT: &str = "RoughTime v1 delegation signature--\x00";

/// Prefixed to the server's response before generating or verifying the server's signature
pub const SIGNED_RESPONSE_CONTEXT: &str = "RoughTime v1 response signature\x00";

/// Value prepended to leaves prior to hashing
pub const TREE_LEAF_TWEAK: &[u8] = &[0x00];

/// Value prepended to nodes prior to hashing
pub const TREE_NODE_TWEAK: &[u8] = &[0x01];
<|endoftext|>


<commit_before>extern crate i2cdev;
extern crate nix;

mod utils;

pub mod bme280;
pub use bme280::*;
<commit_msg>Fix visibility of inner module.<commit_after>extern crate i2cdev;
extern crate nix;

mod bme280;
mod utils;

pub use bme280::*;
<|endoftext|>


<commit_before>/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

pub trait ColorSpaceLuminance {
	fn to_luma(&self, gamma: f32, luminance: f32) -> f32;
	fn from_luma(&self, gamma: f32, luma: f32) -> f32;
}

pub struct SRGBColorSpaceLuminance
{
}

pub struct LinearColorSpaceLuminance
{
}

pub struct GammaColorSpaceLuminance
{}

impl ColorSpaceLuminance for LinearColorSpaceLuminance {
	fn to_luma(&self, gamma: f32, luminance: f32) -> f32 {
        assert!(gamma == 1.);
		luminance
	}
	fn from_luma(&self, gamma: f32, luma: f32) -> f32 {
        assert!(gamma == 1.);
		luma
	}
}

impl ColorSpaceLuminance for GammaColorSpaceLuminance {
	fn to_luma(&self, gamma: f32, luminance: f32) -> f32 {
		luminance.powf(gamma)
	}
	fn from_luma(&self, gamma: f32, luma: f32) -> f32 {
		luma.powf(1./gamma)
	}
}

impl ColorSpaceLuminance for SRGBColorSpaceLuminance {
	fn to_luma(&self, gamma: f32, luminance: f32) -> f32 {
        assert!(gamma == 0.);
        //The magic numbers are derived from the sRGB specification.
        //See http://www.color.org/chardata/rgb/srgb.xalter .
		if luminance <= 0.04045 {
			return luminance / 12.92;
		}
		return ((luminance + 0.055) / 1.055).powf(2.4);
	}
	fn from_luma(&self, gamma: f32, luma: f32) -> f32 {
        assert!(gamma == 0.);
        //The magic numbers are derived from the sRGB specification.
        //See http://www.color.org/chardata/rgb/srgb.xalter .
        if luma <= 0.0031308 {
            return luma * 12.92;
        }
        return 1.055 * luma.powf(1./2.4)
               - 0.055;
	}
}

fn round_to_u8(x : f32) -> u8
{
    assert!((x + 0.5).floor() < 256.0);
    (x + 0.5).floor() as u8
}

/*
 * Scales base <= 2^N-1 to 2^8-1
 * @param N [1, 8] the number of bits used by base.
 * @param base the number to be scaled to [0, 255].
 */
fn scale255(n: u8, mut base : u8) -> u8 {
    base <<= 8 - n;
    let mut lum = base;
    let mut i = n;

    while i < 8 {
        lum |= base >> i;
        i += n;
    }

    return lum;
}

#[derive(Copy, Clone)]
pub struct Color {
    color: u32,
}

impl Color {
    fn get_b(self) -> u8 {
        return ((self.color >> 0) & 0xFF) as u8;
    }
    fn get_g(self) -> u8 {
        return ((self.color >> 8) & 0xFF) as u8;
    }
    fn get_r(self) -> u8 {
        return ((self.color >> 16) & 0xFF) as u8;
    }
    #[allow(dead_code)]
    fn get_a(self) -> u8 {
        return ((self.color >> 24) & 0xFF) as u8;
    }

    fn new(r: u8, g: u8, b: u8) -> Color {
        return Color {
                color: ((r as u32) << 16)|
                       ((g as u32) << 8) |
                       b as u32
        };
    }
}

/**
 * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
 * With lower values small text appears washed out (though correctly so).
 * With higher values lcd fringing is worse and the smoothing effect of
 * partial coverage is diminished.
 */
fn apply_contrast(srca: f32, contrast: f32) -> f32 {
    srca + ((1.0 - srca) * contrast * srca)
}

// The approach here is not necessarily the one with the lowest error
// See https://bel.fi/alankila/lcd/alpcor.html for a similar kind of thing
// that just search for the adjusted alpha value
pub fn build_gamma_correcting_lut(table: &mut [u8; 256], src: u8, contrast: f32,
                                  src_space: &ColorSpaceLuminance, src_gamma: f32,
                                  dst_convert: &ColorSpaceLuminance, dst_gamma: f32) {

    let src = src as f32 / 255.0;
    let lin_src = src_space.to_luma(src_gamma, src);
    // Guess at the dst. The perceptual inverse provides smaller visual
    // discontinuities when slight changes to desaturated colors cause a channel
    // to map to a different correcting lut with neighboring srcI.
    // See https://code.google.com/p/chromium/issues/detail?id=141425#c59 .
    let dst = 1.0 - src;
    let lin_dst = dst_convert.to_luma(dst_gamma, dst);

    // Contrast value tapers off to 0 as the src luminance becomes white
    let adjusted_contrast = contrast * lin_dst;

    // Remove discontinuity and instability when src is close to dst.
    // The value 1/256 is arbitrary and appears to contain the instability.
    if (src - dst).abs() < (1.0 / 256.0) {
        let mut ii : f32 = 0.0;
        for i in 0..256 {
            let raw_srca = ii / 255.0;
            let srca = apply_contrast(raw_srca, adjusted_contrast);

            table[i] = round_to_u8(255.0 * srca);
            ii += 1.0;
        }
    } else {
        // Avoid slow int to float conversion.
        let mut ii : f32 = 0.0;
        for i in 0..256 {
            // 'raw_srca += 1.0f / 255.0f' and even
            // 'raw_srca = i * (1.0f / 255.0f)' can add up to more than 1.0f.
            // When this happens the table[255] == 0x0 instead of 0xff.
            // See http://code.google.com/p/chromium/issues/detail?id=146466
            let raw_srca = ii / 255.0;
            let srca = apply_contrast(raw_srca, adjusted_contrast);
            assert!(srca <= 1.0);
            let dsta = 1.0 - srca;

            // Calculate the output we want.
            let lin_out = lin_src * srca + dsta * lin_dst;
            assert!(lin_out <= 1.0);
            let out = dst_convert.from_luma(dst_gamma, lin_out);

            // Undo what the blit blend will do.
            // i.e. given the formula for OVER: out = src * result + (1 - result) * dst
            // solving for result gives:
            let result = (out - dst) / (src - dst);

            //println!("Setting {:?} to {:?}", i, round_to_u8(255.0 * result));
            table[i] = round_to_u8(255.0 * result);

            ii += 1.0;
        }
    }
}

fn fetch_color_space(gamma: f32) -> Box<ColorSpaceLuminance> {
    if 0.0 == gamma {
        return Box::new( SRGBColorSpaceLuminance{} );
    } else if 1.0 == gamma {
        return Box::new( LinearColorSpaceLuminance{} );
    } else {
        return Box::new( GammaColorSpaceLuminance{} );
    }
}

// Skia uses 3 bits per channel for luminance.
pub const LUM_BITS :u8 = 3;
pub struct GammaLut {
    tables: [[u8; 256 ]; 1 << LUM_BITS],
}

impl GammaLut {
    // Skia actually makes 9 gamma tables, then based on the luminance color,
    // fetches the RGB gamma table for that color.
    fn generate_tables(&mut self, contrast: f32, paint_gamma: f32, device_gamma: f32) {
        let paint_color_space = fetch_color_space(paint_gamma);
        let device_color_space = fetch_color_space(device_gamma);

        for i in 0..(1 << LUM_BITS) {
            let luminance = scale255(LUM_BITS, i);
            build_gamma_correcting_lut(&mut self.tables[i as usize],
                                       luminance,
                                       contrast,
                                       &*paint_color_space,
                                       paint_gamma,
                                       &*device_color_space,
                                       device_gamma);
        }
    }

    #[allow(dead_code)]
    fn table_count() -> usize {
        return 1 << LUM_BITS;
    }

    pub fn print_values(&self, table: usize) {
        for x in 0..256 {
            println!("[{:?}] = {:?}", x, self.tables[table][x])
        }
    }

    fn get_table(&self, color: u8) -> [u8; 256] {
        return self.tables[(color >> (8 - LUM_BITS)) as usize];
    }

    pub fn new(contrast: f32, paint_gamma: f32, device_gamma: f32) -> GammaLut {
        let mut table = GammaLut {
            tables: [[0; 256]; 1 << LUM_BITS],
        };

        table.generate_tables(contrast, paint_gamma, device_gamma);

        table
    }
}

pub struct PreblendLut {
    r_table: [u8; 256],
    g_table: [u8; 256],
    b_table: [u8; 256],
}

impl PreblendLut {
    pub fn new_default_color(contrast: f32, paint_gamma: f32, device_gamma: f32) -> PreblendLut {
        // Skia normally preblends based on what the background color is
        // Since we're using shaders, we can't do that, so preblend
        // based on the colors picked by Skia.
        let preblend_color :Color = Color::new(0x7f, 0x80, 0x7f);
        PreblendLut::new(contrast, paint_gamma, device_gamma, preblend_color)
    }

    pub fn new(contrast: f32, paint_gamma: f32, device_gamma: f32, preblend_color: Color) -> PreblendLut {
        let gamma_table = GammaLut::new(contrast, paint_gamma, device_gamma);

        PreblendLut {
            r_table : gamma_table.get_table(preblend_color.get_r().clone()),
            g_table : gamma_table.get_table(preblend_color.get_g().clone()),
            b_table : gamma_table.get_table(preblend_color.get_b().clone()),
        }
    }

    pub fn print_table(&self) {
        for x in 0..256 {
            println!("{:?} == ({:?}, {:?}, {:?})", x,
                    self.r_table[x],
                    self.g_table[x],
                    self.b_table[x]);
        }
    }
}

#[cfg(test)]
mod tests {
    use std::cmp;
    use std::mem;

    fn over(dst: u32, src: u32, alpha: u32) -> u32 {
        (src * alpha + dst * (255 - alpha))/255
    }

    fn overf(dst: f32, src: f32, alpha: f32) -> f32 {
        ((src * alpha + dst * (255. - alpha))/255.) as f32
    }

    fn absdiff(a: u32, b: u32) -> u32 {
        if a < b  { b - a } else { a - b }
    }

    #[test]
    fn gamma() {
        let mut table: [u8; 256] = unsafe{ mem::uninitialized() } ;
        let space = ::GammaColorSpaceLuminance{};
        let g : f32 = 2.;
        let mut src : u32 = 131;
        while src < 256 {
            ::build_gamma_correcting_lut(&mut table, src as u8, 0., &space, g, &space, g);
            let mut max_diff = 0;
            let mut dst = 0;
            while dst < 256 {
                for alpha in 0u32..256 {
                    let preblend = table[alpha as usize];
                    let lin_dst = (dst as f32 / 255.).powf(g) * 255.;
                    let lin_src = (src as f32 / 255.).powf(g) * 255.;

                    let preblend_result = over(dst, src, preblend as u32);
                    let true_result = ((overf(lin_dst, lin_src, alpha as f32) / 255.).powf(1. / g) * 255.) as u32;
                    let diff = absdiff(preblend_result, true_result);
                    //println!("{} -- {} {} = {}", alpha, preblend_result, true_result, diff);
                    max_diff = cmp::max(max_diff, diff);
                }

                //println!("{} {} max {}", src, dst, max_diff);
                assert!(max_diff <= 33);
                dst += 1;

            }
            src += 1;
        }
    }
} // end mod
<commit_msg>properly format comments<commit_after>/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

pub trait ColorSpaceLuminance {
	fn to_luma(&self, gamma: f32, luminance: f32) -> f32;
	fn from_luma(&self, gamma: f32, luma: f32) -> f32;
}

pub struct SRGBColorSpaceLuminance
{
}

pub struct LinearColorSpaceLuminance
{
}

pub struct GammaColorSpaceLuminance
{}

impl ColorSpaceLuminance for LinearColorSpaceLuminance {
	fn to_luma(&self, gamma: f32, luminance: f32) -> f32 {
        assert!(gamma == 1.);
		luminance
	}
	fn from_luma(&self, gamma: f32, luma: f32) -> f32 {
        assert!(gamma == 1.);
		luma
	}
}

impl ColorSpaceLuminance for GammaColorSpaceLuminance {
	fn to_luma(&self, gamma: f32, luminance: f32) -> f32 {
		luminance.powf(gamma)
	}
	fn from_luma(&self, gamma: f32, luma: f32) -> f32 {
		luma.powf(1./gamma)
	}
}

impl ColorSpaceLuminance for SRGBColorSpaceLuminance {
	fn to_luma(&self, gamma: f32, luminance: f32) -> f32 {
        assert!(gamma == 0.);
        //The magic numbers are derived from the sRGB specification.
        //See http://www.color.org/chardata/rgb/srgb.xalter .
		if luminance <= 0.04045 {
			return luminance / 12.92;
		}
		return ((luminance + 0.055) / 1.055).powf(2.4);
	}
	fn from_luma(&self, gamma: f32, luma: f32) -> f32 {
        assert!(gamma == 0.);
        //The magic numbers are derived from the sRGB specification.
        //See http://www.color.org/chardata/rgb/srgb.xalter .
        if luma <= 0.0031308 {
            return luma * 12.92;
        }
        return 1.055 * luma.powf(1./2.4)
               - 0.055;
	}
}

fn round_to_u8(x : f32) -> u8
{
    assert!((x + 0.5).floor() < 256.0);
    (x + 0.5).floor() as u8
}

/*
 * Scales base <= 2^N-1 to 2^8-1
 * @param N [1, 8] the number of bits used by base.
 * @param base the number to be scaled to [0, 255].
 */
fn scale255(n: u8, mut base : u8) -> u8 {
    base <<= 8 - n;
    let mut lum = base;
    let mut i = n;

    while i < 8 {
        lum |= base >> i;
        i += n;
    }

    return lum;
}

#[derive(Copy, Clone)]
pub struct Color {
    color: u32,
}

impl Color {
    fn get_b(self) -> u8 {
        return ((self.color >> 0) & 0xFF) as u8;
    }
    fn get_g(self) -> u8 {
        return ((self.color >> 8) & 0xFF) as u8;
    }
    fn get_r(self) -> u8 {
        return ((self.color >> 16) & 0xFF) as u8;
    }
    #[allow(dead_code)]
    fn get_a(self) -> u8 {
        return ((self.color >> 24) & 0xFF) as u8;
    }

    fn new(r: u8, g: u8, b: u8) -> Color {
        return Color {
                color: ((r as u32) << 16)|
                       ((g as u32) << 8) |
                       b as u32
        };
    }
}

// A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
// With lower values small text appears washed out (though correctly so).
// With higher values lcd fringing is worse and the smoothing effect of
// partial coverage is diminished.
fn apply_contrast(srca: f32, contrast: f32) -> f32 {
    srca + ((1.0 - srca) * contrast * srca)
}

// The approach here is not necessarily the one with the lowest error
// See https://bel.fi/alankila/lcd/alpcor.html for a similar kind of thing
// that just search for the adjusted alpha value
pub fn build_gamma_correcting_lut(table: &mut [u8; 256], src: u8, contrast: f32,
                                  src_space: &ColorSpaceLuminance, src_gamma: f32,
                                  dst_convert: &ColorSpaceLuminance, dst_gamma: f32) {

    let src = src as f32 / 255.0;
    let lin_src = src_space.to_luma(src_gamma, src);
    // Guess at the dst. The perceptual inverse provides smaller visual
    // discontinuities when slight changes to desaturated colors cause a channel
    // to map to a different correcting lut with neighboring srcI.
    // See https://code.google.com/p/chromium/issues/detail?id=141425#c59 .
    let dst = 1.0 - src;
    let lin_dst = dst_convert.to_luma(dst_gamma, dst);

    // Contrast value tapers off to 0 as the src luminance becomes white
    let adjusted_contrast = contrast * lin_dst;

    // Remove discontinuity and instability when src is close to dst.
    // The value 1/256 is arbitrary and appears to contain the instability.
    if (src - dst).abs() < (1.0 / 256.0) {
        let mut ii : f32 = 0.0;
        for i in 0..256 {
            let raw_srca = ii / 255.0;
            let srca = apply_contrast(raw_srca, adjusted_contrast);

            table[i] = round_to_u8(255.0 * srca);
            ii += 1.0;
        }
    } else {
        // Avoid slow int to float conversion.
        let mut ii : f32 = 0.0;
        for i in 0..256 {
            // 'raw_srca += 1.0f / 255.0f' and even
            // 'raw_srca = i * (1.0f / 255.0f)' can add up to more than 1.0f.
            // When this happens the table[255] == 0x0 instead of 0xff.
            // See http://code.google.com/p/chromium/issues/detail?id=146466
            let raw_srca = ii / 255.0;
            let srca = apply_contrast(raw_srca, adjusted_contrast);
            assert!(srca <= 1.0);
            let dsta = 1.0 - srca;

            // Calculate the output we want.
            let lin_out = lin_src * srca + dsta * lin_dst;
            assert!(lin_out <= 1.0);
            let out = dst_convert.from_luma(dst_gamma, lin_out);

            // Undo what the blit blend will do.
            // i.e. given the formula for OVER: out = src * result + (1 - result) * dst
            // solving for result gives:
            let result = (out - dst) / (src - dst);

            //println!("Setting {:?} to {:?}", i, round_to_u8(255.0 * result));
            table[i] = round_to_u8(255.0 * result);

            ii += 1.0;
        }
    }
}

fn fetch_color_space(gamma: f32) -> Box<ColorSpaceLuminance> {
    if 0.0 == gamma {
        return Box::new( SRGBColorSpaceLuminance{} );
    } else if 1.0 == gamma {
        return Box::new( LinearColorSpaceLuminance{} );
    } else {
        return Box::new( GammaColorSpaceLuminance{} );
    }
}

// Skia uses 3 bits per channel for luminance.
pub const LUM_BITS :u8 = 3;
pub struct GammaLut {
    tables: [[u8; 256 ]; 1 << LUM_BITS],
}

impl GammaLut {
    // Skia actually makes 9 gamma tables, then based on the luminance color,
    // fetches the RGB gamma table for that color.
    fn generate_tables(&mut self, contrast: f32, paint_gamma: f32, device_gamma: f32) {
        let paint_color_space = fetch_color_space(paint_gamma);
        let device_color_space = fetch_color_space(device_gamma);

        for i in 0..(1 << LUM_BITS) {
            let luminance = scale255(LUM_BITS, i);
            build_gamma_correcting_lut(&mut self.tables[i as usize],
                                       luminance,
                                       contrast,
                                       &*paint_color_space,
                                       paint_gamma,
                                       &*device_color_space,
                                       device_gamma);
        }
    }

    #[allow(dead_code)]
    fn table_count() -> usize {
        return 1 << LUM_BITS;
    }

    pub fn print_values(&self, table: usize) {
        for x in 0..256 {
            println!("[{:?}] = {:?}", x, self.tables[table][x])
        }
    }

    fn get_table(&self, color: u8) -> [u8; 256] {
        return self.tables[(color >> (8 - LUM_BITS)) as usize];
    }

    pub fn new(contrast: f32, paint_gamma: f32, device_gamma: f32) -> GammaLut {
        let mut table = GammaLut {
            tables: [[0; 256]; 1 << LUM_BITS],
        };

        table.generate_tables(contrast, paint_gamma, device_gamma);

        table
    }
}

pub struct PreblendLut {
    r_table: [u8; 256],
    g_table: [u8; 256],
    b_table: [u8; 256],
}

impl PreblendLut {
    pub fn new_default_color(contrast: f32, paint_gamma: f32, device_gamma: f32) -> PreblendLut {
        // Skia normally preblends based on what the background color is
        // Since we're using shaders, we can't do that, so preblend
        // based on the colors picked by Skia.
        let preblend_color :Color = Color::new(0x7f, 0x80, 0x7f);
        PreblendLut::new(contrast, paint_gamma, device_gamma, preblend_color)
    }

    pub fn new(contrast: f32, paint_gamma: f32, device_gamma: f32, preblend_color: Color) -> PreblendLut {
        let gamma_table = GammaLut::new(contrast, paint_gamma, device_gamma);

        PreblendLut {
            r_table : gamma_table.get_table(preblend_color.get_r().clone()),
            g_table : gamma_table.get_table(preblend_color.get_g().clone()),
            b_table : gamma_table.get_table(preblend_color.get_b().clone()),
        }
    }

    pub fn print_table(&self) {
        for x in 0..256 {
            println!("{:?} == ({:?}, {:?}, {:?})", x,
                    self.r_table[x],
                    self.g_table[x],
                    self.b_table[x]);
        }
    }
}

#[cfg(test)]
mod tests {
    use std::cmp;
    use std::mem;

    fn over(dst: u32, src: u32, alpha: u32) -> u32 {
        (src * alpha + dst * (255 - alpha))/255
    }

    fn overf(dst: f32, src: f32, alpha: f32) -> f32 {
        ((src * alpha + dst * (255. - alpha))/255.) as f32
    }

    fn absdiff(a: u32, b: u32) -> u32 {
        if a < b  { b - a } else { a - b }
    }

    #[test]
    fn gamma() {
        let mut table: [u8; 256] = unsafe{ mem::uninitialized() } ;
        let space = ::GammaColorSpaceLuminance{};
        let g : f32 = 2.;
        let mut src : u32 = 131;
        while src < 256 {
            ::build_gamma_correcting_lut(&mut table, src as u8, 0., &space, g, &space, g);
            let mut max_diff = 0;
            let mut dst = 0;
            while dst < 256 {
                for alpha in 0u32..256 {
                    let preblend = table[alpha as usize];
                    let lin_dst = (dst as f32 / 255.).powf(g) * 255.;
                    let lin_src = (src as f32 / 255.).powf(g) * 255.;

                    let preblend_result = over(dst, src, preblend as u32);
                    let true_result = ((overf(lin_dst, lin_src, alpha as f32) / 255.).powf(1. / g) * 255.) as u32;
                    let diff = absdiff(preblend_result, true_result);
                    //println!("{} -- {} {} = {}", alpha, preblend_result, true_result, diff);
                    max_diff = cmp::max(max_diff, diff);
                }

                //println!("{} {} max {}", src, dst, max_diff);
                assert!(max_diff <= 33);
                dst += 1;

            }
            src += 1;
        }
    }
} // end mod
<|endoftext|>


<commit_before>//! Bindings for serial port I/O and futures
//!
//! This crate provides bindings between `mio_serial`, a mio crate for
//! serial port I/O, and `futures`.  The API is very similar to the
//! bindings in `mio_serial`
//!
#![deny(missing_docs)]

extern crate bytes;
extern crate futures;
extern crate tokio;

extern crate mio_serial;

// Re-export serialport types and traits from mio_serial
pub use mio_serial::{BaudRate, DataBits, Error, ErrorKind, FlowControl, Parity, SerialPort,
                     SerialPortSettings, StopBits};

/// A type for results generated by interacting with serial ports.
pub type Result<T> = mio_serial::Result<T>;

use futures::{Async, Poll};
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::reactor::{Handle, PollEvented2};

use std::io::{self, Read, Write};
use std::path::Path;
use std::time::Duration;

/// Serial port I/O struct.
pub struct Serial {
    io: PollEvented2<mio_serial::Serial>,
}

impl Serial {
    /// Open serial port from a provided path, using the default reactor.
    pub fn from_path<P>(path: P, settings: &mio_serial::SerialPortSettings) -> io::Result<Serial>
    where
        P: AsRef<Path>,
    {
        let port = mio_serial::Serial::from_path(path.as_ref(), settings)?;
        let io = PollEvented2::new(port);

        Ok(Serial { io })
    }

    /// Open serial port from a provided path, using the specified reactor.
    pub fn from_path_with_handle<P>(
        path: P,
        settings: &mio_serial::SerialPortSettings,
        handle: &Handle,
    ) -> io::Result<Serial>
    where
        P: AsRef<Path>,
    {
        let port = mio_serial::Serial::from_path(path.as_ref(), settings)?;
        let io = PollEvented2::new_with_handle(port, handle)?;

        Ok(Serial { io })
    }

    /// Create a pair of pseudo serial terminals using the default reactor
    ///
    /// ## Returns
    /// Two connected, unnamed `Serial` objects.
    ///
    /// ## Errors
    /// Attempting any IO or parameter settings on the slave tty after the master
    /// tty is closed will return errors.
    ///
    #[cfg(unix)]
    pub fn pair() -> ::Result<(Self, Self)> {
        let (master, slave) = mio_serial::Serial::pair()?;

        let master = Serial {
            io: PollEvented2::new(master),
        };
        let slave = Serial {
            io: PollEvented2::new(slave),
        };
        Ok((master, slave))
    }

    /// Create a pair of pseudo serial terminals using the specified reactor.
    ///
    /// ## Returns
    /// Two connected, unnamed `Serial` objects.
    ///
    /// ## Errors
    /// Attempting any IO or parameter settings on the slave tty after the master
    /// tty is closed will return errors.
    ///
    #[cfg(unix)]
    pub fn pair_with_handle(handle: &Handle) -> ::Result<(Self, Self)> {
        let (master, slave) = mio_serial::Serial::pair()?;

        let master = Serial {
            io: PollEvented2::new_with_handle(master, handle)?,
        };
        let slave = Serial {
            io: PollEvented2::new_with_handle(slave, handle)?,
        };
        Ok((master, slave))
    }

    /// Sets the exclusivity of the port
    ///
    /// If a port is exclusive, then trying to open the same device path again
    /// will fail.
    ///
    /// See the man pages for the tiocexcl and tiocnxcl ioctl's for more details.
    ///
    /// ## Errors
    ///
    /// * `Io` for any error while setting exclusivity for the port.
    #[cfg(unix)]
    pub fn set_exclusive(&mut self, exclusive: bool) -> ::Result<()> {
        self.io.get_mut().set_exclusive(exclusive)
    }

    /// Returns the exclusivity of the port
    ///
    /// If a port is exclusive, then trying to open the same device path again
    /// will fail.
    #[cfg(unix)]
    pub fn exclusive(&self) -> bool {
        self.io.get_ref().exclusive()
    }
}

impl ::SerialPort for Serial {
    fn settings(&self) -> ::SerialPortSettings {
        self.io.get_ref().settings()
    }

    fn port_name(&self) -> Option<String> {
        self.io.get_ref().port_name()
    }

    fn baud_rate(&self) -> Option<::BaudRate> {
        self.io.get_ref().baud_rate()
    }

    fn data_bits(&self) -> Option<::DataBits> {
        self.io.get_ref().data_bits()
    }

    fn flow_control(&self) -> Option<::FlowControl> {
        self.io.get_ref().flow_control()
    }

    fn parity(&self) -> Option<::Parity> {
        self.io.get_ref().parity()
    }

    fn stop_bits(&self) -> Option<::StopBits> {
        self.io.get_ref().stop_bits()
    }

    fn timeout(&self) -> Duration {
        Duration::from_secs(0)
    }

    fn set_all(&mut self, settings: &::SerialPortSettings) -> ::Result<()> {
        self.io.get_mut().set_all(settings)
    }

    fn set_baud_rate(&mut self, baud_rate: ::BaudRate) -> ::Result<()> {
        self.io.get_mut().set_baud_rate(baud_rate)
    }

    fn set_data_bits(&mut self, data_bits: ::DataBits) -> ::Result<()> {
        self.io.get_mut().set_data_bits(data_bits)
    }

    fn set_flow_control(&mut self, flow_control: ::FlowControl) -> ::Result<()> {
        self.io.get_mut().set_flow_control(flow_control)
    }

    fn set_parity(&mut self, parity: ::Parity) -> ::Result<()> {
        self.io.get_mut().set_parity(parity)
    }

    fn set_stop_bits(&mut self, stop_bits: ::StopBits) -> ::Result<()> {
        self.io.get_mut().set_stop_bits(stop_bits)
    }

    fn set_timeout(&mut self, _: Duration) -> ::Result<()> {
        Ok(())
    }

    fn write_request_to_send(&mut self, level: bool) -> ::Result<()> {
        self.io.get_mut().write_request_to_send(level)
    }

    fn write_data_terminal_ready(&mut self, level: bool) -> ::Result<()> {
        self.io.get_mut().write_data_terminal_ready(level)
    }

    fn read_clear_to_send(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_clear_to_send()
    }

    fn read_data_set_ready(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_data_set_ready()
    }

    fn read_ring_indicator(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_ring_indicator()
    }

    fn read_carrier_detect(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_carrier_detect()
    }

    fn try_clone(&self) -> ::Result<Box<::SerialPort>> {
        self.io.get_ref().try_clone()
    }
}

impl Read for Serial {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.io.read(buf)
    }
}

impl Write for Serial {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.io.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }
}

#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(unix)]
impl AsRawFd for Serial {
    fn as_raw_fd(&self) -> RawFd {
        self.io.get_ref().as_raw_fd()
    }
}

impl AsyncRead for Serial {
    fn poll_read(&mut self, buf: &mut [u8]) -> io::Result<Async<usize>> {
        Ok(self.io.poll_read(buf)?)
    }
}

impl AsyncWrite for Serial {
    fn poll_write(&mut self, buf: &[u8]) -> io::Result<Async<usize>> {
        Ok(self.io.poll_write(buf)?)
    }

    fn shutdown(&mut self) -> Poll<(), io::Error> {
        Ok(Async::Ready(()))
    }
}
<commit_msg>Calling PollEvented2 methods directly for AsyncRead and AsyncWrite.<commit_after>//! Bindings for serial port I/O and futures
//!
//! This crate provides bindings between `mio_serial`, a mio crate for
//! serial port I/O, and `futures`.  The API is very similar to the
//! bindings in `mio_serial`
//!
#![deny(missing_docs)]

extern crate bytes;
extern crate futures;
extern crate tokio;

extern crate mio_serial;

// Re-export serialport types and traits from mio_serial
pub use mio_serial::{BaudRate, DataBits, Error, ErrorKind, FlowControl, Parity, SerialPort,
                     SerialPortSettings, StopBits};

/// A type for results generated by interacting with serial ports.
pub type Result<T> = mio_serial::Result<T>;

use futures::{Async, Poll};
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::reactor::{Handle, PollEvented2};

use std::io::{self, Read, Write};
use std::path::Path;
use std::time::Duration;

/// Serial port I/O struct.
pub struct Serial {
    io: PollEvented2<mio_serial::Serial>,
}

impl Serial {
    /// Open serial port from a provided path, using the default reactor.
    pub fn from_path<P>(path: P, settings: &mio_serial::SerialPortSettings) -> io::Result<Serial>
    where
        P: AsRef<Path>,
    {
        let port = mio_serial::Serial::from_path(path.as_ref(), settings)?;
        let io = PollEvented2::new(port);

        Ok(Serial { io })
    }

    /// Open serial port from a provided path, using the specified reactor.
    pub fn from_path_with_handle<P>(
        path: P,
        settings: &mio_serial::SerialPortSettings,
        handle: &Handle,
    ) -> io::Result<Serial>
    where
        P: AsRef<Path>,
    {
        let port = mio_serial::Serial::from_path(path.as_ref(), settings)?;
        let io = PollEvented2::new_with_handle(port, handle)?;

        Ok(Serial { io })
    }

    /// Create a pair of pseudo serial terminals using the default reactor
    ///
    /// ## Returns
    /// Two connected, unnamed `Serial` objects.
    ///
    /// ## Errors
    /// Attempting any IO or parameter settings on the slave tty after the master
    /// tty is closed will return errors.
    ///
    #[cfg(unix)]
    pub fn pair() -> ::Result<(Self, Self)> {
        let (master, slave) = mio_serial::Serial::pair()?;

        let master = Serial {
            io: PollEvented2::new(master),
        };
        let slave = Serial {
            io: PollEvented2::new(slave),
        };
        Ok((master, slave))
    }

    /// Create a pair of pseudo serial terminals using the specified reactor.
    ///
    /// ## Returns
    /// Two connected, unnamed `Serial` objects.
    ///
    /// ## Errors
    /// Attempting any IO or parameter settings on the slave tty after the master
    /// tty is closed will return errors.
    ///
    #[cfg(unix)]
    pub fn pair_with_handle(handle: &Handle) -> ::Result<(Self, Self)> {
        let (master, slave) = mio_serial::Serial::pair()?;

        let master = Serial {
            io: PollEvented2::new_with_handle(master, handle)?,
        };
        let slave = Serial {
            io: PollEvented2::new_with_handle(slave, handle)?,
        };
        Ok((master, slave))
    }

    /// Sets the exclusivity of the port
    ///
    /// If a port is exclusive, then trying to open the same device path again
    /// will fail.
    ///
    /// See the man pages for the tiocexcl and tiocnxcl ioctl's for more details.
    ///
    /// ## Errors
    ///
    /// * `Io` for any error while setting exclusivity for the port.
    #[cfg(unix)]
    pub fn set_exclusive(&mut self, exclusive: bool) -> ::Result<()> {
        self.io.get_mut().set_exclusive(exclusive)
    }

    /// Returns the exclusivity of the port
    ///
    /// If a port is exclusive, then trying to open the same device path again
    /// will fail.
    #[cfg(unix)]
    pub fn exclusive(&self) -> bool {
        self.io.get_ref().exclusive()
    }
}

impl ::SerialPort for Serial {
    fn settings(&self) -> ::SerialPortSettings {
        self.io.get_ref().settings()
    }

    fn port_name(&self) -> Option<String> {
        self.io.get_ref().port_name()
    }

    fn baud_rate(&self) -> Option<::BaudRate> {
        self.io.get_ref().baud_rate()
    }

    fn data_bits(&self) -> Option<::DataBits> {
        self.io.get_ref().data_bits()
    }

    fn flow_control(&self) -> Option<::FlowControl> {
        self.io.get_ref().flow_control()
    }

    fn parity(&self) -> Option<::Parity> {
        self.io.get_ref().parity()
    }

    fn stop_bits(&self) -> Option<::StopBits> {
        self.io.get_ref().stop_bits()
    }

    fn timeout(&self) -> Duration {
        Duration::from_secs(0)
    }

    fn set_all(&mut self, settings: &::SerialPortSettings) -> ::Result<()> {
        self.io.get_mut().set_all(settings)
    }

    fn set_baud_rate(&mut self, baud_rate: ::BaudRate) -> ::Result<()> {
        self.io.get_mut().set_baud_rate(baud_rate)
    }

    fn set_data_bits(&mut self, data_bits: ::DataBits) -> ::Result<()> {
        self.io.get_mut().set_data_bits(data_bits)
    }

    fn set_flow_control(&mut self, flow_control: ::FlowControl) -> ::Result<()> {
        self.io.get_mut().set_flow_control(flow_control)
    }

    fn set_parity(&mut self, parity: ::Parity) -> ::Result<()> {
        self.io.get_mut().set_parity(parity)
    }

    fn set_stop_bits(&mut self, stop_bits: ::StopBits) -> ::Result<()> {
        self.io.get_mut().set_stop_bits(stop_bits)
    }

    fn set_timeout(&mut self, _: Duration) -> ::Result<()> {
        Ok(())
    }

    fn write_request_to_send(&mut self, level: bool) -> ::Result<()> {
        self.io.get_mut().write_request_to_send(level)
    }

    fn write_data_terminal_ready(&mut self, level: bool) -> ::Result<()> {
        self.io.get_mut().write_data_terminal_ready(level)
    }

    fn read_clear_to_send(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_clear_to_send()
    }

    fn read_data_set_ready(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_data_set_ready()
    }

    fn read_ring_indicator(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_ring_indicator()
    }

    fn read_carrier_detect(&mut self) -> ::Result<bool> {
        self.io.get_mut().read_carrier_detect()
    }

    fn try_clone(&self) -> ::Result<Box<::SerialPort>> {
        self.io.get_ref().try_clone()
    }
}

impl Read for Serial {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.io.read(buf)
    }
}

impl Write for Serial {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.io.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }
}

#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd};
#[cfg(unix)]
impl AsRawFd for Serial {
    fn as_raw_fd(&self) -> RawFd {
        self.io.get_ref().as_raw_fd()
    }
}

impl AsyncRead for Serial {
    fn poll_read(&mut self, buf: &mut [u8]) -> io::Result<Async<usize>> {
        self.io.poll_read(buf)
    }
}

impl AsyncWrite for Serial {
    fn poll_write(&mut self, buf: &[u8]) -> io::Result<Async<usize>> {
        self.io.poll_write(buf)
    }

    fn shutdown(&mut self) -> Poll<(), io::Error> {
        self.io.shutdown()
    }

}
<|endoftext|>


<commit_before>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam;

use crossbeam::mem::epoch::{Atomic, Owned, pin};
use std::sync::atomic::Ordering::*;

use std::ops::Deref;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone>(Atomic<T>);

impl<T: Clone> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(Some(t), Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        if let Some(t) = self.0.swap(Some(t), Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        if let Some(t) = self.0.swap(None, Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        let t = self.0.load(Acquire, &guard);
        t.map(|t| -> &T { t.deref() }).cloned()
    }
}

impl<T: Clone> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone>(Pinboard<T>);

impl<T: Clone> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

macro_rules! debuggable {
    ($struct:ident, $trait:ident) => {
        impl<T: Clone> ::std::fmt::$trait for $struct<T> where T: ::std::fmt::$trait {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                write!(f, "{}(", stringify!($struct))?;
                ::std::fmt::$trait::fmt(&self.read(), f)?;
                write!(f, ")")
            }
        }
    }
}

debuggable!(Pinboard, Debug);
debuggable!(NonEmptyPinboard, Debug);
debuggable!(NonEmptyPinboard, Binary);
debuggable!(NonEmptyPinboard, Display);
debuggable!(NonEmptyPinboard, LowerExp);
debuggable!(NonEmptyPinboard, LowerHex);
debuggable!(NonEmptyPinboard, Octal);
debuggable!(NonEmptyPinboard, Pointer);
debuggable!(NonEmptyPinboard, UpperExp);
debuggable!(NonEmptyPinboard, UpperHex);

#[cfg(test)]
mod tests {
    use super::*;
    use std::fmt::Display;

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    fn check_debug<T: ::std::fmt::Debug>(_: T) {}

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }

    #[test]
    fn debuggable() {
        let t = Pinboard::<i32>::new(3);
        check_debug(t);
        let t = NonEmptyPinboard::<i32>::new(2);
        check_debug(t);
    }
}
<commit_msg>impl<T: Clone> From<Option<T>> for Pinboard<T><commit_after>#![warn(missing_docs)]

//! A `Pinboard` is a shared, mutable, eventually consistent, lock-free data-structure.  This
//! allows multiple threads to communicate in a decoupled way by publishing data to the pinboard
//! which other threads can then read in an eventually consistent way.
//!
//! This is not a silver bullet though, there are various limitations of `Pinboard` that trade off
//! the nice behaviour described above.
//!
//! * Eventual consistency:
//!     * Writes from one thread are not guaranteed to be seen by reads from another thread
//!     * Writes from one thread can overwrite writes from another thread
//! * No in-place mutation:
//!     * The only write primitive completely overwrites the data on the `Pinboard`
//! * Requires `Clone`:
//!     * All reads return a clone of the data, decoupling the lifetime of the read value from the
//!     data stored in the global reference.

extern crate crossbeam;

use crossbeam::mem::epoch::{Atomic, Owned, pin};
use std::sync::atomic::Ordering::*;

use std::ops::Deref;

/// An instance of a `Pinboard`, holds a shared, mutable, eventually-consistent reference to a `T`.
pub struct Pinboard<T: Clone>(Atomic<T>);

impl<T: Clone> Pinboard<T> {
    /// Create a new `Pinboard` instance holding the given value.
    pub fn new(t: T) -> Pinboard<T> {
        let t = Owned::new(t);
        let p = Pinboard::default();
        p.0.store(Some(t), Release);
        p
    }

    /// Update the value stored in the `Pinboard`.
    pub fn set(&self, t: T) {
        let guard = pin();
        let t = Owned::new(t);
        if let Some(t) = self.0.swap(Some(t), Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Clear out the `Pinboard` so its no longer holding any data.
    pub fn clear(&self) {
        let guard = pin();
        if let Some(t) = self.0.swap(None, Release, &guard) {
            unsafe {
                guard.unlinked(t);
            }
        }
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    pub fn read(&self) -> Option<T> {
        let guard = pin();
        let t = self.0.load(Acquire, &guard);
        t.map(|t| -> &T { t.deref() }).cloned()
    }
}

impl<T: Clone> Default for Pinboard<T> {
    fn default() -> Pinboard<T> {
        Pinboard(Atomic::null())
    }
}

impl<T: Clone> Drop for Pinboard<T> {
    fn drop(&mut self) {
        // Make sure any stored data is marked for deletion
        self.clear();
    }
}

impl<T: Clone> From<Option<T>> for Pinboard<T> {
    fn from(src: Option<T>) -> Pinboard<T> {
        src.map(Pinboard::new).unwrap_or_default()
    }
}

/// An wrapper around a `Pinboard` which provides the guarantee it is never empty.
pub struct NonEmptyPinboard<T: Clone>(Pinboard<T>);

impl<T: Clone> NonEmptyPinboard<T> {
    /// Create a new `NonEmptyPinboard` instance holding the given value.
    pub fn new(t: T) -> NonEmptyPinboard<T> {
        NonEmptyPinboard(Pinboard::new(t))
    }

    /// Update the value stored in the `NonEmptyPinboard`.
    #[inline]
    pub fn set(&self, t: T) {
        self.0.set(t)
    }

    /// Get a copy of the latest (well, recent) version of the posted data.
    #[inline]
    pub fn read(&self) -> T {
        // Unwrap the option returned by the inner `Pinboard`. This will never panic, because it's
        // impossible for this `Pinboard` to be empty (though it's not possible to prove this to the
        // compiler).
        match self.0.read() {
            Some(t) => t,
            None => unreachable!("Inner pointer was unexpectedly null"),
        }
    }
}

macro_rules! debuggable {
    ($struct:ident, $trait:ident) => {
        impl<T: Clone> ::std::fmt::$trait for $struct<T> where T: ::std::fmt::$trait {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
                write!(f, "{}(", stringify!($struct))?;
                ::std::fmt::$trait::fmt(&self.read(), f)?;
                write!(f, ")")
            }
        }
    }
}

debuggable!(Pinboard, Debug);
debuggable!(NonEmptyPinboard, Debug);
debuggable!(NonEmptyPinboard, Binary);
debuggable!(NonEmptyPinboard, Display);
debuggable!(NonEmptyPinboard, LowerExp);
debuggable!(NonEmptyPinboard, LowerHex);
debuggable!(NonEmptyPinboard, Octal);
debuggable!(NonEmptyPinboard, Pointer);
debuggable!(NonEmptyPinboard, UpperExp);
debuggable!(NonEmptyPinboard, UpperHex);

#[cfg(test)]
mod tests {
    use super::*;
    use std::fmt::Display;

    fn consume<T: Clone + Display>(t: &Pinboard<T>) {
        loop {
            match t.read() {
                Some(_) => {}
                None => break,
            }
            std::thread::sleep(std::time::Duration::from_millis(1));
        }
    }

    fn produce(t: &Pinboard<u32>) {
        for i in 1..100 {
            t.set(i);
            std::thread::sleep(std::time::Duration::from_millis(2));
        }
        t.clear();
    }

    fn check_debug<T: ::std::fmt::Debug>(_: T) {}

    #[test]
    fn it_works() {
        let t = Pinboard::<u32>::default();
        assert_eq!(None, t.read());
        t.set(3);
        assert_eq!(Some(3), t.read());
        t.clear();
        assert_eq!(None, t.read());
    }

    #[test]
    fn single_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_single_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn single_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn multi_producer_multi_consumer() {
        let t = Pinboard::<u32>::new(0);

        crossbeam::scope(|scope| {
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| produce(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                             scope.spawn(|| consume(&t));
                         })
    }

    #[test]
    fn non_empty_pinboard() {
        let t = NonEmptyPinboard::<u32>::new(3);
        assert_eq!(3, t.read());
        t.set(4);
        assert_eq!(4, t.read());
    }

    #[test]
    fn debuggable() {
        let t = Pinboard::<i32>::new(3);
        check_debug(t);
        let t = NonEmptyPinboard::<i32>::new(2);
        check_debug(t);
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::collections::HashMap;
use rand::Rng;

/// A bigram is simply two consecutive words.
type Bigram<'a> = (&'a str, &'a str);

/// Simple order two Markov chain implementation.
///
/// The [Markov chain] is a chain of order two, which means that it
/// will use the previous two words (a bigram) when predicting the
/// next word. This is normally enough to generate random text that
/// looks somewhat plausible. The implementation is based on
/// [Generating arbitrary text with Markov chains in Rust][blog post].
///
/// [Markov chain]: https://en.wikipedia.org/wiki/Markov_chain
/// [blog post]: https://blakewilliams.me/posts/generating-arbitrary-text-with-markov-chains-in-rust
#[derive(Default)]
pub struct MarkovChain<'a> {
    map: HashMap<Bigram<'a>, Vec<&'a str>>,
}

impl<'a> MarkovChain<'a> {
    /// Create a new Markov chain. It will use a default thread-local
    /// random number generator.
    pub fn new() -> MarkovChain<'a> {
        MarkovChain { map: HashMap::new() }
    }

    /// Add new text to the Markov chain. This can be called several
    /// times to build up the chain.
    pub fn learn(&mut self, sentence: &'a str) {
        let words = sentence.split_whitespace().collect::<Vec<&str>>();
        for window in words.windows(3) {
            let (a, b, c) = (window[0], window[1], window[2]);
            self.map.entry((a, b)).or_insert(vec![]).push(c);
        }
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from a random point in the Markov chain.
    pub fn generate(&self, n: usize) -> String {
        if self.map.is_empty() {
            // The learn method has not been called.
            return String::new();
        }

        let mut rng = rand::thread_rng();
        let keys = self.map.keys().collect::<Vec<&Bigram>>();
        let (mut a, mut b) = **rng.choose(&keys).unwrap();
        let mut sentence = String::from(a) + " " + b;

        for _ in 0..n {
            while !self.map.contains_key(&(a, b)) {
                let new_key = **rng.choose(&keys).unwrap();
                a = new_key.0;
                b = new_key.1;
            }

            let next_words = &self.map[&(a, b)];
            let c = rng.choose(next_words).unwrap();
            sentence.push(' ');
            sentence.push_str(c);
            a = b;
            b = c;
        }

        return sentence;
    }
}

/// The traditional lorem ipsum text as given in [Wikipedia]. Using
/// this text alone for a Markov chain of order two doesn't work very
/// well since each bigram (two consequtive words) is followed by just
/// one other word. In other words, the Markov chain will always
/// produce the same output and recreate the lorem ipsum text
/// precisely. However, combining it with the full text in
/// [`LIBER_PRIMUS`] works well.
///
/// [Wikipedia]: https://en.wikipedia.org/wiki/Lorem_ipsum
/// [`LIBER_PRIMUS`]: constant.LIBER_PRIMUS.html
const LOREM_IPSUM: &str = include_str!("lorem-ipsum.txt");

/// The first book in Cicero's work De finibus bonorum et malorum ("On
/// the ends of good and evil"). The lorem ipsum text in
/// [`LOREM_IPSUM`] is derived from part of this text.
///
/// [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
const LIBER_PRIMUS: &str = include_str!("liber-primus.txt");

/// Generate a standard lorem ipsum text.
pub fn lipsum() -> String {
    String::from(LOREM_IPSUM)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn starts_with_lorem_ipsum() {
        assert_eq!(&lipsum()[..11], "Lorem ipsum");
    }

    #[test]
    fn empty_chain() {
        let chain = MarkovChain::new();
        assert_eq!(chain.generate(10), "");
    }

    #[test]
    fn chain_map() {
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz quuz");
        let map = &chain.map;

        assert_eq!(map.len(), 2);
        assert_eq!(map[&("foo", "bar")], vec!["baz"]);
        assert_eq!(map[&("bar", "baz")], vec!["quuz"]);
    }
}
<commit_msg>MarkovChain: add generate_from method<commit_after>extern crate rand;

use std::collections::HashMap;
use rand::Rng;

/// A bigram is simply two consecutive words.
type Bigram<'a> = (&'a str, &'a str);

/// Simple order two Markov chain implementation.
///
/// The [Markov chain] is a chain of order two, which means that it
/// will use the previous two words (a bigram) when predicting the
/// next word. This is normally enough to generate random text that
/// looks somewhat plausible. The implementation is based on
/// [Generating arbitrary text with Markov chains in Rust][blog post].
///
/// [Markov chain]: https://en.wikipedia.org/wiki/Markov_chain
/// [blog post]: https://blakewilliams.me/posts/generating-arbitrary-text-with-markov-chains-in-rust
#[derive(Default)]
pub struct MarkovChain<'a> {
    map: HashMap<Bigram<'a>, Vec<&'a str>>,
}

impl<'a> MarkovChain<'a> {
    /// Create a new Markov chain. It will use a default thread-local
    /// random number generator.
    pub fn new() -> MarkovChain<'a> {
        MarkovChain { map: HashMap::new() }
    }

    /// Add new text to the Markov chain. This can be called several
    /// times to build up the chain.
    pub fn learn(&mut self, sentence: &'a str) {
        let words = sentence.split_whitespace().collect::<Vec<&str>>();
        for window in words.windows(3) {
            let (a, b, c) = (window[0], window[1], window[2]);
            self.map.entry((a, b)).or_insert(vec![]).push(c);
        }
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from a random point in the Markov chain.
    pub fn generate(&self, n: usize) -> String {
        if self.map.is_empty() {
            // The learn method has not been called.
            return String::new();
        }

        let mut rng = rand::thread_rng();
        let keys = self.map.keys().collect::<Vec<&(&str, &str)>>();
        self.generate_from(n, **rng.choose(&keys).unwrap())
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from the given bigram.
    pub fn generate_from(&self, n: usize, from: Bigram<'a>) -> String {
        let mut rng = rand::thread_rng(); // make part of struct
        let keys = self.map.keys().collect::<Vec<&Bigram>>();
        let (mut a, mut b) = from;
        let mut sentence = String::from(a) + " " + b;

        for _ in 0..n {
            while !self.map.contains_key(&(a, b)) {
                let new_key = **rng.choose(&keys).unwrap();
                a = new_key.0;
                b = new_key.1;
            }

            let next_words = &self.map[&(a, b)];
            let c = rng.choose(next_words).unwrap();
            sentence.push(' ');
            sentence.push_str(c);
            a = b;
            b = c;
        }

        return sentence;
    }
}

/// The traditional lorem ipsum text as given in [Wikipedia]. Using
/// this text alone for a Markov chain of order two doesn't work very
/// well since each bigram (two consequtive words) is followed by just
/// one other word. In other words, the Markov chain will always
/// produce the same output and recreate the lorem ipsum text
/// precisely. However, combining it with the full text in
/// [`LIBER_PRIMUS`] works well.
///
/// [Wikipedia]: https://en.wikipedia.org/wiki/Lorem_ipsum
/// [`LIBER_PRIMUS`]: constant.LIBER_PRIMUS.html
const LOREM_IPSUM: &str = include_str!("lorem-ipsum.txt");

/// The first book in Cicero's work De finibus bonorum et malorum ("On
/// the ends of good and evil"). The lorem ipsum text in
/// [`LOREM_IPSUM`] is derived from part of this text.
///
/// [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
const LIBER_PRIMUS: &str = include_str!("liber-primus.txt");

/// Generate a standard lorem ipsum text.
pub fn lipsum() -> String {
    String::from(LOREM_IPSUM)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn starts_with_lorem_ipsum() {
        assert_eq!(&lipsum()[..11], "Lorem ipsum");
    }

    #[test]
    fn empty_chain() {
        let chain = MarkovChain::new();
        assert_eq!(chain.generate(10), "");
    }

    #[test]
    fn generate_from() {
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz quuz");
        assert_eq!(chain.generate_from(1, ("foo", "bar")), "foo bar baz");
        assert_eq!(chain.generate_from(1, ("bar", "baz")), "bar baz quuz");
    }

    #[test]
    fn generate_from_no_panic() {
        // No panic when asked to generate a chain from a starting
        // point that doesn't exist in the chain.
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz");
        assert_eq!(chain.generate_from(1, ("xxx", "yyy")), "xxx yyy baz");
    }

    #[test]
    fn chain_map() {
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz quuz");
        let map = &chain.map;

        assert_eq!(map.len(), 2);
        assert_eq!(map[&("foo", "bar")], vec!["baz"]);
        assert_eq!(map[&("bar", "baz")], vec!["quuz"]);
    }
}
<|endoftext|>