<commit_before>// Rust JSON-RPC Library
// Written in 2014 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 serialize::json;

use {JsonResult, Response};

/// 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 bemodified 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.
///
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
}

#[deriving(Clone, Show, Encodable)]
/// A JSONRPC error object
pub struct Error {
  code: int,
  message: String,
  data: Option<json::Json>
}

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

/// Converts a Rust `Result` to a JSONRPC response object
pub fn result_to_response(result: JsonResult<json::Json>, id: json::Json) -> Response {
  match result {
    Ok(data) => Response { result: Some(data), error: None, id: id },
    Err(err) => Response { result: None, error: Some(err), id: id }
  }
}

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

  use serialize::json;

  #[test]
  fn test_parse_error() {
    let resp = result_to_response(Err(standard_error(ParseError, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32700);
  }

  #[test]
  fn test_invalid_request() {
    let resp = result_to_response(Err(standard_error(InvalidRequest, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32600);
  }

  #[test]
  fn test_method_not_found() {
    let resp = result_to_response(Err(standard_error(MethodNotFound, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32601);
  }

  #[test]
  fn test_invalid_params() {
    let resp = result_to_response(Err(standard_error(InvalidParams, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32602);
  }

  #[test]
  fn test_internal_error() {
    let resp = result_to_response(Err(standard_error(InternalError, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32603);
  }
}

<commit_msg>Make Error fields public<commit_after>// Rust JSON-RPC Library
// Written in 2014 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 serialize::json;

use {JsonResult, Response};

/// 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 bemodified 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.
///
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
}

#[deriving(Clone, Show, Encodable)]
/// A JSONRPC error object
pub struct Error {
  /// The integer identifier of the error
  pub code: int,
  /// A string describing the error
  pub message: String,
  /// Additional data specific to the error
  pub data: Option<json::Json>
}

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

/// Converts a Rust `Result` to a JSONRPC response object
pub fn result_to_response(result: JsonResult<json::Json>, id: json::Json) -> Response {
  match result {
    Ok(data) => Response { result: Some(data), error: None, id: id },
    Err(err) => Response { result: None, error: Some(err), id: id }
  }
}

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

  use serialize::json;

  #[test]
  fn test_parse_error() {
    let resp = result_to_response(Err(standard_error(ParseError, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32700);
  }

  #[test]
  fn test_invalid_request() {
    let resp = result_to_response(Err(standard_error(InvalidRequest, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32600);
  }

  #[test]
  fn test_method_not_found() {
    let resp = result_to_response(Err(standard_error(MethodNotFound, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32601);
  }

  #[test]
  fn test_invalid_params() {
    let resp = result_to_response(Err(standard_error(InvalidParams, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32602);
  }

  #[test]
  fn test_internal_error() {
    let resp = result_to_response(Err(standard_error(InternalError, None)), json::Number(1.0));
    assert!(resp.result.is_none());
    assert!(resp.error.is_some());
    assert_eq!(resp.id, json::Number(1.0));
    assert_eq!(resp.error.get_ref().code, -32603);
  }
}

<|endoftext|>


<commit_before>//! Error and result module

use client::FutureResponse;
use tokio_timer::TimeoutError;
use std::error::Error as StdError;
use std::io::Error as IoError;
use serde_json::Error as SerdeError;
use openssl::error::ErrorStack;
use std::fmt;
use std::convert::From;
use response::Response;

#[derive(Debug)]
pub enum Error {
    SerializeError,
    ConnectionError,
    TimeoutError,
    SignerError(String),
    ResponseError(Response),
    InvalidOptions(String),
    TlsError(String),
    ReadError(String),
}

impl<'a> fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}", self.description())
    }
}

impl<'a> StdError for Error {
    fn description(&self) -> &str {
        match self {
            &Error::SerializeError => "Error serializing to JSON",
            &Error::ConnectionError => "Error connecting to APNs",
            &Error::SignerError(_) => "Error creating a signature",
            &Error::ResponseError(_) => "Notification was not accepted by APNs",
            &Error::InvalidOptions(_) => "Invalid options for APNs payload",
            &Error::TlsError(_) => "Error in creating a TLS connection",
            &Error::ReadError(_) => "Error in reading a certificate file",
            &Error::TimeoutError => "Timeout in sending a push notification",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        None
    }
}

impl From<TimeoutError<FutureResponse>> for Error {
    fn from(_: TimeoutError<FutureResponse>) -> Error {
        Error::TimeoutError
    }
}

impl<'a> From<SerdeError> for Error {
    fn from(_: SerdeError) -> Error {
        Error::SerializeError
    }
}

impl<'a> From<ErrorStack> for Error {
    fn from(e: ErrorStack) -> Error {
        Error::SignerError(format!("{}", e.description()))
    }
}

impl<'a> From<IoError> for Error {
    fn from(e: IoError) -> Error {
        Error::ReadError(format!("{}", e.description()))
    }
}
<commit_msg>Show APNS error reason in Display impl<commit_after>//! Error and result module

use client::FutureResponse;
use tokio_timer::TimeoutError;
use std::error::Error as StdError;
use std::io::Error as IoError;
use serde_json::Error as SerdeError;
use openssl::error::ErrorStack;
use std::fmt;
use std::convert::From;
use response::{Response, ErrorBody};

#[derive(Debug)]
pub enum Error {
    SerializeError,
    ConnectionError,
    TimeoutError,
    SignerError(String),
    ResponseError(Response),
    InvalidOptions(String),
    TlsError(String),
    ReadError(String),
}

impl<'a> fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::ResponseError(Response { error: Some(ErrorBody { ref reason, .. }), .. }) => {
                write!(fmt, "{} (reason: {:?})", self.description(), reason)
            },
            _ => write!(fmt, "{}", self.description()),
        }
    }
}

impl<'a> StdError for Error {
    fn description(&self) -> &str {
        match self {
            &Error::SerializeError => "Error serializing to JSON",
            &Error::ConnectionError => "Error connecting to APNs",
            &Error::SignerError(_) => "Error creating a signature",
            &Error::ResponseError(_) => "Notification was not accepted by APNs",
            &Error::InvalidOptions(_) => "Invalid options for APNs payload",
            &Error::TlsError(_) => "Error in creating a TLS connection",
            &Error::ReadError(_) => "Error in reading a certificate file",
            &Error::TimeoutError => "Timeout in sending a push notification",
        }
    }

    fn cause(&self) -> Option<&StdError> {
        None
    }
}

impl From<TimeoutError<FutureResponse>> for Error {
    fn from(_: TimeoutError<FutureResponse>) -> Error {
        Error::TimeoutError
    }
}

impl<'a> From<SerdeError> for Error {
    fn from(_: SerdeError) -> Error {
        Error::SerializeError
    }
}

impl<'a> From<ErrorStack> for Error {
    fn from(e: ErrorStack) -> Error {
        Error::SignerError(format!("{}", e.description()))
    }
}

impl<'a> From<IoError> for Error {
    fn from(e: IoError) -> Error {
        Error::ReadError(format!("{}", e.description()))
    }
}
<|endoftext|>


<commit_before>//! 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)
}
<commit_msg>error: implement an Error instance for ConfigError<commit_after>//! Errors that can occur while parsing a configuration

use std::error::Error;
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>,

    err_desc: 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 {
    let err_desc = format!("{:?} {}: {}", kind, desc, err);
    ConfigError {
        kind: kind,
        desc: desc,
        detail: Some(format!("{}", err)),

        err_desc: err_desc
    }
}

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

impl fmt::Display for ConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }
}

impl Error for ConfigError {
    fn description(&self) -> &str {
        &self.err_desc[..]
    }
}
<|endoftext|>


<commit_before>use errors::sovrin::SovrinError;
use commands::{Command, CommandExecutor};
use commands::sovrin::SovrinCommand;
use common::{SovrinRole, SovrinIdentity};

use std::error;
use std::sync::Arc;

pub struct SovrinAPI {
    command_executor: Arc<CommandExecutor>
}

impl SovrinAPI {
    /// Constructs a new `SovrinAPI`.
    ///
    /// #Params
    /// command_executor: Reference to `CommandExecutor` instance.
    ///
    pub fn new(command_executor: Arc<CommandExecutor>) -> SovrinAPI {
        SovrinAPI {
            command_executor: command_executor
        }
    }

    /// Sends NYM transaction to Identity Ledger.
    ///
    /// Creates a new NYM records for specific user, trust anchor, steward or trustee.
    /// Note that only trustees and stewards can create new sponsors and trustee can be created only by other trusties.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Id of a target NYM record or an alias.
    /// verkey: Optional(defaults to dest). Verification key.
    /// xref: Optional (Required if dest is an alias). Id of a NYM record.
    /// data: Optional. Alias.
    /// role: Optional (defaults to None). Role of a user NYM record being created for.
    ///     One of USER, TRUST_ANCHOR, STEWARD, TRUSTEE.
    ///     Also a TRUSTEE can change any Nym's role to None, this stopping it from making any writes.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// No result.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_nym_tx(&self, identity: &SovrinIdentity, dest: &str, verkey: Option<&str>, xref: Option<&str>,
                       data: Option<&str>, role: Option<SovrinRole>,
                       cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        self.command_executor.send(
            Command::Sovrin(
                SovrinCommand::SendNymTx(
                    dest.to_string(),
                    verkey.map(String::from),
                    xref.map(String::from),
                    data.map(String::from),
                    role,
                    cb)));
    }

    /// Sends ATTRIB transaction to Identity Ledger.
    ///
    /// Adds attribute to NYM record.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Optional (defaults to origin). Id of a target NYM record.
    /// hash: Hash of attribute data.
    /// raw: Raw attribute data represented as json, where key is attribute name and value is it's value.
    /// enc: Optional. Encrypted attribute data.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// No result.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_attrib_tx(&self, identity: &SovrinIdentity, dest: Option<&str>, hash: &str, raw: &str, enc: &str,
                       cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends GET_ATTR transaction to Identity Ledger.
    ///
    /// Get attribute value.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Id of a target NYM record.
    /// data: Attribute name.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// Attribute value.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_get_att_tx(&self, identity: &SovrinIdentity, dest: &str, data: &str,
                          cb: Box<Fn(Result<String, SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends GET_NYM transaction to Identity Ledger.
    ///
    /// Get information about existing NYM record, such as a role
    /// and id of a sponsor, who created it.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Id of a target NYM record.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// NIM data represent as json.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_get_nym_tx(&self, identity: &SovrinIdentity, dest: &str,
                           cb: Box<Fn(Result<String, SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends SCHEMA transaction to Identity Ledger.
    ///
    /// Write the schema of a claim on sovrin.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Id of a target NYM record.
    /// data: Schema represent as json: name, version, type, attr_names (ip, port, keys) and etc...
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// NIM data represent as json.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_get_schema_tx(&self, identity: &SovrinIdentity, data: &str,
                           cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends GET_SCHEMA transaction to Identity Ledger.
    ///
    /// Write the schema of a claim on sovrin.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Id of a target NYM record.
    /// data: Schema represent as json: name, version, type, attr_names (ip, port, keys) and etc...
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// NIM data represent as json.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_schema_tx(&self, identity: &SovrinIdentity, data: &str,
                          cb: Box<Fn(Result<String, SovrinError>) + Send>) {
        unimplemented!();
    }
}

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

    #[test]
    fn sovrin_api_can_be_created() {
        let sovrin_api = SovrinAPI::new(Arc::new(CommandExecutor::new()));
        assert! (true, "No crashes on SovrinAPI::new");
    }

    #[test]
    fn sovrin_api_can_be_dropped() {
        fn drop_test() {
            let sovrin_api = SovrinAPI::new(Arc::new(CommandExecutor::new()));
        }

        drop_test();
        assert! (true, "No crashes on SovrinAPI::drop");
    }
}<commit_msg>* Added additional Sovrin API methods<commit_after>use errors::sovrin::SovrinError;
use commands::{Command, CommandExecutor};
use commands::sovrin::SovrinCommand;
use common::{SovrinRole, SovrinIdentity};

