<commit_before>// Rust JSON-RPC Library
// Written in 2015 by
//     Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Error handling
//!
//! Some useful methods for creating Error objects
//!

use std::{error, fmt};

use hyper;
use serde_json;

use Response;

/// A library error
#[derive(Debug)]
pub enum Error {
    /// Json error
    Json(serde_json::Error),
    /// Client error
    Hyper(hyper::error::Error),
    /// Error response
    Rpc(RpcError),
    /// Response has neither error nor result
    NoErrorOrResult,
    /// Response to a request did not have the expected nonce
    NonceMismatch,
    /// Response to a request had a jsonrpc field other than "2.0"
    VersionMismatch,
}

impl From<serde_json::Error> for Error {
    fn from(e: serde_json::Error) -> Error {
        Error::Json(e)
    }
}

impl From<hyper::error::Error> for Error {
    fn from(e: hyper::error::Error) -> Error {
        Error::Hyper(e)
    }
}

impl From<RpcError> for Error {
    fn from(e: RpcError) -> Error {
        Error::Rpc(e)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Json(ref e) => write!(f, "JSON decode error: {}", e),
            Error::Hyper(ref e) => write!(f, "Hyper error: {}", e),
            Error::Rpc(ref r) => write!(f, "RPC error response: {:?}", r),
            _ => f.write_str(error::Error::description(self)),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Json(_) => "JSON decode error",
            Error::Hyper(_) => "Hyper error",
            Error::Rpc(_) => "RPC error response",
            Error::NoErrorOrResult => "Malformed RPC response",
            Error::NonceMismatch => "Nonce of response did not match nonce of request",
            Error::VersionMismatch => "`jsonrpc` field set to non-\"2.0\"",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Json(ref e) => Some(e),
            Error::Hyper(ref e) => Some(e),
            _ => None,
        }
    }
}

/// Standard error responses, as described at at
/// http://www.jsonrpc.org/specification#error_object
///
/// # Documentation Copyright
/// Copyright (C) 2007-2010 by the JSON-RPC Working Group
///
/// This document and translations of it may be used to implement JSON-RPC, it
/// may be copied and furnished to others, and derivative works that comment
/// on or otherwise explain it or assist in its implementation may be prepared,
/// copied, published and distributed, in whole or in part, without restriction
/// of any kind, provided that the above copyright notice and this paragraph
/// are included on all such copies and derivative works. However, this document
/// itself may not be modified in any way.
///
/// The limited permissions granted above are perpetual and will not be revoked.
///
/// This document and the information contained herein is provided "AS IS" and
/// ALL WARRANTIES, EXPRESS OR IMPLIED are DISCLAIMED, INCLUDING BUT NOT LIMITED
/// TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY
/// RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
/// PARTICULAR PURPOSE.
///
#[derive(Debug)]
pub enum StandardError {
    /// Invalid JSON was received by the server.
    /// An error occurred on the server while parsing the JSON text.
    ParseError,
    /// The JSON sent is not a valid Request object.
    InvalidRequest,
    /// The method does not exist / is not available.
    MethodNotFound,
    /// Invalid method parameter(s).
    InvalidParams,
    /// Internal JSON-RPC error.
    InternalError,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
/// A JSONRPC error object
pub struct RpcError {
    /// The integer identifier of the error
    pub code: i32,
    /// A string describing the error
    pub message: String,
    /// Additional data specific to the error
    pub data: Option<serde_json::Value>,
}

/// Create a standard error responses
pub fn standard_error(code: StandardError, data: Option<serde_json::Value>) -> RpcError {
    match code {
        StandardError::ParseError => RpcError {
            code: -32700,
            message: "Parse error".to_string(),
            data: data,
        },
        StandardError::InvalidRequest => RpcError {
            code: -32600,
            message: "Invalid Request".to_string(),
            data: data,
        },
        StandardError::MethodNotFound => RpcError {
            code: -32601,
            message: "Method not found".to_string(),
            data: data,
        },
        StandardError::InvalidParams => RpcError {
            code: -32602,
            message: "Invalid params".to_string(),
            data: data,
        },
        StandardError::InternalError => RpcError {
            code: -32603,
            message: "Internal error".to_string(),
            data: data,
        },
    }
}

/// Converts a Rust `Result` to a JSONRPC response object
pub fn result_to_response(
    result: Result<serde_json::Value, RpcError>,
    id: serde_json::Value,
) -> Response {
    match result {
        Ok(data) => Response {
            result: Some(data),
            error: None,
            id: id,
            jsonrpc: Some(String::from("2.0")),
        },
        Err(err) => Response {
            result: None,
            error: Some(err),
            id: id,
            jsonrpc: Some(String::from("2.0")),
        },
    }
}

#[cfg(test)]
mod tests {
    use super::StandardError::{
        InternalError, InvalidParams, InvalidRequest, MethodNotFound, ParseError,
    };
    use super::{result_to_response, standard_error};
    use serde_json;

    #[test]
    fn test_parse_error() {
        let resp = result_to_response(Err(standard_error(ParseError, None)), From::from(1));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from(1));
        assert_eq!(resp.error.unwrap().code, -32700);
    }

    #[test]
    fn test_invalid_request() {
        let resp = result_to_response(Err(standard_error(InvalidRequest, None)), From::from(1));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from(1));
        assert_eq!(resp.error.unwrap().code, -32600);
    }

    #[test]
    fn test_method_not_found() {
        let resp = result_to_response(Err(standard_error(MethodNotFound, None)), From::from(1));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from(1));
        assert_eq!(resp.error.unwrap().code, -32601);
    }

    #[test]
    fn test_invalid_params() {
        let resp = result_to_response(Err(standard_error(InvalidParams, None)), From::from("123"));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from("123"));
        assert_eq!(resp.error.unwrap().code, -32602);
    }

    #[test]
    fn test_internal_error() {
        let resp = result_to_response(Err(standard_error(InternalError, None)), From::from(-1));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from(-1));
        assert_eq!(resp.error.unwrap().code, -32603);
    }
}
<commit_msg>Remove now unused error variant<commit_after>// Rust JSON-RPC Library
// Written in 2015 by
//     Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Error handling
//!
//! Some useful methods for creating Error objects
//!

use std::{error, fmt};

use hyper;
use serde_json;

use Response;

/// A library error
#[derive(Debug)]
pub enum Error {
    /// Json error
    Json(serde_json::Error),
    /// Client error
    Hyper(hyper::error::Error),
    /// Error response
    Rpc(RpcError),
    /// Response to a request did not have the expected nonce
    NonceMismatch,
    /// Response to a request had a jsonrpc field other than "2.0"
    VersionMismatch,
}

impl From<serde_json::Error> for Error {
    fn from(e: serde_json::Error) -> Error {
        Error::Json(e)
    }
}

impl From<hyper::error::Error> for Error {
    fn from(e: hyper::error::Error) -> Error {
        Error::Hyper(e)
    }
}

impl From<RpcError> for Error {
    fn from(e: RpcError) -> Error {
        Error::Rpc(e)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Json(ref e) => write!(f, "JSON decode error: {}", e),
            Error::Hyper(ref e) => write!(f, "Hyper error: {}", e),
            Error::Rpc(ref r) => write!(f, "RPC error response: {:?}", r),
            _ => f.write_str(error::Error::description(self)),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Json(_) => "JSON decode error",
            Error::Hyper(_) => "Hyper error",
            Error::Rpc(_) => "RPC error response",
            Error::NonceMismatch => "Nonce of response did not match nonce of request",
            Error::VersionMismatch => "`jsonrpc` field set to non-\"2.0\"",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Json(ref e) => Some(e),
            Error::Hyper(ref e) => Some(e),
            _ => None,
        }
    }
}