use std::error;
use std::sync::Arc;

pub struct SovrinAPI {
    command_executor: Arc<CommandExecutor>
}

impl SovrinAPI {
    /// Constructs a new `SovrinAPI`.
    ///
    /// #Params
    /// command_executor: Reference to `CommandExecutor` instance.
    ///
    pub fn new(command_executor: Arc<CommandExecutor>) -> SovrinAPI {
        SovrinAPI {
            command_executor: command_executor
        }
    }

    /// Sends NYM transaction to Identity Ledger.
    ///
    /// Creates a new NYM records for specific user, trust anchor, steward or trustee.
    /// Note that only trustees and stewards can create new sponsors and trustee can be created only by other trusties.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Id of a target NYM record or an alias.
    /// verkey: Optional(defaults to dest). Verification key.
    /// xref: Optional (Required if dest is an alias). Id of a NYM record.
    /// data: Optional. Alias.
    /// role: Optional (defaults to None). Role of a user NYM record being created for.
    ///     One of USER, TRUST_ANCHOR, STEWARD, TRUSTEE.
    ///     Also a TRUSTEE can change any Nym's role to None, this stopping it from making any writes.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// No result.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_nym_tx(&self, identity: &SovrinIdentity, dest: &str, verkey: Option<&str>, xref: Option<&str>,
                       data: Option<&str>, role: Option<SovrinRole>,
                       cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        self.command_executor.send(
            Command::Sovrin(
                SovrinCommand::SendNymTx(
                    dest.to_string(),
                    verkey.map(String::from),
                    xref.map(String::from),
                    data.map(String::from),
                    role,
                    cb)));
    }

    /// Sends ATTRIB transaction to Identity Ledger.
    ///
    /// Adds attribute to NYM record.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Optional (defaults to origin). Id of a target NYM record.
    /// hash: Hash of attribute data.
    /// raw: Raw attribute data represented as json, where key is attribute name and value is it's value.
    /// enc: Optional. Encrypted attribute data.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// No result.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_attrib_tx(&self, identity: &SovrinIdentity, dest: Option<&str>, hash: &str, raw: &str, enc: &str,
                          cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends GET_ATTR transaction to Identity Ledger.
    ///
    /// Get attribute value.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Id of a target NYM record.
    /// data: Attribute name.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// Attribute value.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_get_att_tx(&self, identity: &SovrinIdentity, dest: &str, data: &str,
                           cb: Box<Fn(Result<String, SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends GET_NYM transaction to Identity Ledger.
    ///
    /// Get information about existing NYM record, such as a role
    /// and id of a sponsor, who created it.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: Id of a target NYM record.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// NIM data represent as json.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_get_nym_tx(&self, identity: &SovrinIdentity, dest: &str,
                           cb: Box<Fn(Result<String, SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends SCHEMA transaction to Identity Ledger.
    ///
    /// Write the schema of a claim on sovrin.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// data: Schema represent as json: name, version, type, attr_names (ip, port, keys) and etc...
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// No data
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_schema_tx(&self, identity: &SovrinIdentity, data: &str,
                          cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends GET_SCHEMA transaction to Identity Ledger.
    ///
    /// Write the schema of a claim on sovrin.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// data: Schema query represent as json: name and version
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// Schema data represent as json.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_get_schema_tx(&self, identity: &SovrinIdentity, data: &str,
                              cb: Box<Fn(Result<String, SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends ISSUER_KEY transaction to Identity Ledger.
    ///
    /// Set public key, that Issuer creates and publishes for a particular credential definition.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// xref: Seq. number of schema.
    /// data: components of a key as json: N, R, S, Z.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// No data
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_issuer_key_tx(&self, identity: &SovrinIdentity, xref: &str, data: &str,
                              cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends GET_ISSUER_KEY transaction to Identity Ledger.
    ///
    /// Get issuer key.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// xref: Seq. number of schema.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// Issuer key represent as json.
    ///
    /// #Errors
    /// No method specific errors.
    /// See `SovrinError` docs for common errors description.
    pub fn send_get_issuer_key_tx(&self, identity: &SovrinIdentity, xref: &str,
                                  cb: Box<Fn(Result<String, SovrinError>) + Send>) {
        unimplemented!();
    }

    /// Sends NODE transaction to Pool Ledger.
    ///
    /// Add new node to a cluster, or update existing node of pool.
    ///
    /// #Params
    /// identity: Transaction identity.
    /// dest: id of a target NYM record.
    /// data: Node data as json: node_ip, node_port, client_ip, client_port,alias.
    /// cb: Callback that takes command result as parameter.
    ///
    /// #Returns
    /// No data.
    ///
    /// #Errors
    /// No method specific errors.
/// See `SovrinError` docs for common errors description.
    pub fn send_node_tx(&self, identity: &SovrinIdentity, dest: &str, data: &str,
                        cb: Box<Fn(Result<(), SovrinError>) + Send>) {
        unimplemented!();
    }
}

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

    #[test]
    fn sovrin_api_can_be_created() {
        let sovrin_api = SovrinAPI::new(Arc::new(CommandExecutor::new()));
        assert! (true, "No crashes on SovrinAPI::new");
    }

    #[test]
    fn sovrin_api_can_be_dropped() {
        fn drop_test() {
            let sovrin_api = SovrinAPI::new(Arc::new(CommandExecutor::new()));
        }

        drop_test();
        assert! (true, "No crashes on SovrinAPI::drop");
    }
}<|endoftext|>


<commit_before>//! Implements basic arithmetic and polynomial operations in GF(2^8).

use rand::{CryptoRng, Rng};

/// Multiply two elements of GF(2^8).
pub fn mul(lhs: u8, rhs: u8) -> u8 {
    // This algorithm is constant-time, allowing us to perform GF256 arithmetic over secret values
    // without leaking information about the values via timing.
    let mut aa = lhs;
    let mut bb = rhs;
    let mut r = 0;
    // Loop over all 8 bits, regardless of whether or not it's required. aa != 0 is the usual loop
    // condition, but here it's folded into the per-round bitmask.
    for _ in 0..8 {
        // Perform r ^= bb iff aa & 1 == 0 && aa != 0.
        let loop_live = bool_to_mask(aa != 0);
        r ^= bb & bool_to_mask(aa & 1 != 0) & loop_live;
        let t = bb & 0x80;
        bb <<= 1;
        // Perform bb ^= 0x1b iff t != 0 && aa != 0.
        bb ^= 0x1b & bool_to_mask(t != 0) & loop_live;
        aa >>= 1;
    }
    r
}

/// Divide one element of GF(2^8) by another.
pub fn div(lhs: u8, rhs: u8) -> u8 {
    if rhs == 0 {
        panic!("Divide by zero: {} / {}", lhs, rhs)
    }

    // Again, this algorithm is constant-time. First, we find the multiplicative inverse of `a` by
    // iterating over all possible values, and using a bitmask to accumulate only that value which,
    // when multiplied by `a`, is `1`.
    let mut inv = 0;
    for i in 0x00..=0xff {
        inv += i & bool_to_mask(mul(i, rhs) == 1);
    }

    // Finally, we multiply `e` by the multiplicative inverse of `a`.
    mul(inv, lhs)
}

// If b is true, return 0xff, otherwise, return 0x00. Constant-time implementation.
#[inline(always)]
fn bool_to_mask(b: bool) -> u8 {
    (b as u8) * 0xff
}

/// Evaluate a polynomial, returning the Y value for the given X value.
pub fn eval(p: &[u8], x: u8) -> u8 {
    p.iter().rev().fold(0, |res, &v| mul(res, x) ^ v)
}

/// Generates a random polynomial of the Nth degree with a Y-intercept with the
/// given value.
pub fn generate<R>(n: usize, y: u8, rng: &mut R) -> Vec<u8>
where
    R: Rng + CryptoRng,
{
    // Allocate a vec of n+1 bytes.
    let mut p = vec![0; n + 1];

    // Set its Y-intercept to the given value.
    p[0] = y;

    // Generate random coefficients.
    rng.fill_bytes(&mut p[1..n]);

    // Ensure the Nth coefficient is non-zero, otherwise it's an (N-1)th-degree
    // polynomial.
    p[n] = rng.gen_range(1, 255);

    p
}

/// Interpolates a vector of (X, Y) points, returning the Y value at zero.
pub fn y_intercept(points: Vec<(u8, u8)>) -> u8 {
    let mut value = 0;
    for (i, &(ax, ay)) in points.iter().enumerate() {
        let mut weight = 1;
        for (j, &(bx, _)) in points.iter().enumerate() {
            if i != j {
                weight = mul(weight, div(bx, ax ^ bx));
            }
        }
        value ^= mul(weight, ay)
    }
    value
}

#[cfg(test)]
mod test {
    extern crate proptest;
    extern crate rand_chacha;

    use super::*;
    use rand::SeedableRng;

    use self::proptest::prelude::*;
    use self::rand_chacha::ChaChaRng;

    proptest! {
        #[test]
        fn test_div_is_inverse_of_mul(a in 0u8..=255, b in 1u8..=255) {
            assert_eq!(mul(div(a, b), b), a);
        }

        #[test]
        fn test_mul_is_inverse_of_div(a in 0u8..=255, b in 1u8..=255) {
            assert_eq!(div(mul(a, b), b), a);
        }

        #[test]
        fn test_mul_is_commutative(a in 0u8..=255, b in 0u8..=255) {
            assert_eq!(mul(a, b), mul(b, a));
        }
    }

    #[test]
    fn test_mul() {
        assert_eq!(mul(90, 21), 254);
        assert_eq!(mul(133, 5), 167);
        assert_eq!(mul(0, 21), 0);
    }

    #[test]
    fn test_div() {
        assert_eq!(div(90, 21), 189);
        assert_eq!(div(6, 55), 151);
        assert_eq!(div(22, 192), 138);
        assert_eq!(div(0, 21), 0);
    }

    #[test]
    fn test_eval() {
        assert_eq!(eval(&vec![1, 0, 2, 3], 2), 17);
    }

    proptest! {
        #[test]
        fn test_generate(seed: [u8; 32]) {
            let mut rng = ChaChaRng::from_seed(seed);
            let p = generate(20, 100, &mut rng);
            assert_eq!(p[0], 100);
            assert_ne!(p[20], 0);
        }
    }

    #[test]
    fn test_y_intercept() {
        assert_eq!(y_intercept(vec![(1, 1), (2, 2), (3, 3)]), 0);
        assert_eq!(y_intercept(vec![(1, 80), (2, 90), (3, 20)]), 30);
        assert_eq!(y_intercept(vec![(1, 43), (2, 22), (3, 86)]), 107);
    }
}
<commit_msg>No need for GF256 arithmetic to be exported.<commit_after>//! Implements basic arithmetic and polynomial operations in GF(2^8).

use rand::{CryptoRng, Rng};

/// Multiply two elements of GF(2^8).
fn mul(lhs: u8, rhs: u8) -> u8 {
    // This algorithm is constant-time, allowing us to perform GF256 arithmetic over secret values
    // without leaking information about the values via timing.
    let mut aa = lhs;
    let mut bb = rhs;
    let mut r = 0;
    // Loop over all 8 bits, regardless of whether or not it's required. aa != 0 is the usual loop
    // condition, but here it's folded into the per-round bitmask.
    for _ in 0..8 {
        // Perform r ^= bb iff aa & 1 == 0 && aa != 0.
        let loop_live = bool_to_mask(aa != 0);
        r ^= bb & bool_to_mask(aa & 1 != 0) & loop_live;
        let t = bb & 0x80;
        bb <<= 1;
        // Perform bb ^= 0x1b iff t != 0 && aa != 0.
        bb ^= 0x1b & bool_to_mask(t != 0) & loop_live;
        aa >>= 1;
    }
    r
}

/// Divide one element of GF(2^8) by another.
fn div(lhs: u8, rhs: u8) -> u8 {
    if rhs == 0 {
        panic!("Divide by zero: {} / {}", lhs, rhs)
    }

    // Again, this algorithm is constant-time. First, we find the multiplicative inverse of `a` by
    // iterating over all possible values, and using a bitmask to accumulate only that value which,
    // when multiplied by `a`, is `1`.
    let mut inv = 0;
    for i in 0x00..=0xff {
        inv += i & bool_to_mask(mul(i, rhs) == 1);
    }

    // Finally, we multiply `e` by the multiplicative inverse of `a`.
    mul(inv, lhs)
}

// If b is true, return 0xff, otherwise, return 0x00. Constant-time implementation.
#[inline(always)]
fn bool_to_mask(b: bool) -> u8 {
    (b as u8) * 0xff
}

/// Evaluate a polynomial, returning the Y value for the given X value.
pub fn eval(p: &[u8], x: u8) -> u8 {
    p.iter().rev().fold(0, |res, &v| mul(res, x) ^ v)
}

/// Generates a random polynomial of the Nth degree with a Y-intercept with the
/// given value.
pub fn generate<R>(n: usize, y: u8, rng: &mut R) -> Vec<u8>
where
    R: Rng + CryptoRng,
{
    // Allocate a vec of n+1 bytes.
    let mut p = vec![0; n + 1];

    // Set its Y-intercept to the given value.
    p[0] = y;

    // Generate random coefficients.
    rng.fill_bytes(&mut p[1..n]);

    // Ensure the Nth coefficient is non-zero, otherwise it's an (N-1)th-degree
    // polynomial.
    p[n] = rng.gen_range(1, 255);

    p
}

/// Interpolates a vector of (X, Y) points, returning the Y value at zero.
pub fn y_intercept(points: Vec<(u8, u8)>) -> u8 {
    let mut value = 0;
    for (i, &(ax, ay)) in points.iter().enumerate() {
        let mut weight = 1;
        for (j, &(bx, _)) in points.iter().enumerate() {
            if i != j {
                weight = mul(weight, div(bx, ax ^ bx));
            }
        }
        value ^= mul(weight, ay)
    }
    value
}

#[cfg(test)]
mod test {
    extern crate proptest;
    extern crate rand_chacha;

    use super::*;
    use rand::SeedableRng;

    use self::proptest::prelude::*;
    use self::rand_chacha::ChaChaRng;

    proptest! {
        #[test]
        fn test_div_is_inverse_of_mul(a in 0u8..=255, b in 1u8..=255) {
            assert_eq!(mul(div(a, b), b), a);
        }

        #[test]
        fn test_mul_is_inverse_of_div(a in 0u8..=255, b in 1u8..=255) {
            assert_eq!(div(mul(a, b), b), a);
        }

        #[test]
        fn test_mul_is_commutative(a in 0u8..=255, b in 0u8..=255) {
            assert_eq!(mul(a, b), mul(b, a));
        }
    }

    #[test]
    fn test_mul() {
        assert_eq!(mul(90, 21), 254);
        assert_eq!(mul(133, 5), 167);
        assert_eq!(mul(0, 21), 0);
    }

    #[test]
    fn test_div() {
        assert_eq!(div(90, 21), 189);
        assert_eq!(div(6, 55), 151);
        assert_eq!(div(22, 192), 138);
        assert_eq!(div(0, 21), 0);
    }

    #[test]
    fn test_eval() {
        assert_eq!(eval(&vec![1, 0, 2, 3], 2), 17);
    }

    proptest! {
        #[test]
        fn test_generate(seed: [u8; 32]) {
            let mut rng = ChaChaRng::from_seed(seed);
            let p = generate(20, 100, &mut rng);
            assert_eq!(p[0], 100);
            assert_ne!(p[20], 0);
        }
    }

    #[test]
    fn test_y_intercept() {
        assert_eq!(y_intercept(vec![(1, 1), (2, 2), (3, 3)]), 0);
        assert_eq!(y_intercept(vec![(1, 80), (2, 90), (3, 20)]), 30);
        assert_eq!(y_intercept(vec![(1, 43), (2, 22), (3, 86)]), 107);
    }
}
<|endoftext|>


<commit_before>
use device;
use gfx;
use gfx::DeviceHelper;
use graphics::{
    BackEnd,
};

use Texture;

static BUFFER_SIZE: uint = 1024;

static VERTEX_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec4 color;
varying vec4 v_Color;
void main() {
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec4 color;
out vec4 v_Color;
void main() {
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
varying vec4 v_Color;
void main() {
    gl_FragColor = v_Color;
}
"
    GLSL_150: b"
#version 150 core
in vec4 v_Color;
out vec4 o_Color;
void main() {
    o_Color = v_Color;
}
"
};

static VERTEX_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec4 color;
attribute vec2 uv;
uniform sampler2D s_texture;
varying vec4 v_Color;
varying vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec4 color;
in vec2 uv;
uniform sampler2D s_texture;
out vec4 v_Color;
out vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
uniform sampler2D s_texture;
varying vec2 v_UV;
varying vec4 v_Color;
void main()
{
    gl_FragColor = texture(s_texture, v_UV) * v_Color;
}
"
    GLSL_150: b"
#version 150 core
out vec4 o_Color;
uniform sampler2D s_texture;
in vec2 v_UV;
in vec4 v_Color;
void main()
{
    o_Color = texture(s_texture, v_UV) * v_Color;
}
"
};

#[vertex_format]
struct Vertex {
    pos: [f32, ..2],
    color: [f32, ..4],
}

impl Vertex {
    fn new(pos: [f32, ..2], color: [f32, ..4]) -> Vertex {
        Vertex {
            pos: pos,
            color: color,
        }
    }
}

#[vertex_format]
struct VertexUV {
    pos: [f32, ..2],
    color: [f32, ..4],
    uv: [f32, ..2],
}

impl VertexUV {
    fn new(pos: [f32, ..2], color: [f32, ..4], uv: [f32, ..2]) -> VertexUV {
        VertexUV {
            pos: pos,
            color: color,
            uv: uv,
        }
    }
}

#[shader_param(BatchUV, OwnedBatchUV)]
struct ParamsUV {
    s_texture: gfx::shade::TextureParam,
}

/// The graphics back-end.
pub struct Gfx2d<C: gfx::CommandBuffer> {
    state: gfx::DrawState,
    program: device::Handle<u32,device::shade::ProgramInfo>,
    program_uv: device::Handle<u32,device::shade::ProgramInfo>,
    buffer: gfx::BufferHandle<Vertex>,
    buffer_uv: gfx::BufferHandle<VertexUV>,
    mesh: gfx::Mesh,
    mesh_uv: gfx::Mesh,
}

impl<C: gfx::CommandBuffer> Gfx2d<C> {
    /// Creates a new Gfx2d object.
    pub fn new<D: gfx::Device<C>>(device: &mut D) -> Gfx2d<C> {
        let buffer = device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic);
        let buffer_uv = device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic);
        Gfx2d {
            state: gfx::DrawState::new(),
            program: device.link_program(
                    VERTEX_SHADER.clone(),
                    FRAGMENT_SHADER.clone()
                ).unwrap(),
            program_uv: device.link_program(
                    VERTEX_SHADER_UV.clone(),
                    FRAGMENT_SHADER_UV.clone()
                ).unwrap(),
            buffer: buffer,
            buffer_uv: buffer_uv,
            mesh: gfx::Mesh::from_format(buffer, BUFFER_SIZE as u32),
            mesh_uv: gfx::Mesh::from_format(buffer, BUFFER_SIZE as u32),
        }
    }
}

/// Used for rendering 2D graphics.
pub struct RenderContext<'a, C: 'a + gfx::CommandBuffer> {
    renderer: &'a mut gfx::Renderer<C>,
    frame: &'a gfx::Frame,
    gfx2d: &'a mut Gfx2d<C>,
}

impl<'a, C: gfx::CommandBuffer> RenderContext<'a, C> {
    /// Creates a new object for rendering 2D graphics.
    pub fn new(renderer: &'a mut gfx::Renderer<C>,
               frame: &'a gfx::Frame,
               gfx2d: &'a mut Gfx2d<C>) -> RenderContext<'a, C> {
        RenderContext {
            renderer: renderer,
            frame: frame,
            gfx2d: gfx2d
        }
    }
}

impl<'a, C: gfx::CommandBuffer> BackEnd<Texture>
for RenderContext<'a, C> {
    fn supports_clear_rgba(&self) -> bool { true }

    fn clear_rgba(&mut self, r: f32, g: f32, b: f32, a: f32) {
        let &RenderContext {
            ref mut renderer,
            frame,
            ..
        } = self;
        renderer.clear(
                gfx::ClearData {
                    color: [r, g, b, a],
                    depth: 0.0,
                    stencil: 0,
                },
                gfx::Color,
                frame
            );
    }

    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32]
    ) {
        let &RenderContext {
            ref mut renderer,
            ref frame,
            gfx2d: &Gfx2d {
                ref mut buffer,
                ..
            }
        } = self;
        let mut vertex_data = Vec::new();
        let n = vertices.len() / 2;
        for i in range(0, n) {
            vertex_data.push(
                Vertex::new(
                    [vertices[2 * i], vertices[2 * i + 1]],
                    [
                        colors[4 * i],
                        colors[4 * i + 1],
                        colors[4 * i + 2],
                        colors[4 * i + 3]
                    ]
                )
            );
        }

        /*
        let n = vertex_data.len();
        renderer.update_buffer_vec(*buffer, vertex_data, 0);
        */
    }
}
<commit_msg>Red square is working<commit_after>
use device;
use gfx;
use gfx::DeviceHelper;
use graphics::{
    BackEnd,
};