/// Standard error responses, as described at at
/// http://www.jsonrpc.org/specification#error_object
///
/// # Documentation Copyright
/// Copyright (C) 2007-2010 by the JSON-RPC Working Group
///
/// This document and translations of it may be used to implement JSON-RPC, it
/// may be copied and furnished to others, and derivative works that comment
/// on or otherwise explain it or assist in its implementation may be prepared,
/// copied, published and distributed, in whole or in part, without restriction
/// of any kind, provided that the above copyright notice and this paragraph
/// are included on all such copies and derivative works. However, this document
/// itself may not be modified in any way.
///
/// The limited permissions granted above are perpetual and will not be revoked.
///
/// This document and the information contained herein is provided "AS IS" and
/// ALL WARRANTIES, EXPRESS OR IMPLIED are DISCLAIMED, INCLUDING BUT NOT LIMITED
/// TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY
/// RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
/// PARTICULAR PURPOSE.
///
#[derive(Debug)]
pub enum StandardError {
    /// Invalid JSON was received by the server.
    /// An error occurred on the server while parsing the JSON text.
    ParseError,
    /// The JSON sent is not a valid Request object.
    InvalidRequest,
    /// The method does not exist / is not available.
    MethodNotFound,
    /// Invalid method parameter(s).
    InvalidParams,
    /// Internal JSON-RPC error.
    InternalError,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
/// A JSONRPC error object
pub struct RpcError {
    /// The integer identifier of the error
    pub code: i32,
    /// A string describing the error
    pub message: String,
    /// Additional data specific to the error
    pub data: Option<serde_json::Value>,
}

/// Create a standard error responses
pub fn standard_error(code: StandardError, data: Option<serde_json::Value>) -> RpcError {
    match code {
        StandardError::ParseError => RpcError {
            code: -32700,
            message: "Parse error".to_string(),
            data: data,
        },
        StandardError::InvalidRequest => RpcError {
            code: -32600,
            message: "Invalid Request".to_string(),
            data: data,
        },
        StandardError::MethodNotFound => RpcError {
            code: -32601,
            message: "Method not found".to_string(),
            data: data,
        },
        StandardError::InvalidParams => RpcError {
            code: -32602,
            message: "Invalid params".to_string(),
            data: data,
        },
        StandardError::InternalError => RpcError {
            code: -32603,
            message: "Internal error".to_string(),
            data: data,
        },
    }
}

/// Converts a Rust `Result` to a JSONRPC response object
pub fn result_to_response(
    result: Result<serde_json::Value, RpcError>,
    id: serde_json::Value,
) -> Response {
    match result {
        Ok(data) => Response {
            result: Some(data),
            error: None,
            id: id,
            jsonrpc: Some(String::from("2.0")),
        },
        Err(err) => Response {
            result: None,
            error: Some(err),
            id: id,
            jsonrpc: Some(String::from("2.0")),
        },
    }
}

#[cfg(test)]
mod tests {
    use super::StandardError::{
        InternalError, InvalidParams, InvalidRequest, MethodNotFound, ParseError,
    };
    use super::{result_to_response, standard_error};
    use serde_json;

    #[test]
    fn test_parse_error() {
        let resp = result_to_response(Err(standard_error(ParseError, None)), From::from(1));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from(1));
        assert_eq!(resp.error.unwrap().code, -32700);
    }

    #[test]
    fn test_invalid_request() {
        let resp = result_to_response(Err(standard_error(InvalidRequest, None)), From::from(1));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from(1));
        assert_eq!(resp.error.unwrap().code, -32600);
    }

    #[test]
    fn test_method_not_found() {
        let resp = result_to_response(Err(standard_error(MethodNotFound, None)), From::from(1));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from(1));
        assert_eq!(resp.error.unwrap().code, -32601);
    }

    #[test]
    fn test_invalid_params() {
        let resp = result_to_response(Err(standard_error(InvalidParams, None)), From::from("123"));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from("123"));
        assert_eq!(resp.error.unwrap().code, -32602);
    }

    #[test]
    fn test_internal_error() {
        let resp = result_to_response(Err(standard_error(InternalError, None)), From::from(-1));
        assert!(resp.result.is_none());
        assert!(resp.error.is_some());
        assert_eq!(resp.id, serde_json::Value::from(-1));
        assert_eq!(resp.error.unwrap().code, -32603);
    }
}
<|endoftext|>


<commit_before>//! Errors that can occur while parsing a configuration

use std::io::Error as IoError;
use parser::ParseError;

/// A generic configuration error type
#[derive(Debug)]
pub struct ConfigError {
    /// Indicates what kind of error this is
    pub kind: ConfigErrorKind,
    /// A descriptive message about the error
    pub desc: &'static str,
    /// Error details, if available
    pub detail: Option<String>
}

/// Possible error kinds
#[derive(Debug)]
#[derive(PartialEq)]
pub enum ConfigErrorKind {
    /// An I/O error. Can only occur if reading from a stream (file, socket, etc.)
    IoError,
    /// A syntax error
    ParseError
}

/// Converts an I/O Error into a `ConfigError`
pub fn from_io_err(err: IoError) -> ConfigError {
    ConfigError {
        kind: ConfigErrorKind::IoError,
        desc: "An I/O error has occurred",
        detail: Some(format!("{}", err))
    }
}

/// Converts a `ParseError` into a `ConfigError`
pub fn from_parse_err(err: ParseError) -> ConfigError {
    ConfigError {
        kind: ConfigErrorKind::ParseError,
        desc: "Syntax error",
        detail: Some(format!("{}", err))
    }
}
<commit_msg>error: refactor out creating the error object<commit_after>//! Errors that can occur while parsing a configuration

use std::fmt;
use std::io::Error as IoError;
use parser::ParseError;

/// A generic configuration error type
#[derive(Debug)]
pub struct ConfigError {
    /// Indicates what kind of error this is
    pub kind: ConfigErrorKind,
    /// A descriptive message about the error
    pub desc: &'static str,
    /// Error details, if available
    pub detail: Option<String>
}

/// Possible error kinds
#[derive(Debug)]
#[derive(PartialEq)]
pub enum ConfigErrorKind {
    /// An I/O error. Can only occur if reading from a stream (file, socket, etc.)
    IoError,
    /// A syntax error
    ParseError
}

fn mk_error<E: fmt::Display>(kind: ConfigErrorKind, desc: &'static str, err: E) -> ConfigError {
    ConfigError {
        kind: kind,
        desc: desc,
        detail: Some(format!("{}", err))
    }
}

/// Converts an I/O Error into a `ConfigError`
pub fn from_io_err(err: IoError) -> ConfigError {
    mk_error(ConfigErrorKind::IoError, "An I/O error has occurred", err)
}

/// Converts a `ParseError` into a `ConfigError`
pub fn from_parse_err(err: ParseError) -> ConfigError {
    mk_error(ConfigErrorKind::ParseError, "Syntax error", err)
}
<|endoftext|>


<commit_before>use std::fmt;

use serde::de;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Visitor, Unexpected};

/// The Telegram `Integer`, currently i64.
pub type Integer = i64;

/// The Telegram `Float`, currently f32.
pub type Float = f32;

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct True; // TODO(knsd): Option<True> => bool?

impl Deserialize for True {
    fn deserialize<D>(deserializer: D) -> Result<True, D::Error> where D: Deserializer {
        struct TrueVisitor;

        impl Visitor for TrueVisitor {
            type Value = True;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("true")
            }

            fn visit_bool<E>(self, value: bool) -> Result<True, E> where E: de::Error {
                match value {
                    true => Ok(True),
                    false => Err(E::invalid_value(Unexpected::Bool(value), &self))
                }
            }
        }

        deserializer.deserialize_bool(TrueVisitor)
    }
}

impl Serialize for True {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_bool(true)
    }
}
<commit_msg>misc: remove one todo item<commit_after>use std::fmt;

use serde::de;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Visitor, Unexpected};

/// The Telegram `Integer`, currently i64.
pub type Integer = i64;

/// The Telegram `Float`, currently f32.
pub type Float = f32;

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct True;

impl Deserialize for True {
    fn deserialize<D>(deserializer: D) -> Result<True, D::Error> where D: Deserializer {
        struct TrueVisitor;

        impl Visitor for TrueVisitor {
            type Value = True;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("true")
            }

            fn visit_bool<E>(self, value: bool) -> Result<True, E> where E: de::Error {
                match value {
                    true => Ok(True),
                    false => Err(E::invalid_value(Unexpected::Bool(value), &self))
                }
            }
        }

        deserializer.deserialize_bool(TrueVisitor)
    }
}

impl Serialize for True {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_bool(true)
    }
}
<|endoftext|>


<commit_before>extern crate num;
extern crate nalgebra as na;

pub const TOTAL_FLUIDS: usize = 8;
pub const NORMAL_DIFFUSION: [f64; TOTAL_FLUIDS] = [0.0004, 4.0, 0.2, 2.0, 0.5, 0.5, 0.5, 0.5];
pub const KILL_FLUID_NORMAL: f64 = 0.05;
pub const KILL_FLUID_DECAY: f64 = 0.01;
pub const KILL_FLUID_UPPER_THRESHOLD: f64 = 0.052;
pub const KILL_FLUID_LOWER_THRESHOLD: f64 = 0.048;
pub const SIGNAL_FLUID_NORMAL: f64 = 0.5;
pub const SIGNAL_FLUID_DECAY: f64 = 0.001;
pub const B_FOOD_RATE: f64 = 0.015;

const TIMESTEP: f64 = 0.2;

#[derive(Default, Debug)]
pub struct Solution {
    pub fluids: [f64; TOTAL_FLUIDS],
    pub coefficients: [f64; TOTAL_FLUIDS],
    pub diffuse: [f64; TOTAL_FLUIDS],
}

impl Solution {
    pub fn new(fluids: [f64; TOTAL_FLUIDS], coefficients: [f64; TOTAL_FLUIDS]) -> Self {
        Solution {
            fluids: fluids,
            coefficients: coefficients,
            diffuse: [0.0; TOTAL_FLUIDS],
        }
    }

    pub fn react_deltas(&self) -> [f64; TOTAL_FLUIDS] {
        let a = self.fluids[1];
        let b = self.fluids[3];
        let kill = self.fluids[2];
        let f = 0.029;
        let k = 0.057;
        [B_FOOD_RATE * b,
         -a * b * b + f * (1.0 - a),
         KILL_FLUID_DECAY * (KILL_FLUID_NORMAL - kill),
         a * b * b - (k + f) * b,
         SIGNAL_FLUID_DECAY * (SIGNAL_FLUID_NORMAL - self.fluids[4]),
         SIGNAL_FLUID_DECAY * (SIGNAL_FLUID_NORMAL - self.fluids[5]),
         SIGNAL_FLUID_DECAY * (SIGNAL_FLUID_NORMAL - self.fluids[6]),
         SIGNAL_FLUID_DECAY * (SIGNAL_FLUID_NORMAL - self.fluids[7])]
    }

    pub fn diffuse_from(&mut self, other: &Solution) {
        for i in 0..TOTAL_FLUIDS {
            self.diffuse[i] += other.fluids[i] * other.coefficients[i] / 6.0;
        }
    }

    pub fn end_cycle(&mut self) {
        let reacts = self.react_deltas();
        for i in 0..TOTAL_FLUIDS {
            self.fluids[i] += TIMESTEP *
                              (reacts[i] + self.diffuse[i] - self.coefficients[i] * self.fluids[i]);
            self.diffuse[i] = 0.0;
        }
    }
}
<commit_msg>reduce food a tiny bit<commit_after>extern crate num;
extern crate nalgebra as na;

pub const TOTAL_FLUIDS: usize = 8;
pub const NORMAL_DIFFUSION: [f64; TOTAL_FLUIDS] = [0.0004, 4.0, 0.2, 2.0, 0.5, 0.5, 0.5, 0.5];
pub const KILL_FLUID_NORMAL: f64 = 0.05;
pub const KILL_FLUID_DECAY: f64 = 0.01;
pub const KILL_FLUID_UPPER_THRESHOLD: f64 = 0.052;
pub const KILL_FLUID_LOWER_THRESHOLD: f64 = 0.048;
pub const SIGNAL_FLUID_NORMAL: f64 = 0.5;
pub const SIGNAL_FLUID_DECAY: f64 = 0.001;
pub const B_FOOD_RATE: f64 = 0.012;

const TIMESTEP: f64 = 0.2;

#[derive(Default, Debug)]
pub struct Solution {
    pub fluids: [f64; TOTAL_FLUIDS],
    pub coefficients: [f64; TOTAL_FLUIDS],
    pub diffuse: [f64; TOTAL_FLUIDS],
}

impl Solution {
    pub fn new(fluids: [f64; TOTAL_FLUIDS], coefficients: [f64; TOTAL_FLUIDS]) -> Self {
        Solution {
            fluids: fluids,
            coefficients: coefficients,
            diffuse: [0.0; TOTAL_FLUIDS],
        }
    }

    pub fn react_deltas(&self) -> [f64; TOTAL_FLUIDS] {
        let a = self.fluids[1];
        let b = self.fluids[3];
        let kill = self.fluids[2];
        let f = 0.029;
        let k = 0.057;
        [B_FOOD_RATE * b,
         -a * b * b + f * (1.0 - a),
         KILL_FLUID_DECAY * (KILL_FLUID_NORMAL - kill),
         a * b * b - (k + f) * b,
         SIGNAL_FLUID_DECAY * (SIGNAL_FLUID_NORMAL - self.fluids[4]),
         SIGNAL_FLUID_DECAY * (SIGNAL_FLUID_NORMAL - self.fluids[5]),
         SIGNAL_FLUID_DECAY * (SIGNAL_FLUID_NORMAL - self.fluids[6]),
         SIGNAL_FLUID_DECAY * (SIGNAL_FLUID_NORMAL - self.fluids[7])]
    }

    pub fn diffuse_from(&mut self, other: &Solution) {
        for i in 0..TOTAL_FLUIDS {
            self.diffuse[i] += other.fluids[i] * other.coefficients[i] / 6.0;
        }
    }

    pub fn end_cycle(&mut self) {
        let reacts = self.react_deltas();
        for i in 0..TOTAL_FLUIDS {
            self.fluids[i] += TIMESTEP *
                              (reacts[i] + self.diffuse[i] - self.coefficients[i] * self.fluids[i]);
            self.diffuse[i] = 0.0;
        }
    }
}
<|endoftext|>


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

use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};

use proc_macro2::Term;
use unicode_xid::UnicodeXID;

use proc_macro2::Span;

/// A word of Rust code, which may be a keyword or legal variable name.
///
/// An identifier consists of at least one Unicode code point, the first of
/// which has the XID_Start property and the rest of which have the XID_Continue
/// property. An underscore may be used as the first character as long as it is
/// not the only character.
///
/// - The empty string is not an identifier. Use `Option<Ident>`.
/// - An underscore by itself is not an identifier. Use
///   `Token![_]` instead.
/// - A lifetime is not an identifier. Use `syn::Lifetime` instead.
///
/// An identifier constructed with `Ident::new` is permitted to be a Rust
/// keyword, though parsing one through its [`Synom`] implementation rejects
/// Rust keywords.
///
/// [`Synom`]: synom/trait.Synom.html
///
/// # Examples
///
/// A new ident can be created from a string using the `Ident::from` function.
/// Idents produced by `Ident::from` are set to resolve at the procedural macro
/// *def site* by default. A different span can be provided explicitly by using
/// `Ident::new`.
///
/// ```rust
/// extern crate syn;
/// extern crate proc_macro2;
///
/// use syn::Ident;
/// use proc_macro2::Span;
///
/// fn main() {
///     let def_ident = Ident::from("definitely");
///     let call_ident = Ident::new("calligraphy", Span::call_site());
///
///     println!("{} {}", def_ident, call_ident);
/// }
/// ```
///
/// An ident can be interpolated into a token stream using the `quote!` macro.
///
/// ```rust
/// #[macro_use]
/// extern crate quote;
///
/// extern crate syn;
/// use syn::Ident;
///
/// fn main() {
///     let ident = Ident::from("demo");
///
///     // Create a variable binding whose name is this ident.
///     let expanded = quote! { let #ident = 10; };
///
///     // Create a variable binding with a slightly different name.
///     let temp_ident = Ident::from(format!("new_{}", ident));
///     let expanded = quote! { let #temp_ident = 10; };
/// }
/// ```
///
/// A string representation of the ident is available through the `as_ref()` and
/// `to_string()` methods.
///
/// ```rust
/// # use syn::Ident;
/// # let ident = Ident::from("another_identifier");
/// #
/// // Examine the ident as a &str.
/// let ident_str = ident.as_ref();
/// if ident_str.len() > 60 {
///     println!("Very long identifier: {}", ident_str)
/// }
///
/// // Create a String from the ident.
/// let ident_string = ident.to_string();
/// give_away(ident_string);
///
/// fn give_away(s: String) { /* ... */ }
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Ident {
    term: Term,
}

impl Ident {
    /// Creates an ident with the given string representation.
    ///
    /// # Panics
    ///
    /// Panics if the input string is neither a keyword nor a legal variable
    /// name.
    pub fn new(s: &str, span: Span) -> Self {
        if s.is_empty() {
            panic!("ident is not allowed to be empty; use Option<Ident>");
        }

        if s.starts_with('\'') {
            panic!("ident is not allowed to be a lifetime; use syn::Lifetime");
        }

        if s.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
            panic!("ident cannot be a number, use syn::Index instead");
        }

        fn xid_ok(s: &str) -> bool {
            let mut chars = s.chars();
            let first = chars.next().unwrap();
            if !(UnicodeXID::is_xid_start(first) || first == '_') {
                return false;
            }
            for ch in chars {
                if !UnicodeXID::is_xid_continue(ch) {
                    return false;
                }
            }
            true
        }

        if !xid_ok(s) {
            panic!("{:?} is not a valid ident", s);
        }