use Texture;

static BUFFER_SIZE: uint = 1024;

static VERTEX_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec4 color;
varying vec4 v_Color;
void main() {
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec4 color;
out vec4 v_Color;
void main() {
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
varying vec4 v_Color;
void main() {
    gl_FragColor = v_Color;
}
"
    GLSL_150: b"
#version 150 core
in vec4 v_Color;
out vec4 o_Color;
void main() {
    o_Color = v_Color;
}
"
};

static VERTEX_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec4 color;
attribute vec2 uv;
uniform sampler2D s_texture;
varying vec4 v_Color;
varying vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec4 color;
in vec2 uv;
uniform sampler2D s_texture;
out vec4 v_Color;
out vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
uniform sampler2D s_texture;
varying vec2 v_UV;
varying vec4 v_Color;
void main()
{
    gl_FragColor = texture(s_texture, v_UV) * v_Color;
}
"
    GLSL_150: b"
#version 150 core
out vec4 o_Color;
uniform sampler2D s_texture;
in vec2 v_UV;
in vec4 v_Color;
void main()
{
    o_Color = texture(s_texture, v_UV) * v_Color;
}
"
};

#[vertex_format]
struct Vertex {
    pos: [f32, ..2],
    color: [f32, ..4],
}

impl Vertex {
    fn new(pos: [f32, ..2], color: [f32, ..4]) -> Vertex {
        Vertex {
            pos: pos,
            color: color,
        }
    }
}