        Ident {
            term: Term::new(s, span),
        }
    }

    pub fn span(&self) -> Span {
        self.term.span()
    }

    pub fn set_span(&mut self, span: Span) {
        self.term.set_span(span);
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident::new(s, Span::call_site())
    }
}

impl From<Token![self]> for Ident {
    fn from(tok: Token![self]) -> Self {
        Ident::new("self", tok.0)
    }
}

impl From<Token![Self]> for Ident {
    fn from(tok: Token![Self]) -> Self {
        Ident::new("Self", tok.0)
    }
}

impl From<Token![super]> for Ident {
    fn from(tok: Token![super]) -> Self {
        Ident::new("super", tok.0)
    }
}

impl From<Token![crate]> for Ident {
    fn from(tok: Token![crate]) -> Self {
        Ident::new("crate", tok.0)
    }
}

impl<'a> From<Cow<'a, str>> for Ident {
    fn from(s: Cow<'a, str>) -> Self {
        Ident::new(&s, Span::call_site())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident::new(&s, Span::call_site())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        self.term.as_str()
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.term.as_str().fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
where
    T: AsRef<str>,
{
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl Eq for Ident {}

impl PartialOrd for Ident {
    fn partial_cmp(&self, other: &Ident) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Ident {
    fn cmp(&self, other: &Ident) -> Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl Hash for Ident {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self.as_ref().hash(h);
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use buffer::Cursor;
    use parse_error;
    use synom::PResult;
    use synom::Synom;

    impl Synom for Ident {
        fn parse(input: Cursor) -> PResult<Self> {
            let (term, rest) = match input.term() {
                Some(term) => term,
                _ => return parse_error(),
            };
            if term.as_str().starts_with('\'') {
                return parse_error();
            }
            match term.as_str() {
                "_"
                // From https://doc.rust-lang.org/grammar.html#keywords
                | "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const"
                | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final"
                | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match"
                | "mod" | "move" | "mut" | "offsetof" | "override" | "priv" | "proc" | "pub"
                | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct"
                | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use"
                | "virtual" | "where" | "while" | "yield" => return parse_error(),
                _ => {}
            }

            Ok((Ident { term: term }, rest))
        }

        fn description() -> Option<&'static str> {
            Some("identifier")
        }
    }

    impl Ident {
        /// Parses any identifier
        ///
        /// This is useful when parsing a DSL which allows Rust keywords as identifiers.
        pub fn parse_any(input: Cursor) -> PResult<Self> {
            let (term, rest) = match input.term() {
                Some(term) => term,
                _ => return parse_error(),
            };
            if term.as_str().starts_with('\'') {
                return parse_error();
            }

            Ok((Ident { term: term }, rest))
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{ToTokens, Tokens};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.term);
        }
    }
}
<commit_msg>Update documentation<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};

use proc_macro2::Term;
use unicode_xid::UnicodeXID;

use proc_macro2::Span;

/// A word of Rust code, which may be a keyword or legal variable name.
///
/// An identifier consists of at least one Unicode code point, the first of
/// which has the XID_Start property and the rest of which have the XID_Continue
/// property. An underscore may be used as the first character as long as it is
/// not the only character.
///
/// - The empty string is not an identifier. Use `Option<Ident>`.
/// - An underscore by itself is not an identifier. Use
///   `Token![_]` instead.
/// - A lifetime is not an identifier. Use `syn::Lifetime` instead.
///
/// An identifier constructed with `Ident::new` is permitted to be a Rust
/// keyword, though parsing one through its [`Synom`] implementation rejects
/// Rust keywords. Use `call!(Ident::parse_any)` when parsing to match the
/// behaviour of `Ident::new`.
///
/// [`Synom`]: synom/trait.Synom.html
///
/// # Examples
///
/// A new ident can be created from a string using the `Ident::from` function.
/// Idents produced by `Ident::from` are set to resolve at the procedural macro
/// *def site* by default. A different span can be provided explicitly by using
/// `Ident::new`.
///
/// ```rust
/// extern crate syn;
/// extern crate proc_macro2;
///
/// use syn::Ident;
/// use proc_macro2::Span;
///
/// fn main() {
///     let def_ident = Ident::from("definitely");
///     let call_ident = Ident::new("calligraphy", Span::call_site());
///
///     println!("{} {}", def_ident, call_ident);
/// }
/// ```
///
/// An ident can be interpolated into a token stream using the `quote!` macro.
///
/// ```rust
/// #[macro_use]
/// extern crate quote;
///
/// extern crate syn;
/// use syn::Ident;
///
/// fn main() {
///     let ident = Ident::from("demo");
///
///     // Create a variable binding whose name is this ident.
///     let expanded = quote! { let #ident = 10; };
///
///     // Create a variable binding with a slightly different name.
///     let temp_ident = Ident::from(format!("new_{}", ident));
///     let expanded = quote! { let #temp_ident = 10; };
/// }
/// ```
///
/// A string representation of the ident is available through the `as_ref()` and
/// `to_string()` methods.
///
/// ```rust
/// # use syn::Ident;
/// # let ident = Ident::from("another_identifier");
/// #
/// // Examine the ident as a &str.
/// let ident_str = ident.as_ref();
/// if ident_str.len() > 60 {
///     println!("Very long identifier: {}", ident_str)
/// }
///
/// // Create a String from the ident.
/// let ident_string = ident.to_string();
/// give_away(ident_string);
///
/// fn give_away(s: String) { /* ... */ }
/// ```
#[derive(Copy, Clone, Debug)]
pub struct Ident {
    term: Term,
}

impl Ident {
    /// Creates an ident with the given string representation.
    ///
    /// # Panics
    ///
    /// Panics if the input string is neither a keyword nor a legal variable
    /// name.
    pub fn new(s: &str, span: Span) -> Self {
        if s.is_empty() {
            panic!("ident is not allowed to be empty; use Option<Ident>");
        }

        if s.starts_with('\'') {
            panic!("ident is not allowed to be a lifetime; use syn::Lifetime");
        }

        if s.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
            panic!("ident cannot be a number, use syn::Index instead");
        }

        fn xid_ok(s: &str) -> bool {
            let mut chars = s.chars();
            let first = chars.next().unwrap();
            if !(UnicodeXID::is_xid_start(first) || first == '_') {
                return false;
            }
            for ch in chars {
                if !UnicodeXID::is_xid_continue(ch) {
                    return false;
                }
            }
            true
        }

        if !xid_ok(s) {
            panic!("{:?} is not a valid ident", s);
        }

        Ident {
            term: Term::new(s, span),
        }
    }

    pub fn span(&self) -> Span {
        self.term.span()
    }

    pub fn set_span(&mut self, span: Span) {
        self.term.set_span(span);
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident::new(s, Span::call_site())
    }
}

impl From<Token![self]> for Ident {
    fn from(tok: Token![self]) -> Self {
        Ident::new("self", tok.0)
    }
}

impl From<Token![Self]> for Ident {
    fn from(tok: Token![Self]) -> Self {
        Ident::new("Self", tok.0)
    }
}

impl From<Token![super]> for Ident {
    fn from(tok: Token![super]) -> Self {
        Ident::new("super", tok.0)
    }
}

impl From<Token![crate]> for Ident {
    fn from(tok: Token![crate]) -> Self {
        Ident::new("crate", tok.0)
    }
}

impl<'a> From<Cow<'a, str>> for Ident {
    fn from(s: Cow<'a, str>) -> Self {
        Ident::new(&s, Span::call_site())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident::new(&s, Span::call_site())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        self.term.as_str()
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.term.as_str().fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
where
    T: AsRef<str>,
{
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl Eq for Ident {}

impl PartialOrd for Ident {
    fn partial_cmp(&self, other: &Ident) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Ident {
    fn cmp(&self, other: &Ident) -> Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl Hash for Ident {
    fn hash<H: Hasher>(&self, h: &mut H) {
        self.as_ref().hash(h);
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use buffer::Cursor;
    use parse_error;
    use synom::PResult;
    use synom::Synom;

    impl Synom for Ident {
        fn parse(input: Cursor) -> PResult<Self> {
            let (term, rest) = match input.term() {
                Some(term) => term,
                _ => return parse_error(),
            };
            if term.as_str().starts_with('\'') {
                return parse_error();
            }
            match term.as_str() {
                "_"
                // From https://doc.rust-lang.org/grammar.html#keywords
                | "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const"
                | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final"
                | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match"
                | "mod" | "move" | "mut" | "offsetof" | "override" | "priv" | "proc" | "pub"
                | "pure" | "ref" | "return" | "Self" | "self" | "sizeof" | "static" | "struct"
                | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use"
                | "virtual" | "where" | "while" | "yield" => return parse_error(),
                _ => {}
            }

            Ok((Ident { term: term }, rest))
        }

        fn description() -> Option<&'static str> {
            Some("identifier")
        }
    }

    impl Ident {
        /// Parses any identifier
        ///
        /// This is useful when parsing a DSL which allows Rust keywords as identifiers.
        pub fn parse_any(input: Cursor) -> PResult<Self> {
            let (term, rest) = match input.term() {
                Some(term) => term,
                _ => return parse_error(),
            };
            if term.as_str().starts_with('\'') {
                return parse_error();
            }

            Ok((Ident { term: term }, rest))
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{ToTokens, Tokens};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.term);
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub};
use std::collections::HashMap;
use std::iter::FromIterator;

struct WordVecBuilder {
    pub word: String,
    pub count: u64,
    vec: Box<[f32; 10_000]>,
}

pub struct WordVec {
    pub word: String,
    pub count: u64,
    vec: Box<[f32; 10_000]>,
}

impl WordVecBuilder {
    fn new(word: String) -> WordVecBuilder {
        WordVecBuilder {
            word: word,
            count: 0,
            vec: Box::new([0f32; 10_000]),
        }
    }

    fn normalize(mut self) -> WordVec {
        for elem in &mut self.vec[..] {
            *elem /= self.count as f32;
        }
        WordVec {
            word: self.word,
            count: self.count,
            vec: self.vec,
        }
    }

    fn inc(&mut self, i: usize) {
        self.vec[i] += 1.0;
    }
}

impl WordVec {

    pub fn distance(&self, other: &WordVec) -> f32 {
        self.vec.iter()
                .zip(other.vec.iter())
                .map(|(x, y)| (x*x - y*y).abs().sqrt())
                .fold(0.0, |x, y| x + y)
    }

}

impl<'a> Add for &'a WordVec {
    type Output = WordVec;

    fn add(self, other: &WordVec) -> WordVec {
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: Box::new([0f32; 10_000]),
        };

        for i in 0..10_000 {
            newvec.vec[i] = self.vec[i] + other.vec[i];
        }

        newvec
    }
}

impl<'a> Sub for &'a WordVec {
    type Output = WordVec;

    fn sub(self, other: &WordVec) -> WordVec {
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: Box::new([0f32; 10_000]),
        };

        for i in 0..10_000 {
            newvec.vec[i] = self.vec[i] - other.vec[i];
        }

        newvec
    }
}

pub struct LanguageModelBuilder {
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVecBuilder>,
}

impl LanguageModelBuilder {
    fn new(words: Vec<String>) -> LanguageModelBuilder {
        assert_eq!(words.len(), 10_000);

        let word_vecs = words.iter()
                              .map(|s| WordVecBuilder::new(s.clone()))
                              .collect();

        let words = HashMap::from_iter(
                        words.into_iter()
                             .enumerate()
                             .map(|(a, b)| (b, a)));

        LanguageModelBuilder {
            words: words,
            word_vecs: word_vecs,
        }
    }
}<commit_msg>Start on word acceptor<commit_after>use std::ops::{Add, Sub};
use std::collections::HashMap;
use std::iter::FromIterator;
use std::collections::VecDeque;

struct WordVecBuilder {
    pub word: String,
    pub count: u64,
    vec: Box<[f32; 10_000]>,
}

pub struct WordVec {
    pub word: String,
    pub count: u64,
    vec: Box<[f32; 10_000]>,
}

impl WordVecBuilder {
    fn new(word: String) -> WordVecBuilder {
        WordVecBuilder {
            word: word,
            count: 0,
            vec: Box::new([0f32; 10_000]),
        }
    }

    fn normalize(mut self) -> WordVec {
        for elem in &mut self.vec[..] {
            *elem /= self.count as f32;
        }
        WordVec {
            word: self.word,
            count: self.count,
            vec: self.vec,
        }
    }

    fn inc(&mut self, i: usize) {
        self.vec[i] += 1.0;
    }
}

impl WordVec {

    pub fn distance(&self, other: &WordVec) -> f32 {
        self.vec.iter()
                .zip(other.vec.iter())
                .map(|(x, y)| (x*x - y*y).abs().sqrt())
                .fold(0.0, |x, y| x + y)
    }

}

impl<'a> Add for &'a WordVec {
    type Output = WordVec;

    fn add(self, other: &WordVec) -> WordVec {
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: Box::new([0f32; 10_000]),
        };

        for i in 0..10_000 {
            newvec.vec[i] = self.vec[i] + other.vec[i];
        }

        newvec
    }
}

impl<'a> Sub for &'a WordVec {
    type Output = WordVec;

    fn sub(self, other: &WordVec) -> WordVec {
        let mut newvec = WordVec {
            word: format!("{} + {}", &self.word, &other.word),
            count: 0,
            vec: Box::new([0f32; 10_000]),
        };

        for i in 0..10_000 {
            newvec.vec[i] = self.vec[i] - other.vec[i];
        }

        newvec
    }
}

pub struct LanguageModel {
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVec>,
}

pub struct LanguageModelBuilder {
    words: HashMap<String, usize>,
    word_vecs: Vec<WordVecBuilder>,
}

pub struct WordAcceptor<'a> {
    window: VecDeque<String>,
    focus: usize,
    builder: &'a mut LanguageModelBuilder,
}

impl<'a> LanguageModelBuilder {
    fn new(words: Vec<String>) -> LanguageModelBuilder {
        assert_eq!(words.len(), 10_000);

        let word_vecs = words.iter()
                             .map(|s| WordVecBuilder::new(s.clone()))
                             .collect();

        let words = HashMap::from_iter(
                        words.into_iter()
                             .enumerate()
                             .map(|(a, b)| (b, a)));

        LanguageModelBuilder {
            words: words,
            word_vecs: word_vecs,
        }
    }

    fn build(self) -> LanguageModel {
        LanguageModel {
            words: self.words,
            word_vecs: self.word_vecs.into_iter()
                                     .map(|b| b.normalize())
                                     .collect(),
        }
    }

    fn newFile(&'a mut self) -> WordAcceptor<'a> {
        WordAcceptor {
            window: VecDeque::new(),
            focus: 0,
            builder: self,
        }
    }
}

impl<'a> WordAcceptor<'a> {
    fn word(&mut self, word: String) {
        if let Some(idx) = self.builder.words.get(&word) {
            self.window.push_back(word);
            if (self.window.len() > 21) {
                self.window.pop_front();
            }
        }
    }
}<|endoftext|>


<commit_before>use feed::Feed;
use statistics::ListenerStats;
use std::borrow::Cow;

#[derive(Fail, Debug)]
pub enum NotifyError {
    #[cfg(any(unix, macos))]
    #[fail(display = "failed to create notification")]
    CreationFailed,

    #[cfg(windows)]
    #[fail(display = "{:?}", _0)]
    WinRT(::winrt::Error),
}

pub enum Icon {
    Update,
    Error,
}

#[cfg(any(unix, macos))]
mod unix {
    extern crate notify_rust;

    use self::notify_rust::Notification;
    use super::*;

    impl Icon {
        fn get_name(&self) -> &str {
            match *self {
                Icon::Update => "emblem-sound",
                Icon::Error => "dialog-error",
            }
        }
    }

    pub fn create(icon: &Icon, title: &str, body: &str) -> Result<(), NotifyError> {
        Notification::new()
            .summary(title)
            .body(body)
            .icon(icon.get_name())
            .show()
            .map_err(|_| NotifyError::CreationFailed)?;

        Ok(())
    }
}

#[cfg(windows)]
mod windows {
    use winrt::FastHString;
    use winrt::windows::data::xml::dom::*;
    use winrt::windows::ui::notifications::*;
    use super::{Icon, NotifyError};

    // The purpose of having an inner create function is so that we only have to specify the error
    // type once if creation fails
    fn inner_create(title: &str, body: &str) -> Result<(), ::winrt::Error> {
        unsafe {
            let toast_xml =
                ToastNotificationManager::get_template_content(ToastTemplateType::ToastText02)?;

            let toast_text_elements =
                toast_xml.get_elements_by_tag_name(&FastHString::new("text"))?;

            let add_text = |i, string| {
                let node = &*toast_xml
                    .create_text_node(&FastHString::new(string))?
                    .query_interface::<IXmlNode>()
                    .unwrap();

                toast_text_elements.item(i)?.append_child(node)
            };

            add_text(0, title)?;
            add_text(1, body)?;

            let toast = ToastNotification::create_toast_notification(&*toast_xml)?;
            let id = env!("CARGO_PKG_NAME");

            ToastNotificationManager::create_toast_notifier_with_id(&FastHString::new(id))?
                .show(&*toast)?;
        }

        Ok(())
    }

    pub fn create(_: &Icon, title: &str, body: &str) -> Result<(), NotifyError> {
        inner_create(title, body).map_err(NotifyError::WinRT)
    }
}

#[cfg(any(unix, macos))]
use self::unix::create;

#[cfg(windows)]
use self::windows::create;

pub fn create_update(
    index: i32,
    max_index: i32,
    feed: &Feed,
    feed_stats: &ListenerStats,
) -> Result<(), NotifyError> {
    let title = format!(
        "{} - Broadcastify Update ({} of {})",
        feed.state.abbrev, index, max_index
    );

    let alert = match feed.alert {
        Some(ref alert) => Cow::Owned(format!("\nAlert: {}", alert)),
        None => Cow::Borrowed(""),
    };

    let body = format!(
        "Name: {}\nListeners: {} (^{}){}\nLink: http://broadcastify.com/listen/feed/{}",
        feed.name,
        feed.listeners,
        feed_stats.get_jump(feed.listeners) as i32,
        &alert,
        feed.id
    );

    create(&Icon::Update, &title, &body)
}

pub fn create_error(body: &str) -> Result<(), NotifyError> {
    create(&Icon::Error, "Broadcastify Update Error", body)
}
<commit_msg>Fix notifications not displaying on Windows since the fall creators update<commit_after>use feed::Feed;
use statistics::ListenerStats;
use std::borrow::Cow;

#[derive(Fail, Debug)]
pub enum NotifyError {
    #[cfg(any(unix, macos))]
    #[fail(display = "failed to create notification")]
    CreationFailed,

    #[cfg(windows)]
    #[fail(display = "{:?}", _0)]
    WinRT(::winrt::Error),
}

pub enum Icon {
    Update,
    Error,
}

#[cfg(any(unix, macos))]
mod unix {
    extern crate notify_rust;

    use self::notify_rust::Notification;
    use super::*;

    impl Icon {
        fn get_name(&self) -> &str {
            match *self {
                Icon::Update => "emblem-sound",
                Icon::Error => "dialog-error",
            }
        }
    }

    pub fn create(icon: &Icon, title: &str, body: &str) -> Result<(), NotifyError> {
        Notification::new()
            .summary(title)
            .body(body)
            .icon(icon.get_name())
            .show()
            .map_err(|_| NotifyError::CreationFailed)?;

        Ok(())
    }
}

#[cfg(windows)]
mod windows {
    use winrt::FastHString;
    use winrt::windows::data::xml::dom::*;
    use winrt::windows::ui::notifications::*;
    use super::{Icon, NotifyError};

    // https://stackoverflow.com/a/46817674
    //
    // The Toast Notification Manager needs a valid app ID for any notifications to actually display,
    // so we'll use one that is already defined since it is not worth the effort to create one ourselves.
    const APP_ID: &str = "{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\\WindowsPowerShell\\v1.0\\powershell.exe";

    // The purpose of having an inner create function is so that we only have to specify the error
    // type once if creation fails
    fn inner_create(title: &str, body: &str) -> Result<(), ::winrt::Error> {
        unsafe {
            let toast_xml =
                ToastNotificationManager::get_template_content(ToastTemplateType::ToastText02)?;

            let toast_text_elements =
                toast_xml.get_elements_by_tag_name(&FastHString::new("text"))?;

            let add_text = |i, string| {
                let node = &*toast_xml
                    .create_text_node(&FastHString::new(string))?
                    .query_interface::<IXmlNode>()
                    .unwrap();

                toast_text_elements.item(i)?.append_child(node)
            };

            add_text(0, title)?;
            add_text(1, body)?;

            let toast = ToastNotification::create_toast_notification(&*toast_xml)?;

            ToastNotificationManager::create_toast_notifier_with_id(&FastHString::new(APP_ID))?
                .show(&*toast)?;
        }

        Ok(())
    }

    pub fn create(_: &Icon, title: &str, body: &str) -> Result<(), NotifyError> {
        inner_create(title, body).map_err(NotifyError::WinRT)
    }
}

#[cfg(any(unix, macos))]
use self::unix::create;

#[cfg(windows)]
use self::windows::create;

pub fn create_update(
    index: i32,
    max_index: i32,
    feed: &Feed,
    feed_stats: &ListenerStats,
) -> Result<(), NotifyError> {
    let title = format!(
        "{} - Broadcastify Update ({} of {})",
        feed.state.abbrev, index, max_index
    );

    let alert = match feed.alert {
        Some(ref alert) => Cow::Owned(format!("\nAlert: {}", alert)),
        None => Cow::Borrowed(""),
    };

    let body = format!(
        "Name: {}\nListeners: {} (^{}){}\nLink: http://broadcastify.com/listen/feed/{}",
        feed.name,
        feed.listeners,
        feed_stats.get_jump(feed.listeners) as i32,
        &alert,
        feed.id
    );

    create(&Icon::Update, &title, &body)
}

pub fn create_error(body: &str) -> Result<(), NotifyError> {
    create(&Icon::Error, "Broadcastify Update Error", body)
}
<|endoftext|>


<commit_before>use notify_rust::{Notification, NotificationHint, NotificationUrgency};
use rusthub::notifications;
use std::process::Command;
use std::thread;

const APP_NAME: &'static str = "gh-notify";

pub fn show_notification(notification: &notifications::Notification) {
    let subject = format!("{} - {}", notification.repository.name, notification.subject.subject_type);
    let body = notification.subject.title.clone();
    let url = notification.repository.html_url.clone();
    thread::spawn(move || {
        notify_action(
            &subject,
            &body,
            "Open in Browser",
            120,
            |action| {
                match action {
                    "default" | "clicked" => {
                        open_link(&url);
                    },
                    "__closed" => (),
                    _ => ()
                }
            }
        );
    });
}

pub fn open_link(url: &str) {
    debug!("Opening browser link: {}", url);
    let _ = Command::new("sh")
        .arg("-c")
        .arg(format!("xdg-open '{}'", url))
        .output()
        .expect("Failed to open web browser instance.");
}

pub fn notify_action<F>(summary: &str, body: &str, button_text: &str, timeout: i32, action: F) where F:FnOnce(&str) {
    Notification::new()
        .appname(APP_NAME)
        .summary(&summary)
        .body(&body)
        .action("default", &button_text)    // IDENTIFIER, LABEL
        .action("clicked", &button_text) // IDENTIFIER, LABEL
        .hint(NotificationHint::Urgency(NotificationUrgency::Normal))
        .timeout(timeout)
        .show()
        .unwrap()
        .wait_for_action(action);
}<commit_msg>cleaned up urls a bit<commit_after>use notify_rust::{Notification, NotificationHint, NotificationUrgency};
use rusthub::notifications;
use std::process::Command;
use std::thread;

const APP_NAME: &'static str = "gh-notify";

pub fn show_notification(notification: &notifications::Notification) {
    let subject = format!("{} - {}", notification.subject.subject_type, notification.repository.name);
    let body = notification.subject.title.clone();
    let url = notification.subject.url.clone();
    let url = url.replace("api.", "").replace("repos/", "").replace("/pulls/", "/pull/");
    thread::spawn(move || {
        notify_action(
            &subject,
            &body,
            "Open in Browser",
            120,
            |action| {
                match action {
                    "default" | "clicked" => {
                        open_link(&url);
                    },
                    "__closed" => (),
                    _ => ()
                }
            }
        );
    });
}

pub fn open_link(url: &str) {
    debug!("Opening browser link: {}", url);
    let _ = Command::new("sh")
        .arg("-c")
        .arg(format!("xdg-open '{}'", url))
        .output()
        .expect("Failed to open web browser instance.");
}

pub fn notify_action<F>(summary: &str, body: &str, button_text: &str, timeout: i32, action: F) where F:FnOnce(&str) {
    Notification::new()
        .appname(APP_NAME)
        .summary(&summary)
        .body(&body)
        .action("default", &button_text)    // IDENTIFIER, LABEL
        .action("clicked", &button_text) // IDENTIFIER, LABEL
        .hint(NotificationHint::Urgency(NotificationUrgency::Normal))
        .timeout(timeout)
        .show()
        .unwrap()
        .wait_for_action(action);
}<|endoftext|>


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

#[link(name = "pcre", vers = "0.1")];
#[crate_type = "lib"];

extern mod extra;

use extra::treemap::{TreeMap};
use std::c_str;
use std::libc::{c_char, c_int, c_uchar, c_void};
use std::option::{Option};
use std::ptr;
use std::vec;

pub type options = c_int;
pub type study_options = c_int;

pub static PCRE_CASELESS: options = 0x00000001;
pub static PCRE_MULTILINE: options = 0x00000002;
pub static PCRE_DOTALL: options = 0x00000004;
pub static PCRE_EXTENDED: options = 0x00000008;
pub static PCRE_ANCHORED: options = 0x00000010;
pub static PCRE_DOLLAR_ENDONLY: options = 0x00000020;
pub static PCRE_EXTRA: options = 0x00000040;
pub static PCRE_NOTBOL: options = 0x00000080;
pub static PCRE_NOTEOL: options = 0x00000100;
pub static PCRE_UNGREEDY: options = 0x00000200;
pub static PCRE_NOTEMPTY: options = 0x00000400;
pub static PCRE_UTF8: options = 0x00000800;
pub static PCRE_UTF16: options = 0x00000800;
pub static PCRE_UTF32: options = 0x00000800;
pub static PCRE_NO_AUTO_CAPTURE: options = 0x00001000;
pub static PCRE_NO_UTF8_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF16_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF32_CHECK: options = 0x00002000;
pub static PCRE_AUTO_CALLOUT: options = 0x00004000;
pub static PCRE_PARTIAL_SOFT: options = 0x00008000;
pub static PCRE_PARTIAL: options = 0x00008000;
pub static PCRE_NEVER_UTF: options = 0x00010000;
pub static PCRE_DFA_SHORTEST: options = 0x00010000;
pub static PCRE_DFA_RESTART: options = 0x00020000;
pub static PCRE_FIRSTLINE: options = 0x00040000;
pub static PCRE_DUPNAMES: options = 0x00080000;
pub static PCRE_NEWLINE_CR: options = 0x00100000;
pub static PCRE_NEWLINE_LF: options = 0x00200000;
pub static PCRE_NEWLINE_CRLF: options = 0x00300000;
pub static PCRE_NEWLINE_ANY: options = 0x00400000;
pub static PCRE_NEWLINE_ANYCRLF: options = 0x00500000;
pub static PCRE_BSR_ANYCRLF: options = 0x00800000;
pub static PCRE_BSR_UNICODE: options = 0x01000000;
pub static PCRE_JAVASCRIPT_COMPAT: options = 0x02000000;
pub static PCRE_NO_START_OPTIMIZE: options = 0x04000000;
pub static PCRE_NO_START_OPTIMISE: options = 0x04000000;
pub static PCRE_PARTIAL_HARD: options = 0x08000000;
pub static PCRE_NOTEMPTY_ATSTART: options = 0x10000000;
pub static PCRE_UCP: options = 0x20000000;

pub static PCRE_STUDY_JIT_COMPILE: study_options = 0x0001;
pub static PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE: study_options = 0x0002;
pub static PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE: study_options = 0x0004;
pub static PCRE_STUDY_EXTRA_NEEDED: study_options = 0x0008;

mod detail;

pub struct Pcre {

    priv code: *detail::pcre,

    priv extra: *detail::pcre_extra,

    priv capture_count_: uint

}

pub struct Match<'self> {

    priv subject: &'self str,

    priv ovector: ~[c_int],

    priv string_count_: uint

}

impl Pcre {
    pub fn compile(pattern: &str) -> Pcre {
        Pcre::compile_with_options(pattern, 0)
    }

    pub fn compile_with_options(pattern: &str, options: options) -> Pcre {
        do pattern.with_c_str |pattern_c_str| {
            // Use the default character tables.
            let tableptr: *c_uchar = ptr::null();
            let code = detail::pcre_compile(pattern_c_str, options, tableptr);
            assert!(ptr::is_not_null(code));

            let extra: *detail::pcre_extra = ptr::null();

            let mut capture_count: c_int = 0;
            detail::pcre_fullinfo(code, extra, detail::PCRE_INFO_CAPTURECOUNT, &mut capture_count as *mut c_int as *mut c_void);

            Pcre {
                code: code,
                extra: extra,
                capture_count_: capture_count as uint
            }
        }
    }

    pub fn capture_count(&self) -> uint {
        self.capture_count_
    }

    pub fn exec<'a>(&self, subject: &'a str) -> Option<Match<'a>> {
        self.exec_from(subject, 0)
    }

    pub fn exec_from<'a>(&self, subject: &'a str, startoffset: uint) -> Option<Match<'a>> {
        self.exec_from_with_options(subject, startoffset, 0)
    }

    pub fn exec_from_with_options<'a>(&self, subject: &'a str, startoffset: uint, options: options) -> Option<Match<'a>> {
        let ovecsize = (self.capture_count_ + 1) * 3;
        let mut ovector: ~[c_int] = vec::from_elem(ovecsize, 0 as c_int);

        unsafe {
            do subject.with_c_str_unchecked |subject_c_str| -> Option<Match<'a>> {
                let rc = detail::pcre_exec(self.code, self.extra, subject_c_str, subject.len() as c_int, startoffset as c_int, options, vec::raw::to_mut_ptr(ovector), ovecsize as c_int);
                if rc >= 0 {
                    Some(Match {
                        subject: subject,
                        ovector: ovector.slice_to((self.capture_count_ + 1) * 2).to_owned(),
                        string_count_: rc as uint
                    })
                } else {
                    None
                }
            }
        }
    }

    pub fn name_count(&self) -> uint {
        let mut name_count: c_int = 0;
        detail::pcre_fullinfo(self.code, self.extra, detail::PCRE_INFO_NAMECOUNT, &mut name_count as *mut c_int as *mut c_void);
        name_count as uint
    }

    pub fn name_table(&self) -> TreeMap<~str, ~[uint]> {
        let name_count = self.name_count();
        let mut tabptr: *c_uchar = ptr::null();
        detail::pcre_fullinfo(self.code, self.extra, detail::PCRE_INFO_NAMETABLE, &mut tabptr as *mut *c_uchar as *mut c_void);
        let mut name_entry_size: c_int = 0;
        detail::pcre_fullinfo(self.code, self.extra, detail::PCRE_INFO_NAMEENTRYSIZE, &mut name_entry_size as *mut c_int as *mut c_void);

        let mut name_table: TreeMap<~str, ~[uint]> = TreeMap::new();

        let mut i = 0u;
        unsafe {
            while i < name_count {
                let n: uint = (ptr::read_ptr(tabptr as *mut c_uchar) as uint << 8) | (ptr::read_ptr(ptr::offset(tabptr, 1) as *mut c_uchar) as uint);
                let name_cstring = c_str::CString::new(ptr::offset(tabptr, 2) as *c_char, false);
                let name: ~str = name_cstring.as_str().unwrap().to_owned();
                // TODO Avoid the double lookup.
                // https://github.com/mozilla/rust/issues/9068
                if !name_table.contains_key(&name) {
                    name_table.insert(name, ~[n]);
                } else {
                    name_table.find_mut(&name).unwrap().push(n);
                }
                tabptr = ptr::offset(tabptr, name_entry_size as int);
                i += 1;
            }
        }

        name_table
    }

    pub fn study(&mut self) -> bool {
        self.study_with_options(0)
    }

    pub fn study_with_options(&mut self, options: study_options) -> bool {
        // Free any current study data.
        detail::pcre_free_study(self.extra);
        self.extra = ptr::null();

        let extra = detail::pcre_study(self.code, options);
        self.extra = extra;
        ptr::is_not_null(extra)
    }
}