#[vertex_format]
struct VertexUV {
    pos: [f32, ..2],
    color: [f32, ..4],
    uv: [f32, ..2],
}

impl VertexUV {
    fn new(pos: [f32, ..2], color: [f32, ..4], uv: [f32, ..2]) -> VertexUV {
        VertexUV {
            pos: pos,
            color: color,
            uv: uv,
        }
    }
}

#[shader_param(BatchUV, OwnedBatchUV)]
struct ParamsUV {
    s_texture: gfx::shade::TextureParam,
}

/// The graphics back-end.
pub struct Gfx2d<C: gfx::CommandBuffer> {
    state: gfx::DrawState,
    program_uv: device::Handle<u32,device::shade::ProgramInfo>,
    buffer: gfx::BufferHandle<Vertex>,
    buffer_uv: gfx::BufferHandle<VertexUV>,
    mesh_uv: gfx::Mesh,
    batch: gfx::batch::OwnedBatch<(), ()>,
}

impl<C: gfx::CommandBuffer> Gfx2d<C> {
    /// Creates a new Gfx2d object.
    pub fn new<D: gfx::Device<C>>(device: &mut D) -> Gfx2d<C> {
        let program = device.link_program(
                VERTEX_SHADER.clone(),
                FRAGMENT_SHADER.clone()
            ).unwrap();
        let program_uv = device.link_program(
                VERTEX_SHADER_UV.clone(),
                FRAGMENT_SHADER_UV.clone()
            ).unwrap();
        let buffer = device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic);
        let buffer_uv = device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic);
        let mesh = gfx::Mesh::from_format(buffer, BUFFER_SIZE as u32);
        let mesh_uv = gfx::Mesh::from_format(buffer, BUFFER_SIZE as u32);
        let batch = gfx::batch::OwnedBatch::new(mesh, program, ()).unwrap();
        Gfx2d {
            state: gfx::DrawState::new(),
            program_uv: program_uv,
            buffer: buffer,
            buffer_uv: buffer_uv,
            mesh_uv: mesh_uv,
            batch: batch,
        }
    }
}

/// Used for rendering 2D graphics.
pub struct RenderContext<'a, C: 'a + gfx::CommandBuffer> {
    renderer: &'a mut gfx::Renderer<C>,
    frame: &'a gfx::Frame,
    gfx2d: &'a mut Gfx2d<C>,
}

impl<'a, C: gfx::CommandBuffer> RenderContext<'a, C> {
    /// Creates a new object for rendering 2D graphics.
    pub fn new(renderer: &'a mut gfx::Renderer<C>,
               frame: &'a gfx::Frame,
               gfx2d: &'a mut Gfx2d<C>) -> RenderContext<'a, C> {
        RenderContext {
            renderer: renderer,
            frame: frame,
            gfx2d: gfx2d
        }
    }
}

impl<'a, C: gfx::CommandBuffer> BackEnd<Texture>
for RenderContext<'a, C> {
    fn supports_clear_rgba(&self) -> bool { true }

    fn clear_rgba(&mut self, r: f32, g: f32, b: f32, a: f32) {
        let &RenderContext {
            ref mut renderer,
            frame,
            ..
        } = self;
        renderer.clear(
                gfx::ClearData {
                    color: [r, g, b, a],
                    depth: 0.0,
                    stencil: 0,
                },
                gfx::Color,
                frame
            );
    }

    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32]
    ) {
        let &RenderContext {
            ref mut renderer,
            ref frame,
            gfx2d: &Gfx2d {
                ref mut buffer,
                ref mut batch,
                ..
            }
        } = self;
        let mut vertex_data = Vec::new();
        let n = vertices.len() / 2;
        for i in range(0, n) {
            vertex_data.push(
                Vertex::new(
                    [vertices[2 * i], vertices[2 * i + 1]],
                    [
                        colors[4 * i],
                        colors[4 * i + 1],
                        colors[4 * i + 2],
                        colors[4 * i + 3]
                    ]
                )
            );
        }

        let n = vertex_data.len();
        renderer.update_buffer_vec(*buffer, vertex_data, 0);
        batch.slice = gfx::VertexSlice(gfx::TriangleList, 0, n as u32);
        renderer.draw(&*batch, *frame);
    }
}
<|endoftext|>


<commit_before>
use device;
use gfx;
use gfx::DeviceHelper;
use graphics::{
    BackEnd,
};

use Texture;

static BUFFER_SIZE: uint = 1024;

static VERTEX_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec3 color;
varying vec4 v_Color;
void main() {
    v_Color = vec4(color, 1.0);
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec3 color;
out vec4 v_Color;
void main() {
    v_Color = vec4(color, 1.0);
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
varying vec4 v_Color;
void main() {
    gl_FragColor = v_Color;
}
"
    GLSL_150: b"
#version 150 core
in vec4 v_Color;
out vec4 o_Color;
void main() {
    o_Color = v_Color;
}
"
};

static VERTEX_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec3 color;
attribute vec2 uv;
uniform sampler2D s_texture;
varying vec4 v_Color;
varying vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = a_v4Position;
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec3 color;
in vec2 uv;
uniform sampler2D s_texture;
out vec4 v_Color;
out vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = a_v4Position;
}
"
};

static FRAGMENT_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
uniform sampler2D s_texture;
varying vec2 v_UV;
varying vec4 v_Color;
void main()
{
    gl_FragColor = texture(s_texture, v_UV) * v_Color;
}
"
    GLSL_150: b"
#version 150 core
out vec4 o_Color;
uniform sampler2D s_texture;
in vec2 v_UV;
in vec4 v_Color;
void main()
{
    o_Color = texture(s_texture, v_UV) * v_Color;
}
"
};

#[vertex_format]
struct Vertex {
    pos: [f32, ..2],
    color: [f32, ..4],
}

impl Vertex {
    fn new(pos: [f32, ..2], color: [f32, ..4]) -> Vertex {
        Vertex {
            pos: pos,
            color: color,
        }
    }
}

#[vertex_format]
struct VertexUV {
    pos: [f32, ..2],
    color: [f32, ..4],
    uv: [f32, ..2],
}

impl VertexUV {
    fn new(pos: [f32, ..2], color: [f32, ..4], uv: [f32, ..2]) -> VertexUV {
        VertexUV {
            pos: pos,
            color: color,
            uv: uv,
        }
    }
}

#[shader_param(ProgramUV)]
struct ParamsUV {
    s_texture: gfx::shade::TextureParam,
}

/// The graphics back-end.
pub struct Gfx2d {
    renderer: gfx::Renderer,
    state: gfx::DrawState,
    program: gfx::shade::EmptyProgram,
    program_uv: ProgramUV,
    vertex_data: Vec<Vertex>,
    vertex_data_uv: Vec<VertexUV>,
    buffer: gfx::BufferHandle<Vertex>,
    buffer_uv: gfx::BufferHandle<VertexUV>,
}

impl Gfx2d {
    /// Creates a new Gfx2d object.
    pub fn new<D: gfx::Device>(device: &mut D) -> Gfx2d {
        Gfx2d {
            state: gfx::DrawState::new(),
            program: device.link_program(
                    VERTEX_SHADER.clone(),
                    FRAGMENT_SHADER.clone()
                ).unwrap(),
            program_uv: device.link_program(
                    VERTEX_SHADER_UV.clone(),
                    FRAGMENT_SHADER_UV.clone()
                ).unwrap(),
            vertex_data: Vec::with_capacity(BUFFER_SIZE),
            vertex_data_uv: Vec::with_capacity(BUFFER_SIZE),
            renderer: device.create_renderer(),
            buffer: device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic),
            buffer_uv: device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic),
        }
    }

    /// Returns the command buffer to be submitted to device.
    pub fn as_buffer(&self) -> &device::GlCommandBuffer {
        self.renderer.as_buffer()
    }
}

impl BackEnd<Texture> for Gfx2d {
    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32]
    ) {
        self.vertex_data.clear();
        let n = vertices.len() / 2;
        for i in range(0, n) {
            self.vertex_data.push(
                Vertex::new(
                    [vertices[2 * i], vertices[2 * i + 1]],
                    [
                        colors[4 * i],
                        colors[4 * i + 1],
                        colors[4 * i + 2],
                        colors[4 * i + 3]
                    ]
                )
            );
        }

    }
}
<commit_msg>Added something<commit_after>
use device;
use gfx;
use gfx::DeviceHelper;
use graphics::{
    BackEnd,
};