impl Drop for Pcre {
    fn drop(&mut self) {
        detail::pcre_free_study(self.extra);
        self.extra = ptr::null();
        detail::pcre_free(self.code as *c_void);
        self.code = ptr::null();
    }
}

impl<'self> Match<'self> {

    pub fn group_start(&self, n: uint) -> uint {
        self.ovector[(n * 2) as uint] as uint
    }

    pub fn group_end(&self, n: uint) -> uint {
        self.ovector[(n * 2 + 1) as uint] as uint
    }

    pub fn group_len(&self, n: uint) -> uint {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        (group_offsets[1] - group_offsets[0]) as uint
    }

    pub fn group(&self, n: uint) -> &'self str {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        let start = group_offsets[0];
        let end = group_offsets[1];
        self.subject.slice(start as uint, end as uint)
    }

    pub fn string_count(&self) -> uint {
        self.string_count_
    }
}

pub fn pcre_version() -> ~str {
    detail::pcre_version()
}
<commit_msg>Change the type of two internal fields to `c_int`<commit_after>// Copyright 2013 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[link(name = "pcre", vers = "0.1")];
#[crate_type = "lib"];

extern mod extra;

use extra::treemap::{TreeMap};
use std::c_str;
use std::libc::{c_char, c_int, c_uchar, c_void};
use std::option::{Option};
use std::ptr;
use std::vec;

pub type options = c_int;
pub type study_options = c_int;

pub static PCRE_CASELESS: options = 0x00000001;
pub static PCRE_MULTILINE: options = 0x00000002;
pub static PCRE_DOTALL: options = 0x00000004;
pub static PCRE_EXTENDED: options = 0x00000008;
pub static PCRE_ANCHORED: options = 0x00000010;
pub static PCRE_DOLLAR_ENDONLY: options = 0x00000020;
pub static PCRE_EXTRA: options = 0x00000040;
pub static PCRE_NOTBOL: options = 0x00000080;
pub static PCRE_NOTEOL: options = 0x00000100;
pub static PCRE_UNGREEDY: options = 0x00000200;
pub static PCRE_NOTEMPTY: options = 0x00000400;
pub static PCRE_UTF8: options = 0x00000800;
pub static PCRE_UTF16: options = 0x00000800;
pub static PCRE_UTF32: options = 0x00000800;
pub static PCRE_NO_AUTO_CAPTURE: options = 0x00001000;
pub static PCRE_NO_UTF8_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF16_CHECK: options = 0x00002000;
pub static PCRE_NO_UTF32_CHECK: options = 0x00002000;
pub static PCRE_AUTO_CALLOUT: options = 0x00004000;
pub static PCRE_PARTIAL_SOFT: options = 0x00008000;
pub static PCRE_PARTIAL: options = 0x00008000;
pub static PCRE_NEVER_UTF: options = 0x00010000;
pub static PCRE_DFA_SHORTEST: options = 0x00010000;
pub static PCRE_DFA_RESTART: options = 0x00020000;
pub static PCRE_FIRSTLINE: options = 0x00040000;
pub static PCRE_DUPNAMES: options = 0x00080000;
pub static PCRE_NEWLINE_CR: options = 0x00100000;
pub static PCRE_NEWLINE_LF: options = 0x00200000;
pub static PCRE_NEWLINE_CRLF: options = 0x00300000;
pub static PCRE_NEWLINE_ANY: options = 0x00400000;
pub static PCRE_NEWLINE_ANYCRLF: options = 0x00500000;
pub static PCRE_BSR_ANYCRLF: options = 0x00800000;
pub static PCRE_BSR_UNICODE: options = 0x01000000;
pub static PCRE_JAVASCRIPT_COMPAT: options = 0x02000000;
pub static PCRE_NO_START_OPTIMIZE: options = 0x04000000;
pub static PCRE_NO_START_OPTIMISE: options = 0x04000000;
pub static PCRE_PARTIAL_HARD: options = 0x08000000;
pub static PCRE_NOTEMPTY_ATSTART: options = 0x10000000;
pub static PCRE_UCP: options = 0x20000000;