use Texture;

static BUFFER_SIZE: uint = 1024;

static VERTEX_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec3 color;
varying vec4 v_Color;
void main() {
    v_Color = vec4(color, 1.0);
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec3 color;
out vec4 v_Color;
void main() {
    v_Color = vec4(color, 1.0);
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
varying vec4 v_Color;
void main() {
    gl_FragColor = v_Color;
}
"
    GLSL_150: b"
#version 150 core
in vec4 v_Color;
out vec4 o_Color;
void main() {
    o_Color = v_Color;
}
"
};

static VERTEX_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec3 color;
attribute vec2 uv;
uniform sampler2D s_texture;
varying vec4 v_Color;
varying vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = a_v4Position;
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec3 color;
in vec2 uv;
uniform sampler2D s_texture;
out vec4 v_Color;
out vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = a_v4Position;
}
"
};

static FRAGMENT_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
uniform sampler2D s_texture;
varying vec2 v_UV;
varying vec4 v_Color;
void main()
{
    gl_FragColor = texture(s_texture, v_UV) * v_Color;
}
"
    GLSL_150: b"
#version 150 core
out vec4 o_Color;
uniform sampler2D s_texture;
in vec2 v_UV;
in vec4 v_Color;
void main()
{
    o_Color = texture(s_texture, v_UV) * v_Color;
}
"
};

#[vertex_format]
struct Vertex {
    pos: [f32, ..2],
    color: [f32, ..4],
}

impl Vertex {
    fn new(pos: [f32, ..2], color: [f32, ..4]) -> Vertex {
        Vertex {
            pos: pos,
            color: color,
        }
    }
}

#[vertex_format]
struct VertexUV {
    pos: [f32, ..2],
    color: [f32, ..4],
    uv: [f32, ..2],
}

impl VertexUV {
    fn new(pos: [f32, ..2], color: [f32, ..4], uv: [f32, ..2]) -> VertexUV {
        VertexUV {
            pos: pos,
            color: color,
            uv: uv,
        }
    }
}

#[shader_param(ProgramUV)]
struct ParamsUV {
    s_texture: gfx::shade::TextureParam,
}

/// The graphics back-end.
pub struct Gfx2d {
    renderer: gfx::Renderer,
    state: gfx::DrawState,
    program: gfx::shade::EmptyProgram,
    program_uv: ProgramUV,
    vertex_data: Vec<Vertex>,
    vertex_data_uv: Vec<VertexUV>,
    buffer: gfx::BufferHandle<Vertex>,
    buffer_uv: gfx::BufferHandle<VertexUV>,
}

impl Gfx2d {
    /// Creates a new Gfx2d object.
    pub fn new<D: gfx::Device>(device: &mut D) -> Gfx2d {
        Gfx2d {
            state: gfx::DrawState::new(),
            program: device.link_program(
                    VERTEX_SHADER.clone(),
                    FRAGMENT_SHADER.clone()
                ).unwrap(),
            program_uv: device.link_program(
                    VERTEX_SHADER_UV.clone(),
                    FRAGMENT_SHADER_UV.clone()
                ).unwrap(),
            vertex_data: Vec::with_capacity(BUFFER_SIZE),
            vertex_data_uv: Vec::with_capacity(BUFFER_SIZE),
            renderer: device.create_renderer(),
            buffer: device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic),
            buffer_uv: device.create_buffer(BUFFER_SIZE, gfx::UsageDynamic),
        }
    }

    /// Returns the command buffer to be submitted to device.
    pub fn as_buffer(&self) -> &device::GlCommandBuffer {
        self.renderer.as_buffer()
    }
}

impl BackEnd<Texture> for Gfx2d {
    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { true }

    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        vertices: &[f32],
        colors: &[f32]
    ) {
        let &Gfx2d {
            ref mut vertex_data,
            ref mut renderer,
            ref mut buffer,
            ..
        } = self;
        vertex_data.clear();
        let n = vertices.len() / 2;
        for i in range(0, n) {
            vertex_data.push(
                Vertex::new(
                    [vertices[2 * i], vertices[2 * i + 1]],
                    [
                        colors[4 * i],
                        colors[4 * i + 1],
                        colors[4 * i + 2],
                        colors[4 * i + 3]
                    ]
                )
            );
        }
        renderer.update_buffer_vec(*buffer, vertex_data.clone(), 0);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! Interface between Consensus and Network layers.

use crate::counters;
use anyhow::anyhow;
use aptos_config::network_id::{NetworkId, PeerNetworkId};
use aptos_logger::prelude::*;
use aptos_types::{epoch_change::EpochChangeProof, PeerId};
use async_trait::async_trait;
use channel::{aptos_channel, message_queues::QueueStyle};
use consensus_types::{
    block_retrieval::{BlockRetrievalRequest, BlockRetrievalResponse},
    epoch_retrieval::EpochRetrievalRequest,
    experimental::{commit_decision::CommitDecision, commit_vote::CommitVote},
    proposal_msg::ProposalMsg,
    sync_info::SyncInfo,
    vote_msg::VoteMsg,
};
use network::{
    application::storage::PeerMetadataStorage,
    constants::NETWORK_CHANNEL_SIZE,
    error::NetworkError,
    peer_manager::{ConnectionRequestSender, PeerManagerRequestSender},
    protocols::{
        network::{
            AppConfig, ApplicationNetworkSender, NetworkEvents, NetworkSender, NewNetworkSender,
        },
        rpc::error::RpcError,
        wire::handshake::v1::ProtocolIdSet,
    },
    ProtocolId,
};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, sync::Arc, time::Duration};

/// Network type for consensus
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum ConsensusMsg {
    /// RPC to get a chain of block of the given length starting from the given block id.
    BlockRetrievalRequest(Box<BlockRetrievalRequest>),
    /// Carries the returned blocks and the retrieval status.
    BlockRetrievalResponse(Box<BlockRetrievalResponse>),
    /// Request to get a EpochChangeProof from current_epoch to target_epoch
    EpochRetrievalRequest(Box<EpochRetrievalRequest>),
    /// ProposalMsg contains the required information for the proposer election protocol to make
    /// its choice (typically depends on round and proposer info).
    ProposalMsg(Box<ProposalMsg>),
    /// This struct describes basic synchronization metadata.
    SyncInfo(Box<SyncInfo>),
    /// A vector of LedgerInfo with contiguous increasing epoch numbers to prove a sequence of
    /// epoch changes from the first LedgerInfo's epoch.
    EpochChangeProof(Box<EpochChangeProof>),
    /// VoteMsg is the struct that is ultimately sent by the voter in response for receiving a
    /// proposal.
    VoteMsg(Box<VoteMsg>),
    /// CommitProposal is the struct that is sent by the validator after execution to propose
    /// on the committed state hash root.
    CommitVoteMsg(Box<CommitVote>),
    /// CommitDecision is the struct that is sent by the validator after collecting no fewer
    /// than 2f + 1 signatures on the commit proposal. This part is not on the critical path, but
    /// it can save slow machines to quickly confirm the execution result.
    CommitDecisionMsg(Box<CommitDecision>),
}

/// The interface from Network to Consensus layer.
///
/// `ConsensusNetworkEvents` is a `Stream` of `PeerManagerNotification` where the
/// raw `Bytes` direct-send and rpc messages are deserialized into
/// `ConsensusMessage` types. `ConsensusNetworkEvents` is a thin wrapper around
/// an `channel::Receiver<PeerManagerNotification>`.
pub type ConsensusNetworkEvents = NetworkEvents<ConsensusMsg>;

/// The interface from Consensus to Networking layer.
///
/// This is a thin wrapper around a `NetworkSender<ConsensusMsg>`, so it is easy
/// to clone and send off to a separate task. For example, the rpc requests
/// return Futures that encapsulate the whole flow, from sending the request to
/// remote, to finally receiving the response and deserializing. It therefore
/// makes the most sense to make the rpc call on a separate async task, which
/// requires the `ConsensusNetworkSender` to be `Clone` and `Send`.
#[derive(Clone)]
pub struct ConsensusNetworkSender {
    network_sender: NetworkSender<ConsensusMsg>,
    peer_metadata_storage: Option<Arc<PeerMetadataStorage>>,
}

/// Supported protocols in preferred order (from highest priority to lowest).
pub const RPC: &[ProtocolId] = &[ProtocolId::ConsensusRpcBcs, ProtocolId::ConsensusRpcJson];
/// Supported protocols in preferred order (from highest priority to lowest).
pub const DIRECT_SEND: &[ProtocolId] = &[
    ProtocolId::ConsensusDirectSendBcs,
    ProtocolId::ConsensusDirectSendJson,
];

/// Configuration for the network endpoints to support consensus.
/// TODO: make this configurable
pub fn network_endpoint_config() -> AppConfig {
    let protos = RPC.iter().chain(DIRECT_SEND.iter()).copied();
    AppConfig::p2p(
        protos,
        aptos_channel::Config::new(NETWORK_CHANNEL_SIZE)
            .queue_style(QueueStyle::LIFO)
            .counters(&counters::PENDING_CONSENSUS_NETWORK_EVENTS),
    )
}

impl NewNetworkSender for ConsensusNetworkSender {
    /// Returns a Sender that only sends for the `CONSENSUS_DIRECT_SEND_PROTOCOL` and
    /// `CONSENSUS_RPC_PROTOCOL` ProtocolId.
    fn new(
        peer_mgr_reqs_tx: PeerManagerRequestSender,
        connection_reqs_tx: ConnectionRequestSender,
    ) -> Self {
        Self {
            network_sender: NetworkSender::new(peer_mgr_reqs_tx, connection_reqs_tx),
            peer_metadata_storage: None,
        }
    }
}

impl ConsensusNetworkSender {
    /// Initialize a shared hashmap about connections metadata that is updated by the receiver.
    pub fn initialize(&mut self, peer_metadata_storage: Arc<PeerMetadataStorage>) {
        self.peer_metadata_storage = Some(peer_metadata_storage);
    }

    /// Query the supported protocols from this peer's connection.
    fn supported_protocols(&self, peer: PeerId) -> anyhow::Result<ProtocolIdSet> {
        if let Some(peer_metadata_storage) = &self.peer_metadata_storage {
            let peer_network_id = PeerNetworkId::new(NetworkId::Validator, peer);
            peer_metadata_storage
                .read(peer_network_id)
                .map(|peer_info| peer_info.active_connection.application_protocols)
                .ok_or_else(|| anyhow!("Peer not connected"))
        } else {
            Err(anyhow!("ConsensusNetworkSender not initialized"))
        }
    }

    /// Choose the overlapping protocol for peer. The local protocols are sorted from most to least preferred.
    fn preferred_protocol_for_peer(
        &self,
        peer: PeerId,
        local_protocols: &[ProtocolId],
    ) -> anyhow::Result<ProtocolId> {
        let remote_protocols = self.supported_protocols(peer)?;
        for protocol in local_protocols {
            if remote_protocols.contains(*protocol) {
                return Ok(*protocol);
            }
        }
        Err(anyhow!("No available protocols for peer {}", peer))
    }
}

#[async_trait]
impl ApplicationNetworkSender<ConsensusMsg> for ConsensusNetworkSender {
    /// Send a single message to the destination peer using available ProtocolId.
    fn send_to(&self, recipient: PeerId, message: ConsensusMsg) -> Result<(), NetworkError> {
        let protocol = self.preferred_protocol_for_peer(recipient, DIRECT_SEND)?;
        self.network_sender.send_to(recipient, protocol, message)
    }

    /// Send a single message to the destination peers using available ProtocolId.
    fn send_to_many(
        &self,
        recipients: impl Iterator<Item = PeerId>,
        message: ConsensusMsg,
    ) -> Result<(), NetworkError> {
        let mut peers_per_protocol = HashMap::new();
        for peer in recipients {
            match self.preferred_protocol_for_peer(peer, DIRECT_SEND) {
                Ok(protocol) => peers_per_protocol
                    .entry(protocol)
                    .or_insert_with(Vec::new)
                    .push(peer),
                Err(e) => error!("{}", e),
            }
        }
        for (protocol, peers) in peers_per_protocol {
            self.network_sender
                .send_to_many(peers.into_iter(), protocol, message.clone())?;
        }
        Ok(())
    }

    /// Send a RPC to the destination peer using the `CONSENSUS_RPC_PROTOCOL` ProtocolId.
    async fn send_rpc(
        &self,
        recipient: PeerId,
        message: ConsensusMsg,
        timeout: Duration,
    ) -> Result<ConsensusMsg, RpcError> {
        let protocol = self.preferred_protocol_for_peer(recipient, RPC)?;
        self.network_sender
            .send_rpc(recipient, protocol, message, timeout)
            .await
    }
}
<commit_msg>[consensus] sample disconnected log<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! Interface between Consensus and Network layers.

use crate::counters;
use anyhow::anyhow;
use aptos_config::network_id::{NetworkId, PeerNetworkId};
use aptos_logger::prelude::*;
use aptos_types::{epoch_change::EpochChangeProof, PeerId};
use async_trait::async_trait;
use channel::{aptos_channel, message_queues::QueueStyle};
use consensus_types::{
    block_retrieval::{BlockRetrievalRequest, BlockRetrievalResponse},
    epoch_retrieval::EpochRetrievalRequest,
    experimental::{commit_decision::CommitDecision, commit_vote::CommitVote},
    proposal_msg::ProposalMsg,
    sync_info::SyncInfo,
    vote_msg::VoteMsg,
};
use network::{
    application::storage::PeerMetadataStorage,
    constants::NETWORK_CHANNEL_SIZE,
    error::NetworkError,
    peer_manager::{ConnectionRequestSender, PeerManagerRequestSender},
    protocols::{
        network::{
            AppConfig, ApplicationNetworkSender, NetworkEvents, NetworkSender, NewNetworkSender,
        },
        rpc::error::RpcError,
        wire::handshake::v1::ProtocolIdSet,
    },
    ProtocolId,
};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, sync::Arc, time::Duration};

/// Network type for consensus
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum ConsensusMsg {
    /// RPC to get a chain of block of the given length starting from the given block id.
    BlockRetrievalRequest(Box<BlockRetrievalRequest>),
    /// Carries the returned blocks and the retrieval status.
    BlockRetrievalResponse(Box<BlockRetrievalResponse>),
    /// Request to get a EpochChangeProof from current_epoch to target_epoch
    EpochRetrievalRequest(Box<EpochRetrievalRequest>),
    /// ProposalMsg contains the required information for the proposer election protocol to make
    /// its choice (typically depends on round and proposer info).
    ProposalMsg(Box<ProposalMsg>),
    /// This struct describes basic synchronization metadata.
    SyncInfo(Box<SyncInfo>),
    /// A vector of LedgerInfo with contiguous increasing epoch numbers to prove a sequence of
    /// epoch changes from the first LedgerInfo's epoch.
    EpochChangeProof(Box<EpochChangeProof>),
    /// VoteMsg is the struct that is ultimately sent by the voter in response for receiving a
    /// proposal.
    VoteMsg(Box<VoteMsg>),
    /// CommitProposal is the struct that is sent by the validator after execution to propose
    /// on the committed state hash root.
    CommitVoteMsg(Box<CommitVote>),
    /// CommitDecision is the struct that is sent by the validator after collecting no fewer
    /// than 2f + 1 signatures on the commit proposal. This part is not on the critical path, but
    /// it can save slow machines to quickly confirm the execution result.
    CommitDecisionMsg(Box<CommitDecision>),
}

/// The interface from Network to Consensus layer.
///
/// `ConsensusNetworkEvents` is a `Stream` of `PeerManagerNotification` where the
/// raw `Bytes` direct-send and rpc messages are deserialized into
/// `ConsensusMessage` types. `ConsensusNetworkEvents` is a thin wrapper around
/// an `channel::Receiver<PeerManagerNotification>`.
pub type ConsensusNetworkEvents = NetworkEvents<ConsensusMsg>;

/// The interface from Consensus to Networking layer.
///
/// This is a thin wrapper around a `NetworkSender<ConsensusMsg>`, so it is easy
/// to clone and send off to a separate task. For example, the rpc requests
/// return Futures that encapsulate the whole flow, from sending the request to
/// remote, to finally receiving the response and deserializing. It therefore
/// makes the most sense to make the rpc call on a separate async task, which
/// requires the `ConsensusNetworkSender` to be `Clone` and `Send`.
#[derive(Clone)]
pub struct ConsensusNetworkSender {
    network_sender: NetworkSender<ConsensusMsg>,
    peer_metadata_storage: Option<Arc<PeerMetadataStorage>>,
}

/// Supported protocols in preferred order (from highest priority to lowest).
pub const RPC: &[ProtocolId] = &[ProtocolId::ConsensusRpcBcs, ProtocolId::ConsensusRpcJson];
/// Supported protocols in preferred order (from highest priority to lowest).
pub const DIRECT_SEND: &[ProtocolId] = &[
    ProtocolId::ConsensusDirectSendBcs,
    ProtocolId::ConsensusDirectSendJson,
];

/// Configuration for the network endpoints to support consensus.
/// TODO: make this configurable
pub fn network_endpoint_config() -> AppConfig {
    let protos = RPC.iter().chain(DIRECT_SEND.iter()).copied();
    AppConfig::p2p(
        protos,
        aptos_channel::Config::new(NETWORK_CHANNEL_SIZE)
            .queue_style(QueueStyle::LIFO)
            .counters(&counters::PENDING_CONSENSUS_NETWORK_EVENTS),
    )
}

impl NewNetworkSender for ConsensusNetworkSender {
    /// Returns a Sender that only sends for the `CONSENSUS_DIRECT_SEND_PROTOCOL` and
    /// `CONSENSUS_RPC_PROTOCOL` ProtocolId.
    fn new(
        peer_mgr_reqs_tx: PeerManagerRequestSender,
        connection_reqs_tx: ConnectionRequestSender,
    ) -> Self {
        Self {
            network_sender: NetworkSender::new(peer_mgr_reqs_tx, connection_reqs_tx),
            peer_metadata_storage: None,
        }
    }
}

impl ConsensusNetworkSender {
    /// Initialize a shared hashmap about connections metadata that is updated by the receiver.
    pub fn initialize(&mut self, peer_metadata_storage: Arc<PeerMetadataStorage>) {
        self.peer_metadata_storage = Some(peer_metadata_storage);
    }

    /// Query the supported protocols from this peer's connection.
    fn supported_protocols(&self, peer: PeerId) -> anyhow::Result<ProtocolIdSet> {
        if let Some(peer_metadata_storage) = &self.peer_metadata_storage {
            let peer_network_id = PeerNetworkId::new(NetworkId::Validator, peer);
            peer_metadata_storage
                .read(peer_network_id)
                .map(|peer_info| peer_info.active_connection.application_protocols)
                .ok_or_else(|| anyhow!("Peer not connected"))
        } else {
            Err(anyhow!("ConsensusNetworkSender not initialized"))
        }
    }

    /// Choose the overlapping protocol for peer. The local protocols are sorted from most to least preferred.
    fn preferred_protocol_for_peer(
        &self,
        peer: PeerId,
        local_protocols: &[ProtocolId],
    ) -> anyhow::Result<ProtocolId> {
        let remote_protocols = self.supported_protocols(peer)?;
        for protocol in local_protocols {
            if remote_protocols.contains(*protocol) {
                return Ok(*protocol);
            }
        }
        Err(anyhow!("No available protocols for peer {}", peer))
    }
}

#[async_trait]
impl ApplicationNetworkSender<ConsensusMsg> for ConsensusNetworkSender {
    /// Send a single message to the destination peer using available ProtocolId.
    fn send_to(&self, recipient: PeerId, message: ConsensusMsg) -> Result<(), NetworkError> {
        let protocol = self.preferred_protocol_for_peer(recipient, DIRECT_SEND)?;
        self.network_sender.send_to(recipient, protocol, message)
    }

    /// Send a single message to the destination peers using available ProtocolId.
    fn send_to_many(
        &self,
        recipients: impl Iterator<Item = PeerId>,
        message: ConsensusMsg,
    ) -> Result<(), NetworkError> {
        let mut peers_per_protocol = HashMap::new();
        let mut not_available = vec![];
        for peer in recipients {
            match self.preferred_protocol_for_peer(peer, DIRECT_SEND) {
                Ok(protocol) => peers_per_protocol
                    .entry(protocol)
                    .or_insert_with(Vec::new)
                    .push(peer),
                Err(_) => not_available.push(peer),
            }
        }
        sample!(
            SampleRate::Duration(Duration::from_secs(10)),
            error!("Unavailable peers: {:?}", not_available)
        );
        for (protocol, peers) in peers_per_protocol {
            self.network_sender
                .send_to_many(peers.into_iter(), protocol, message.clone())?;
        }
        Ok(())
    }