pub static PCRE_STUDY_JIT_COMPILE: study_options = 0x0001;
pub static PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE: study_options = 0x0002;
pub static PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE: study_options = 0x0004;
pub static PCRE_STUDY_EXTRA_NEEDED: study_options = 0x0008;

mod detail;

pub struct Pcre {

    priv code: *detail::pcre,

    priv extra: *detail::pcre_extra,

    priv capture_count_: c_int

}

pub struct Match<'self> {

    priv subject: &'self str,

    priv ovector: ~[c_int],

    priv string_count_: c_int

}

impl Pcre {
    pub fn compile(pattern: &str) -> Pcre {
        Pcre::compile_with_options(pattern, 0)
    }

    pub fn compile_with_options(pattern: &str, options: options) -> Pcre {
        do pattern.with_c_str |pattern_c_str| {
            // Use the default character tables.
            let tableptr: *c_uchar = ptr::null();
            let code = detail::pcre_compile(pattern_c_str, options, tableptr);
            assert!(ptr::is_not_null(code));

            let extra: *detail::pcre_extra = ptr::null();

            let mut capture_count: c_int = 0;
            detail::pcre_fullinfo(code, extra, detail::PCRE_INFO_CAPTURECOUNT, &mut capture_count as *mut c_int as *mut c_void);

            Pcre {
                code: code,
                extra: extra,
                capture_count_: capture_count
            }
        }
    }

    pub fn capture_count(&self) -> uint {
        self.capture_count_ as uint
    }

    pub fn exec<'a>(&self, subject: &'a str) -> Option<Match<'a>> {
        self.exec_from(subject, 0)
    }

    pub fn exec_from<'a>(&self, subject: &'a str, startoffset: uint) -> Option<Match<'a>> {
        self.exec_from_with_options(subject, startoffset, 0)
    }

    pub fn exec_from_with_options<'a>(&self, subject: &'a str, startoffset: uint, options: options) -> Option<Match<'a>> {
        let ovecsize = (self.capture_count_ + 1) * 3;
        let mut ovector: ~[c_int] = vec::from_elem(ovecsize as uint, 0 as c_int);

        unsafe {
            do subject.with_c_str_unchecked |subject_c_str| -> Option<Match<'a>> {
                let rc = detail::pcre_exec(self.code, self.extra, subject_c_str, subject.len() as c_int, startoffset as c_int, options, vec::raw::to_mut_ptr(ovector), ovecsize as c_int);
                if rc >= 0 {
                    Some(Match {
                        subject: subject,
                        ovector: ovector.slice_to(((self.capture_count_ + 1) * 2) as uint).to_owned(),
                        string_count_: rc
                    })
                } else {
                    None
                }
            }
        }
    }

    pub fn name_count(&self) -> uint {
        let mut name_count: c_int = 0;
        detail::pcre_fullinfo(self.code, self.extra, detail::PCRE_INFO_NAMECOUNT, &mut name_count as *mut c_int as *mut c_void);
        name_count as uint
    }

    pub fn name_table(&self) -> TreeMap<~str, ~[uint]> {
        let name_count = self.name_count();
        let mut tabptr: *c_uchar = ptr::null();
        detail::pcre_fullinfo(self.code, self.extra, detail::PCRE_INFO_NAMETABLE, &mut tabptr as *mut *c_uchar as *mut c_void);
        let mut name_entry_size: c_int = 0;
        detail::pcre_fullinfo(self.code, self.extra, detail::PCRE_INFO_NAMEENTRYSIZE, &mut name_entry_size as *mut c_int as *mut c_void);

        let mut name_table: TreeMap<~str, ~[uint]> = TreeMap::new();

        let mut i = 0u;
        unsafe {
            while i < name_count {
                let n: uint = (ptr::read_ptr(tabptr as *mut c_uchar) as uint << 8) | (ptr::read_ptr(ptr::offset(tabptr, 1) as *mut c_uchar) as uint);
                let name_cstring = c_str::CString::new(ptr::offset(tabptr, 2) as *c_char, false);
                let name: ~str = name_cstring.as_str().unwrap().to_owned();
                // TODO Avoid the double lookup.
                // https://github.com/mozilla/rust/issues/9068
                if !name_table.contains_key(&name) {
                    name_table.insert(name, ~[n]);
                } else {
                    name_table.find_mut(&name).unwrap().push(n);
                }
                tabptr = ptr::offset(tabptr, name_entry_size as int);
                i += 1;
            }
        }

        name_table
    }

    pub fn study(&mut self) -> bool {
        self.study_with_options(0)
    }

    pub fn study_with_options(&mut self, options: study_options) -> bool {
        // Free any current study data.
        detail::pcre_free_study(self.extra);
        self.extra = ptr::null();

        let extra = detail::pcre_study(self.code, options);
        self.extra = extra;
        ptr::is_not_null(extra)
    }
}

impl Drop for Pcre {
    fn drop(&mut self) {
        detail::pcre_free_study(self.extra);
        self.extra = ptr::null();
        detail::pcre_free(self.code as *c_void);
        self.code = ptr::null();
    }
}

impl<'self> Match<'self> {

    pub fn group_start(&self, n: uint) -> uint {
        self.ovector[(n * 2) as uint] as uint
    }

    pub fn group_end(&self, n: uint) -> uint {
        self.ovector[(n * 2 + 1) as uint] as uint
    }

    pub fn group_len(&self, n: uint) -> uint {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        (group_offsets[1] - group_offsets[0]) as uint
    }

    pub fn group(&self, n: uint) -> &'self str {
        let group_offsets = self.ovector.slice_from((n * 2) as uint);
        let start = group_offsets[0];
        let end = group_offsets[1];
        self.subject.slice(start as uint, end as uint)
    }

    pub fn string_count(&self) -> uint {
        self.string_count_ as uint
    }
}

pub fn pcre_version() -> ~str {
    detail::pcre_version()
}
<|endoftext|>