    /// Send a RPC to the destination peer using the `CONSENSUS_RPC_PROTOCOL` ProtocolId.
    async fn send_rpc(
        &self,
        recipient: PeerId,
        message: ConsensusMsg,
        timeout: Duration,
    ) -> Result<ConsensusMsg, RpcError> {
        let protocol = self.preferred_protocol_for_peer(recipient, RPC)?;
        self.network_sender
            .send_rpc(recipient, protocol, message, timeout)
            .await
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

fn read_file(file_name : &str) -> String {
    let path = Path::new(file_name);
    let display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!("couldn't open {}: {}", display,
            Error::description(&why)),
        Ok(file) => file,
    };

    // Read the file contents into a string, returns `io::Result<usize>`
    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("couldn't read {}: {}", display,
            Error::description(&why)),
        Ok(_) => s,
    }
}

fn parse_table(table : &str) -> Vec<(i32, i32, i32)> {
    let table_lines = table.lines_any();
    let mut parsed_table = Vec::new();

    // Skip table header, then ignore any lines that have issues with parsing
    for line in table_lines.skip(2) {
        let mut words = line.split_whitespace();
        let day = match words.next() {
            Some(num) => match num.parse::<i32>() {
                Ok(num) => num,
                Err(_) => continue,
            },
            None => continue
        };
        let max_temp = match words.next() {
            Some(num) => match num.trim_matches('*').parse::<i32>() {
                Ok(num) => num,
                Err(_) => continue,
            },
            None => continue
        };
        let min_temp = match words.next() {
            Some(num) => match num.trim_matches('*').parse::<i32>() {
                Ok(num) => num,
                Err(_) => continue,
            },
            None => continue
        };
        parsed_table.push((day, max_temp, min_temp));
    }
    parsed_table
}

fn main() {
    let table_string = read_file("weather.dat");
    parse_table(&table_string);
}
<commit_msg>Kata04: Complete first part of kata<commit_after>use std::error::Error;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

fn read_file(file_name : &str) -> String {
    let path = Path::new(file_name);
    let display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!("couldn't open {}: {}", display,
            Error::description(&why)),
        Ok(file) => file,
    };

    // Read the file contents into a string, returns `io::Result<usize>`
    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("couldn't read {}: {}", display,
            Error::description(&why)),
        Ok(_) => s,
    }
}

fn parse_table(table : &str) -> Vec<(i32, i32, i32)> {
    let table_lines = table.lines_any();
    let mut parsed_table = Vec::new();

    // Skip table header, then ignore any lines that have issues with parsing
    for line in table_lines.skip(2) {
        let mut words = line.split_whitespace();
        let day = match words.next() {
            Some(num) => match num.parse::<i32>() {
                Ok(num) => num,
                Err(_) => continue,
            },
            None => continue
        };
        let max_temp = match words.next() {
            Some(num) => match num.trim_matches('*').parse::<i32>() {
                Ok(num) => num,
                Err(_) => continue,
            },
            None => continue
        };
        let min_temp = match words.next() {
            Some(num) => match num.trim_matches('*').parse::<i32>() {
                Ok(num) => num,
                Err(_) => continue,
            },
            None => continue
        };
        parsed_table.push((day, max_temp, min_temp));
    }
    parsed_table
}

fn main() {
    let table_string = read_file("weather.dat");
    let mut parsed_table = parse_table(&table_string);
    // Sort vector by spread -- smallest to greatest
    parsed_table.sort_by(|&(_, a_max, a_min), &(_, b_max, b_min)| (a_max - a_min).cmp(&(b_max - b_min)));
    // Print day with smallest spread
    print!("{}", parsed_table[0].0);
}
<|endoftext|>


<commit_before>
<commit_msg>Add files via upload<commit_after>extern crate rppal;

use std::env;
use std::ffi::OsString;
use rppal::gpio::{GPIO,Mode,Level};

const LAST_PIN_NUMBER: u8 = 27;
const HELP_CMD_STR: &'static str = "help";
const SET_CMD_STR: &'static str = "set";
const GET_CMD_STR: &'static str = "get";
const HIGH_PIN_STATE_STR: &'static str = "high";
const LOW_PIN_STATE_STR: &'static str = "low";
const ALL_PINS_STR: &'static str = "all";
const HELP_EXAMPLE_STR: &'static str = "sudo pi3gpio help";

fn main() {
	handle_cmd ( env::args_os() );
}

fn handle_cmd (mut cmd: env::ArgsOs) {
	match cmd.nth(1) {
		Some (action) => {
			if action == OsString::from(HELP_CMD_STR) {
				print_help_text ();
			}
			else if action == OsString::from(SET_CMD_STR) {
				set_pins (cmd);
			}
			else if action == OsString::from(GET_CMD_STR) {
				read_pins (cmd);
			}
			else {
				panic! ("Unknown command {:?}! \nFor help run \"{}\"", action, HELP_EXAMPLE_STR );
			}
		},
		None => panic! ("No command found! \nFor help run \"{}\"", HELP_EXAMPLE_STR ),
	}
}

fn print_help_text () {
	println! ("SYNTAX: sudo pi3gpio command [state] [pins]");
	println! ("	command: ");
	println! ("		{}	prints the help text", HELP_CMD_STR );
	println! ("		{}	sets the value of the indicated pins to the indicated value", SET_CMD_STR );
	println! ("		{}	prints the state of the indicated pins", GET_CMD_STR );
	println! ("	state: ");
	println! ("		{}	logical 1 for the indicated pins, equivalent voltage 3.3[V]", HIGH_PIN_STATE_STR );
	println! ("		{}	logical 0 for the indicated pins, equivalent voltage 0[V]", LOW_PIN_STATE_STR );
	println! ("	pins: ");
	println! ("		{}	BCM pins between 0 and {}", ALL_PINS_STR, LAST_PIN_NUMBER );
	println! ("Examples:");
	println! ("	sudo pi3gpio help ");
	println! ("	sudo pi3gpio get all");
	println! ("	sudo pi3gpio get 4");
	println! ("	sudo pi3gpio get 10 11");
	println! ("	sudo pi3gpio set low all");
	println! ("	sudo pi3gpio set high 12");
	println! ("	sudo pi3gpio set low 2 5 7");
}

trait ReadState{
	fn read_state (self, gpio: &mut GPIO);
}

impl ReadState for OsString {
	fn read_state (self, gpio: &mut GPIO) {
		match self.to_u8() {
			Ok (pin) => read_pin ( gpio, pin ),
			Err (e) => {
				panic! ("{} \nFor help run \"{}\"", e,  HELP_EXAMPLE_STR );
			},
		}
	}
}

fn read_all_pins ( gpio: &mut GPIO ) {
	for pin in 0..(LAST_PIN_NUMBER+1) {
		read_pin ( gpio, pin );
	}
}

fn read_pin ( gpio: &mut GPIO, pin: u8) {
	gpio.set_mode( pin, Mode::Input );
	match gpio.read(pin) {
		Ok(state) =>	println! ("Pin {} = {:?}", pin, state ),
		Err (_) => println! ("Could not read state of pin {}",pin),
	}
}

fn read_pins (mut cmd: env::ArgsOs) {
	let mut gpio = initiate_gpio_handle();

	match cmd.nth(0) {
		Some (pin_as_os_string) => {
			if pin_as_os_string == OsString::from(ALL_PINS_STR) {
				read_all_pins ( &mut gpio );
				return;
			}
			else {
				pin_as_os_string.read_state ( &mut gpio );
			}
		}
		None => panic! ("Pin not found! \nFor help run \"{}\"",  HELP_EXAMPLE_STR ),
	}

	for argument in cmd {
		argument.read_state ( &mut gpio );
	}

}

trait ToU8 {
	fn to_u8 (self) -> Result<u8, &'static str >;
}

impl ToU8 for OsString {
	fn to_u8 (self) -> Result<u8, &'static str> {
		match self.into_string() {
			Ok(x) => match x.parse::<u8>() {
				Ok (y) => return Ok (y),
				Err(_) => return Err("String indicating pin number could not be converted to u8!" ),
			},
			Err(_) => return Err("OsString indicating pin number could not be converted to String!" ),
		}
	}
}

fn initiate_gpio_handle () -> GPIO {
    let gpio: GPIO;
    match GPIO::new(){
	    Ok (x) => gpio = x,
	    Err (e) => panic! ("Could not access GPIO memory! {}",e),
    }

    gpio
}

fn get_pin_state ( argument: Option<OsString>  ) -> Level {
	let mut pin_state = Level::Low;
	match argument {
		Some (state) => {
			if state == OsString::from(HIGH_PIN_STATE_STR) {
				pin_state = Level::High;
			}
			else if state != OsString::from(LOW_PIN_STATE_STR) {
				panic! ("State {:?} is invalid! \nFor help run \"{}\"", state, HELP_EXAMPLE_STR );
			}
		},
		None => panic! ("State not found! \nFor help run \"{}\"",  HELP_EXAMPLE_STR ),
	}

    pin_state
}

trait SetState{
	fn set_state (self, pin_state: Level ,gpio: &mut GPIO);
}

impl SetState for OsString {
	fn set_state (self, pin_state: Level, gpio: &mut GPIO) {
		match self.to_u8() {
			Ok (pin) => set_pin ( gpio, pin, pin_state ),
			Err (e) => {
				panic! ("{} \nFor help run \"{}\"", e,  HELP_EXAMPLE_STR );
			},
		}
	}
}

fn set_all_pins ( gpio: &mut GPIO, pin_state: Level ) {
	for pin in 0..(LAST_PIN_NUMBER+1) {
		set_pin ( gpio, pin, pin_state );
	}
}

fn set_pin ( gpio: &mut GPIO, pin: u8, pin_state: Level ) {
	println! ("Set pin {} to {:?}", pin, pin_state);
	gpio.set_mode( pin, Mode::Output );
	gpio.write ( pin, pin_state );
}

fn set_pins (mut cmd: env::ArgsOs) {
	let mut gpio = initiate_gpio_handle();
	gpio.set_clear_on_drop ( false );

	let pin_state = get_pin_state( cmd.nth(0) );

	match cmd.nth(0) {
		Some (pin_as_os_string) => {
			if pin_as_os_string == OsString::from(ALL_PINS_STR) {
				set_all_pins ( &mut gpio, pin_state );
				return;
			}
			else {
				pin_as_os_string.set_state( pin_state, &mut gpio );
			}

		}
		None => panic! ("Pin not found! \nFor help run \"{}\"",  HELP_EXAMPLE_STR ),
	}

	for argument in cmd {
		argument.set_state( pin_state, &mut gpio );
	}
}
<|endoftext|>


<commit_before>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

use std::borrow::Cow;
use std::ffi::CStr;
use libc::{c_char, c_int};
use iup_sys::*;
use smallvec::SmallVec;
use super::Control;

pub fn str_to_c_vec<'a: 'b, 'b, A: ::smallvec::Array<Item=u8>>(s: &'a str, buf: &'b mut SmallVec<A>) -> *const c_char {
    // `CString` in the std library doesn't check if the &str already ends in a null terminator
    // It allocates and pushes a 0 unconditionally. However, I can add the null to string literals
    // and avoid many allocations.
    if s.as_bytes().last() == Some(&0) && !s.as_bytes()[..s.len() - 1].contains(&b'\0') {
        s.as_bytes().as_ptr() as *const c_char
    } else {
        buf.grow(s.len() + 1);
        buf.extend(s.as_bytes().iter().map(|c| if *c == b'\0' { b'?' } else { *c }));
        buf.push(0);
        (&buf[..]).as_ptr() as *const c_char
    }
}

pub fn set_str_attribute(handle: *mut Ihandle, name: &str, value: &str) {
    unsafe {
        let mut name_buf = SmallVec::<[u8; 32]>::new();
        let c_name = str_to_c_vec(name, &mut name_buf);
        let mut value_buf = SmallVec::<[u8; 32]>::new(); // TODO: change to 64 after upgrading smallvec
        let c_value = str_to_c_vec(value, &mut value_buf);
        //println!("setting {:?} to {:?}", CStr::from_ptr(c_name).to_string_lossy(), CStr::from_ptr(c_value).to_string_lossy());
        IupSetStrAttribute(handle, c_name, c_value);
    }
}

pub fn get_attribute_ptr(handle: *mut Ihandle, name: &str) -> *mut c_char {
    unsafe {
        let mut name_buf = SmallVec::<[u8; 32]>::new();
        let c_name = str_to_c_vec(name, &mut name_buf);
        IupGetAttribute(handle as *mut Ihandle, c_name)
    }
}

// Unfortunately, the return value has to be copied because its lifetime isn't guaranteed.
// IUP's docs state:
//     "The returned pointer can be used safely even if IupGetGlobal or IupGetAttribute are called
//     several times. But not too many times, because it is an internal buffer and after IUP may
//     reuse it after around 50 calls."
pub fn get_str_attribute(handle: *mut Ihandle, name: &str) -> String {
    unsafe {
        get_str_attribute_slice(handle, name).into_owned()
    }
}

// This function isn't very error prone (see above), but isn't completely safe either.
pub unsafe fn get_str_attribute_slice(handle: *mut Ihandle, name: &str) -> Cow<str> {
    let value = get_attribute_ptr(handle, name);
    //println!("getting {:?}: {:?}", name, CStr::from_ptr(value).to_string_lossy());
    CStr::from_ptr(value).to_string_lossy()
}

pub fn get_int_int_attribute(handle: *mut Ihandle, name: &str) -> (i32, i32) {
    unsafe {
        let mut name_buf = SmallVec::<[u8; 32]>::new();
        let c_name = str_to_c_vec(name, &mut name_buf);
        let mut x: i32 = 0;
        let mut y: i32 = 0;
        assert!(IupGetIntInt(handle as *mut Ihandle,
                             c_name,
                             &mut x as *mut c_int,
                             &mut y as *mut c_int) == 2);
        (x, y)
    }
}

pub trait CommonAttributes : Control {
    fn active(&self) -> bool {
        get_str_attribute(self.handle(), "ACTIVE") == "YES"
    }

    fn set_active(&self, active: bool) {
        set_str_attribute(self.handle(), "ACTIVE", if active { "YES" } else { "NO" });
    }

    fn tip(&self) -> String {
        get_str_attribute(self.handle(), "TIP")
    }
    unsafe fn tip_slice(&self) -> Cow<str> {
        get_str_attribute_slice(self.handle(), "TIP")
    }

    fn set_tip(&self, tip: &str) {
        set_str_attribute(self.handle(), "TIP", tip);
    }

    fn min_size(&self) -> (i32, i32) {
        get_int_int_attribute(self.handle(), "MINSIZE")
    }

    fn set_min_size(&self, x: i32, y: i32) {
        let s = format!("{}x{}", x, y);
        set_str_attribute(self.handle(), "MINSIZE", &s);
    }

    fn max_size(&self) -> (i32, i32) {
        get_int_int_attribute(self.handle(), "MAXSIZE")
    }

    fn set_max_size(&self, x: i32, y: i32) {
        let s = format!("{}x{}", x, y);
        set_str_attribute(self.handle(), "MAXSIZE", &s);
    }

    fn show(&self) -> Result<(), ()> {
        unsafe {
            if IupShow(self.handle()) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    fn hide(&self) -> Result<(), ()> {
        unsafe {
            if IupHide(self.handle()) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    fn set_visible(&self, visible: bool) -> Result<(), ()> {
        if visible { self.show() } else { self.hide() }
    }
}

pub trait TitleAttribute : Control {
    fn title(&self) -> String {
        get_str_attribute(self.handle(), "TITLE")
    }

    fn set_title(&self, title: &str) {
        set_str_attribute(self.handle(), "TITLE", title);
    }
}

pub trait OrientationAttribute : Control {
    fn orientation(&self) -> ::Orientation {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ORIENTATION");
            ::Orientation::from_str(s.as_bytes())
        }
    }

    fn set_orientation(&self, orientation: ::Orientation) {
        set_str_attribute(self.handle(), "ORIENTATION", orientation.to_str());
    }
}
<commit_msg>Change get_str_attribute_slice to return "" when value is null<commit_after>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

use std::borrow::Cow;
use std::ffi::CStr;
use libc::{c_char, c_int};
use iup_sys::*;
use smallvec::SmallVec;
use super::Control;

pub fn str_to_c_vec<'a: 'b, 'b, A: ::smallvec::Array<Item=u8>>(s: &'a str, buf: &'b mut SmallVec<A>) -> *const c_char {
    // `CString` in the std library doesn't check if the &str already ends in a null terminator
    // It allocates and pushes a 0 unconditionally. However, I can add the null to string literals
    // and avoid many allocations.
    if s.as_bytes().last() == Some(&0) && !s.as_bytes()[..s.len() - 1].contains(&b'\0') {
        s.as_bytes().as_ptr() as *const c_char
    } else {
        buf.grow(s.len() + 1);
        buf.extend(s.as_bytes().iter().map(|c| if *c == b'\0' { b'?' } else { *c }));
        buf.push(0);
        (&buf[..]).as_ptr() as *const c_char
    }
}

pub fn set_str_attribute(handle: *mut Ihandle, name: &str, value: &str) {
    unsafe {
        let mut name_buf = SmallVec::<[u8; 32]>::new();
        let c_name = str_to_c_vec(name, &mut name_buf);
        let mut value_buf = SmallVec::<[u8; 32]>::new(); // TODO: change to 64 after upgrading smallvec
        let c_value = str_to_c_vec(value, &mut value_buf);
        //println!("setting {:?} to {:?}", CStr::from_ptr(c_name).to_string_lossy(), CStr::from_ptr(c_value).to_string_lossy());
        IupSetStrAttribute(handle, c_name, c_value);
    }
}

pub fn get_attribute_ptr(handle: *mut Ihandle, name: &str) -> *mut c_char {
    unsafe {
        let mut name_buf = SmallVec::<[u8; 32]>::new();
        let c_name = str_to_c_vec(name, &mut name_buf);
        IupGetAttribute(handle as *mut Ihandle, c_name)
    }
}

// Unfortunately, the return value has to be copied because its lifetime isn't guaranteed.
// IUP's docs state:
//     "The returned pointer can be used safely even if IupGetGlobal or IupGetAttribute are called
//     several times. But not too many times, because it is an internal buffer and after IUP may
//     reuse it after around 50 calls."
pub fn get_str_attribute(handle: *mut Ihandle, name: &str) -> String {
    unsafe {
        get_str_attribute_slice(handle, name).into_owned()
    }
}

// This function isn't very error prone (see above), but isn't completely safe either.
pub unsafe fn get_str_attribute_slice(handle: *mut Ihandle, name: &str) -> Cow<str> {
    let value = get_attribute_ptr(handle, name);
    //println!("getting {:?}: {:?}", name, CStr::from_ptr(value).to_string_lossy());
    // It may be better to return `None` when `value` is null rather than an empty string,
    // but I'll try this for now.
    if value.is_null() {
        "".into()
    } else {
        CStr::from_ptr(value).to_string_lossy()
    }
}

pub fn get_int_int_attribute(handle: *mut Ihandle, name: &str) -> (i32, i32) {
    unsafe {
        let mut name_buf = SmallVec::<[u8; 32]>::new();
        let c_name = str_to_c_vec(name, &mut name_buf);
        let mut x: i32 = 0;
        let mut y: i32 = 0;
        assert!(IupGetIntInt(handle as *mut Ihandle,
                             c_name,
                             &mut x as *mut c_int,
                             &mut y as *mut c_int) == 2);
        (x, y)
    }
}

pub trait CommonAttributes : Control {
    fn active(&self) -> bool {
        get_str_attribute(self.handle(), "ACTIVE") == "YES"
    }

    fn set_active(&self, active: bool) {
        set_str_attribute(self.handle(), "ACTIVE", if active { "YES" } else { "NO" });
    }

    fn tip(&self) -> String {
        get_str_attribute(self.handle(), "TIP")
    }
    unsafe fn tip_slice(&self) -> Cow<str> {
        get_str_attribute_slice(self.handle(), "TIP")
    }

    fn set_tip(&self, tip: &str) {
        set_str_attribute(self.handle(), "TIP", tip);
    }

    fn min_size(&self) -> (i32, i32) {
        get_int_int_attribute(self.handle(), "MINSIZE")
    }

    fn set_min_size(&self, x: i32, y: i32) {
        let s = format!("{}x{}", x, y);
        set_str_attribute(self.handle(), "MINSIZE", &s);
    }

    fn max_size(&self) -> (i32, i32) {
        get_int_int_attribute(self.handle(), "MAXSIZE")
    }

    fn set_max_size(&self, x: i32, y: i32) {
        let s = format!("{}x{}", x, y);
        set_str_attribute(self.handle(), "MAXSIZE", &s);
    }

    fn show(&self) -> Result<(), ()> {
        unsafe {
            if IupShow(self.handle()) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    fn hide(&self) -> Result<(), ()> {
        unsafe {
            if IupHide(self.handle()) == IUP_NOERROR {
                Ok(())
            } else {
                Err(())
            }
        }
    }

    fn set_visible(&self, visible: bool) -> Result<(), ()> {
        if visible { self.show() } else { self.hide() }
    }
}

pub trait TitleAttribute : Control {
    fn title(&self) -> String {
        get_str_attribute(self.handle(), "TITLE")
    }

    fn set_title(&self, title: &str) {
        set_str_attribute(self.handle(), "TITLE", title);
    }
}

pub trait OrientationAttribute : Control {
    fn orientation(&self) -> ::Orientation {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ORIENTATION");
            ::Orientation::from_str(s.as_bytes())
        }
    }

    fn set_orientation(&self, orientation: ::Orientation) {
        set_str_attribute(self.handle(), "ORIENTATION", orientation.to_str());
    }
}
<|endoftext|>