<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

#[macro_use]
mod macros;

mod error;
pub use error::{Error, Result, WaitForTransactionError};

cfg_blocking! {
    mod blocking;
    pub use blocking::BlockingClient;
}

cfg_async! {
    mod client;
    pub use client::Client;

    mod verifying_client;
    pub use verifying_client::{Storage, InMemoryStorage, VerifyingClient};
}

cfg_faucet! {
    mod faucet;
    pub use faucet::FaucetClient;
}

mod request;
pub use request::{JsonRpcRequest, MethodRequest};

mod response;
pub use response::{MethodResponse, Response};

cfg_async_or_blocking! {
    mod move_deserialize;
    pub use move_deserialize::Event;
}

mod state;
pub use state::State;

mod retry;
pub use retry::Retry;

pub use diem_json_rpc_types::{errors, views};
pub use diem_types::{account_address::AccountAddress, transaction::SignedTransaction};

use serde::{Deserialize, Serialize};

cfg_async_or_blocking! {
    const USER_AGENT: &str = concat!("diem-client-sdk-rust / ", env!("CARGO_PKG_VERSION"));
}

#[derive(Debug, Deserialize, Serialize)]
enum JsonRpcVersion {
    #[serde(rename = "2.0")]
    V2,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Method {
    Submit,
    GetMetadata,
    GetAccount,
    GetTransactions,
    GetAccountTransaction,
    GetAccountTransactions,
    GetEvents,
    GetCurrencies,
    GetNetworkStatus,

    //
    // Experimental APIs
    //
    GetStateProof,
    GetAccountStateWithProof,
    GetTransactionsWithProofs,
    GetEventsWithProofs,
}

cfg_async_or_blocking! {
    fn validate(
        state_manager: &state::StateManager,
        resp: &diem_json_rpc_types::response::JsonRpcResponse,
        ignore_stale: bool,
    ) -> Result<(u64, State, serde_json::Value)> {
        if resp.jsonrpc != "2.0" {
            return Err(Error::rpc_response(format!(
                "unsupported jsonrpc version {}",
                resp.jsonrpc
            )));
        }
        let id = get_id(resp)?;

        if let Some(err) = &resp.error {
            return Err(Error::json_rpc(err.clone()));
        }

        let state = State::from_response(resp);
        if let Err(e) = state_manager.update_state(&state) {
            if !ignore_stale {
                return Err(e);
            }
        }

        // Result being empty is an acceptable response
        let result = resp.result.clone().unwrap_or(serde_json::Value::Null);

        Ok((id, state, result))
    }

    fn validate_batch(
        state_manager: &state::StateManager,
        requests: &[JsonRpcRequest],
        raw_responses: Vec<diem_json_rpc_types::response::JsonRpcResponse>,
    ) -> Result<Vec<Result<Response<MethodResponse>>>> {
        let mut responses = std::collections::HashMap::new();
        for raw_response in &raw_responses {
            let id = get_id(&raw_response)?;
            let response = validate(state_manager, &raw_response, false);

            responses.insert(id, response);
        }

        let mut result = Vec::new();

        for request in requests {
            let response = if let Some(response) = responses.remove(&request.id()) {
                response
            } else {
                return Err(Error::batch(format!("{:?}", raw_responses)));
            };

            let response = response.and_then(|(_id, state, result)| {
                MethodResponse::from_json(request.method(), result)
                    .map(|result| Response::new(result, state))
            });

            result.push(response);
        }

        if !responses.is_empty() {
            return Err(Error::batch(format!("{:?}", raw_responses)));
        }

        Ok(result)
    }

    fn get_id(resp: &diem_json_rpc_types::response::JsonRpcResponse) -> Result<u64> {
        let id = if let Some(id) = &resp.id {
            if let Ok(index) = serde_json::from_value::<u64>(id.clone()) {
                index
            } else {
                return Err(Error::rpc_response("invalid response id type"));
            }
        } else {
            return Err(Error::rpc_response("missing response id"));
        };

        Ok(id)
    }

    #[derive(Debug, Deserialize, Serialize)]
    #[serde(untagged)]
    enum BatchResponse {
        Success(Vec<diem_json_rpc_types::response::JsonRpcResponse>),
        Error(Box<diem_json_rpc_types::response::JsonRpcResponse>),
    }

    impl BatchResponse {
        pub fn success(self) -> Result<Vec<diem_json_rpc_types::response::JsonRpcResponse>> {
            match self {
                BatchResponse::Success(inner) => Ok(inner),
                BatchResponse::Error(e) => Err(Error::json_rpc(e.error.unwrap())),
            }
        }
    }
}
<commit_msg>[sdk] #[doc(hidden)] the VerifyingClient<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

#[macro_use]
mod macros;

mod error;
pub use error::{Error, Result, WaitForTransactionError};

cfg_blocking! {
    mod blocking;
    pub use blocking::BlockingClient;
}

cfg_async! {
    mod client;
    pub use client::Client;

    mod verifying_client;
    // WARNING: the VerifyingClient is currently experimental; it's not recommended
    // to use it until it stabilizes further
    // TODO(philiphayes): make this pub once verifying_client is stable.
    #[doc(hidden)]
    pub use verifying_client::{Storage, InMemoryStorage, VerifyingClient};
}

cfg_faucet! {
    mod faucet;
    pub use faucet::FaucetClient;
}

mod request;
pub use request::{JsonRpcRequest, MethodRequest};

mod response;
pub use response::{MethodResponse, Response};

cfg_async_or_blocking! {
    mod move_deserialize;
    pub use move_deserialize::Event;
}

mod state;
pub use state::State;

mod retry;
pub use retry::Retry;

pub use diem_json_rpc_types::{errors, views};
pub use diem_types::{account_address::AccountAddress, transaction::SignedTransaction};

use serde::{Deserialize, Serialize};

cfg_async_or_blocking! {
    const USER_AGENT: &str = concat!("diem-client-sdk-rust / ", env!("CARGO_PKG_VERSION"));
}

#[derive(Debug, Deserialize, Serialize)]
enum JsonRpcVersion {
    #[serde(rename = "2.0")]
    V2,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Method {
    Submit,
    GetMetadata,
    GetAccount,
    GetTransactions,
    GetAccountTransaction,
    GetAccountTransactions,
    GetEvents,
    GetCurrencies,
    GetNetworkStatus,

    //
    // Experimental APIs
    //
    GetStateProof,
    GetAccountStateWithProof,
    GetTransactionsWithProofs,
    GetEventsWithProofs,
}

cfg_async_or_blocking! {
    fn validate(
        state_manager: &state::StateManager,
        resp: &diem_json_rpc_types::response::JsonRpcResponse,
        ignore_stale: bool,
    ) -> Result<(u64, State, serde_json::Value)> {
        if resp.jsonrpc != "2.0" {
            return Err(Error::rpc_response(format!(
                "unsupported jsonrpc version {}",
                resp.jsonrpc
            )));
        }
        let id = get_id(resp)?;

        if let Some(err) = &resp.error {
            return Err(Error::json_rpc(err.clone()));
        }

        let state = State::from_response(resp);
        if let Err(e) = state_manager.update_state(&state) {
            if !ignore_stale {
                return Err(e);
            }
        }

        // Result being empty is an acceptable response
        let result = resp.result.clone().unwrap_or(serde_json::Value::Null);

        Ok((id, state, result))
    }

    fn validate_batch(
        state_manager: &state::StateManager,
        requests: &[JsonRpcRequest],
        raw_responses: Vec<diem_json_rpc_types::response::JsonRpcResponse>,
    ) -> Result<Vec<Result<Response<MethodResponse>>>> {
        let mut responses = std::collections::HashMap::new();
        for raw_response in &raw_responses {
            let id = get_id(&raw_response)?;
            let response = validate(state_manager, &raw_response, false);

            responses.insert(id, response);
        }

        let mut result = Vec::new();

        for request in requests {
            let response = if let Some(response) = responses.remove(&request.id()) {
                response
            } else {
                return Err(Error::batch(format!("{:?}", raw_responses)));
            };

            let response = response.and_then(|(_id, state, result)| {
                MethodResponse::from_json(request.method(), result)
                    .map(|result| Response::new(result, state))
            });

            result.push(response);
        }

        if !responses.is_empty() {
            return Err(Error::batch(format!("{:?}", raw_responses)));
        }

        Ok(result)
    }

    fn get_id(resp: &diem_json_rpc_types::response::JsonRpcResponse) -> Result<u64> {
        let id = if let Some(id) = &resp.id {
            if let Ok(index) = serde_json::from_value::<u64>(id.clone()) {
                index
            } else {
                return Err(Error::rpc_response("invalid response id type"));
            }
        } else {
            return Err(Error::rpc_response("missing response id"));
        };

        Ok(id)
    }

    #[derive(Debug, Deserialize, Serialize)]
    #[serde(untagged)]
    enum BatchResponse {
        Success(Vec<diem_json_rpc_types::response::JsonRpcResponse>),
        Error(Box<diem_json_rpc_types::response::JsonRpcResponse>),
    }

    impl BatchResponse {
        pub fn success(self) -> Result<Vec<diem_json_rpc_types::response::JsonRpcResponse>> {
            match self {
                BatchResponse::Success(inner) => Ok(inner),
                BatchResponse::Error(e) => Err(Error::json_rpc(e.error.unwrap())),
            }
        }
    }
}
<|endoftext|>


<commit_before>use serde::{ser, Serialize};

use error::Error;
use token::Token;

/// A `Serializer` that ensures that a value serializes to a given list of tokens.
pub struct Serializer<'a> {
    tokens: &'a [Token],
}

impl<'a> Serializer<'a> {
    /// Creates the serializer.
    pub fn new(tokens: &'a [Token]) -> Self {
        Serializer {
            tokens: tokens,
        }
    }

    /// Pulls the next token off of the serializer, ignoring it.
    pub fn next_token(&mut self) -> Option<&Token> {
        if let Some((first, rest)) = self.tokens.split_first() {
            self.tokens = rest;
            Some(first)
        } else {
            None
        }
    }
}

macro_rules! assert_next_token {
    ($self:ident, $expected:ident($arg:expr)) => {
        match $self.next_token() {
            Some(&Token::$expected(v)) if v == $arg => {}
            Some(other) => {
                panic!("expected {}({:?}) but serialized as {:?}", stringify!($expected), $arg, other);
            }
            None => {
                panic!("expected {}({:?}) after end of serialized tokens", stringify!($expected), $arg);
            }
        }
    }
}

impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Self;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Self;
    type SerializeMap = Self;
    type SerializeStruct = Self;
    type SerializeStructVariant = Self;

    fn serialize_bool(self, v: bool) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::Bool(v)));
        Ok(())
    }

    fn serialize_i8(self, v: i8) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::I8(v)));
        Ok(())
    }

    fn serialize_i16(self, v: i16) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::I16(v)));
        Ok(())
    }

    fn serialize_i32(self, v: i32) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::I32(v)));
        Ok(())
    }

    fn serialize_i64(self, v: i64) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::I64(v)));
        Ok(())
    }

    fn serialize_u8(self, v: u8) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::U8(v)));
        Ok(())
    }

    fn serialize_u16(self, v: u16) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::U16(v)));
        Ok(())
    }

    fn serialize_u32(self, v: u32) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::U32(v)));
        Ok(())
    }

    fn serialize_u64(self, v: u64) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::U64(v)));
        Ok(())
    }

    fn serialize_f32(self, v: f32) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::F32(v)));
        Ok(())
    }

    fn serialize_f64(self, v: f64) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::F64(v)));
        Ok(())
    }

    fn serialize_char(self, v: char) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::Char(v)));
        Ok(())
    }

    fn serialize_str(self, v: &str) -> Result<(), Error> {
        assert_next_token!(self, Str(v));
        Ok(())
    }

    fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> {
        assert_next_token!(self, Bytes(value));
        Ok(())
    }

    fn serialize_unit(self) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::Unit));
        Ok(())
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::UnitStruct(name)));
        Ok(())
    }

    fn serialize_unit_variant(self,
                              name: &'static str,
                              _variant_index: usize,
                              variant: &'static str)
                              -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::EnumUnit(name, variant)));
        Ok(())
    }

    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::StructNewType(name)));
        value.serialize(self)
    }

    fn serialize_newtype_variant<T: ?Sized>(self,
                                            name: &'static str,
                                            _variant_index: usize,
                                            variant: &'static str,
                                            value: &T)
                                            -> Result<(), Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::EnumNewType(name, variant)));
        value.serialize(self)
    }

    fn serialize_none(self) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::Option(false)));
        Ok(())
    }

    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::Option(true)));
        value.serialize(self)
    }

    fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
        assert_eq!(self.next_token(), Some(&Token::SeqStart(len)));
        Ok(self)
    }

    fn serialize_seq_fixed_size(self, len: usize) -> Result<Self, Error> {
        assert_eq!(self.next_token(), Some(&Token::SeqArrayStart(len)));
        Ok(self)
    }

    fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
        assert_eq!(self.next_token(), Some(&Token::TupleStart(len)));
        Ok(self)
    }

    fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_eq!(self.next_token(),
                   Some(&Token::TupleStructStart(name, len)));
        Ok(self)
    }

    fn serialize_tuple_variant(self,
                               name: &'static str,
                               _variant_index: usize,
                               variant: &'static str,
                               len: usize)
                               -> Result<Self, Error> {
        assert_eq!(self.next_token(),
                   Some(&Token::EnumSeqStart(name, variant, len)));
        Ok(self)
    }

    fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
        assert_eq!(self.next_token(), Some(&Token::MapStart(len)));
        Ok(self)
    }

    fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_eq!(self.next_token(), Some(&Token::StructStart(name, len)));
        Ok(self)
    }

    fn serialize_struct_variant(self,
                                name: &'static str,
                                _variant_index: usize,
                                variant: &'static str,
                                len: usize)
                                -> Result<Self, Error> {
        assert_eq!(self.next_token(),
                   Some(&Token::EnumMapStart(name, variant, len)));
        Ok(self)
    }
}

impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::SeqSep));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::SeqEnd));
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::TupleSep));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::TupleEnd));
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::TupleStructSep));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::TupleStructEnd));
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleVariant for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::EnumSeqSep));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_eq!(self.next_token(), Some(&Token::EnumSeqEnd));
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::MapSep));
        key.serialize(&mut **self)
    }

    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
        where T: Serialize
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_eq!(self.next_token(), Some(&Token::MapEnd));
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self,
                                  key: &'static str,
                                  value: &T)
                                  -> Result<(), Self::Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::StructSep));
        try!(key.serialize(&mut **self));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_eq!(self.next_token(), Some(&Token::StructEnd));
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStructVariant for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self,
                                  key: &'static str,
                                  value: &T)
                                  -> Result<(), Self::Error>
        where T: Serialize
    {
        assert_eq!(self.next_token(), Some(&Token::EnumMapSep));
        try!(key.serialize(&mut **self));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_eq!(self.next_token(), Some(&Token::EnumMapEnd));
        Ok(())
    }
}
<commit_msg>Improve assert_ser_tokens error messages<commit_after>use serde::{ser, Serialize};

use error::Error;
use token::Token;

/// A `Serializer` that ensures that a value serializes to a given list of tokens.
pub struct Serializer<'a> {
    tokens: &'a [Token],
}

impl<'a> Serializer<'a> {
    /// Creates the serializer.
    pub fn new(tokens: &'a [Token]) -> Self {
        Serializer {
            tokens: tokens,
        }
    }

    /// Pulls the next token off of the serializer, ignoring it.
    pub fn next_token(&mut self) -> Option<Token> {
        if let Some((&first, rest)) = self.tokens.split_first() {
            self.tokens = rest;
            Some(first)
        } else {
            None
        }
    }
}

macro_rules! assert_next_token {
    ($self:ident, $expected:ident($a:expr)) => {
        assert_next_token!($self, $expected { a: $a });
    };
    ($self:ident, $expected:ident($a:expr, $b:expr)) => {
        assert_next_token!($self, $expected { a: $a, b: $b });
    };
    ($self:ident, $expected:ident($a:expr, $b:expr, $c:expr)) => {
        assert_next_token!($self, $expected { a: $a, b: $b, c: $c });
    };
    ($self:ident, $expected:ident $({ $($n:ident: $v:expr),* })*) => {
        match $self.next_token() {
            Some(Token::$expected $(($($n),*))*) $(if $($n == $v)&&*)* => {}
            Some(other) => {
                panic!("expected Token::{} but serialized as {:?}",
                       stringify!($expected), other);
            }
            None => {
                panic!("expected Token::{} after end of serialized tokens",
                       stringify!($expected));
            }
        }
    };
}

impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Self;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Self;
    type SerializeMap = Self;
    type SerializeStruct = Self;
    type SerializeStructVariant = Self;

    fn serialize_bool(self, v: bool) -> Result<(), Error> {
        assert_next_token!(self, Bool(v));
        Ok(())
    }

    fn serialize_i8(self, v: i8) -> Result<(), Error> {
        assert_next_token!(self, I8(v));
        Ok(())
    }

    fn serialize_i16(self, v: i16) -> Result<(), Error> {
        assert_next_token!(self, I16(v));
        Ok(())
    }

    fn serialize_i32(self, v: i32) -> Result<(), Error> {
        assert_next_token!(self, I32(v));
        Ok(())
    }

    fn serialize_i64(self, v: i64) -> Result<(), Error> {
        assert_next_token!(self, I64(v));
        Ok(())
    }

    fn serialize_u8(self, v: u8) -> Result<(), Error> {
        assert_next_token!(self, U8(v));
        Ok(())
    }

    fn serialize_u16(self, v: u16) -> Result<(), Error> {
        assert_next_token!(self, U16(v));
        Ok(())
    }

    fn serialize_u32(self, v: u32) -> Result<(), Error> {
        assert_next_token!(self, U32(v));
        Ok(())
    }

    fn serialize_u64(self, v: u64) -> Result<(), Error> {
        assert_next_token!(self, U64(v));
        Ok(())
    }

    fn serialize_f32(self, v: f32) -> Result<(), Error> {
        assert_next_token!(self, F32(v));
        Ok(())
    }

    fn serialize_f64(self, v: f64) -> Result<(), Error> {
        assert_next_token!(self, F64(v));
        Ok(())
    }

    fn serialize_char(self, v: char) -> Result<(), Error> {
        assert_next_token!(self, Char(v));
        Ok(())
    }

    fn serialize_str(self, v: &str) -> Result<(), Error> {
        assert_next_token!(self, Str(v));
        Ok(())
    }

    fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> {
        assert_next_token!(self, Bytes(value));
        Ok(())
    }

    fn serialize_unit(self) -> Result<(), Error> {
        assert_next_token!(self, Unit);
        Ok(())
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
        assert_next_token!(self, UnitStruct(name));
        Ok(())
    }

    fn serialize_unit_variant(self,
                              name: &'static str,
                              _variant_index: usize,
                              variant: &'static str)
                              -> Result<(), Error> {
        assert_next_token!(self, EnumUnit(name, variant));
        Ok(())
    }

    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_next_token!(self, StructNewType(name));
        value.serialize(self)
    }

    fn serialize_newtype_variant<T: ?Sized>(self,
                                            name: &'static str,
                                            _variant_index: usize,
                                            variant: &'static str,
                                            value: &T)
                                            -> Result<(), Error>
        where T: Serialize
    {
        assert_next_token!(self, EnumNewType(name, variant));
        value.serialize(self)
    }

    fn serialize_none(self) -> Result<(), Error> {
        assert_next_token!(self, Option(false));
        Ok(())
    }

    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_next_token!(self, Option(true));
        value.serialize(self)
    }

    fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, SeqStart(len));
        Ok(self)
    }

    fn serialize_seq_fixed_size(self, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, SeqArrayStart(len));
        Ok(self)
    }

    fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, TupleStart(len));
        Ok(self)
    }

    fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, TupleStructStart(name, len));
        Ok(self)
    }

    fn serialize_tuple_variant(self,
                               name: &'static str,
                               _variant_index: usize,
                               variant: &'static str,
                               len: usize)
                               -> Result<Self, Error> {
        assert_next_token!(self, EnumSeqStart(name, variant, len));
        Ok(self)
    }

    fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, MapStart(len));
        Ok(self)
    }

    fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, StructStart(name, len));
        Ok(self)
    }

    fn serialize_struct_variant(self,
                                name: &'static str,
                                _variant_index: usize,
                                variant: &'static str,
                                len: usize)
                                -> Result<Self, Error> {
        assert_next_token!(self, EnumMapStart(name, variant, len));
        Ok(self)
    }
}

impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_next_token!(self, SeqSep);
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, SeqEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_next_token!(self, TupleSep);
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_next_token!(self, TupleStructSep);
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleStructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleVariant for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
        where T: Serialize
    {
        assert_next_token!(self, EnumSeqSep);
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, EnumSeqEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
        where T: Serialize
    {
        assert_next_token!(self, MapSep);
        key.serialize(&mut **self)
    }

    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
        where T: Serialize
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, MapEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self,
                                  key: &'static str,
                                  value: &T)
                                  -> Result<(), Self::Error>
        where T: Serialize
    {
        assert_next_token!(self, StructSep);
        try!(key.serialize(&mut **self));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, StructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStructVariant for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self,
                                  key: &'static str,
                                  value: &T)
                                  -> Result<(), Self::Error>
        where T: Serialize
    {
        assert_next_token!(self, EnumMapSep);
        try!(key.serialize(&mut **self));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, EnumMapEnd);
        Ok(())
    }
}
<|endoftext|>


<commit_before>use crate::error::ContextError;
use crate::{Context, Error, StdError};
use core::convert::Infallible;
use core::fmt::{self, Debug, Display, Write};

#[cfg(backtrace)]
use std::any::Demand;

mod ext {
    use super::*;

    pub trait StdError {
        fn ext_context<C>(self, context: C) -> Error
        where
            C: Display + Send + Sync + 'static;
    }

    #[cfg(feature = "std")]
    impl<E> StdError for E
    where
        E: std::error::Error + Send + Sync + 'static,
    {
        fn ext_context<C>(self, context: C) -> Error
        where
            C: Display + Send + Sync + 'static,
        {
            let backtrace = backtrace_if_absent!(&self);
            Error::from_context(context, self, backtrace)
        }
    }

    impl StdError for Error {
        fn ext_context<C>(self, context: C) -> Error
        where
            C: Display + Send + Sync + 'static,
        {
            self.context(context)
        }
    }
}

impl<T, E> Context<T, E> for Result<T, E>
where
    E: ext::StdError + Send + Sync + 'static,
{
    fn context<C>(self, context: C) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
    {
        // Not using map_err to save 2 useless frames off the captured backtrace
        // in ext_context.
        match self {
            Ok(ok) => Ok(ok),
            Err(error) => Err(error.ext_context(context)),
        }
    }

    fn with_context<C, F>(self, context: F) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
        F: FnOnce() -> C,
    {
        match self {
            Ok(ok) => Ok(ok),
            Err(error) => Err(error.ext_context(context())),
        }
    }
}

/// ```
/// # type T = ();
/// #
/// use anyhow::{Context, Result};
///
/// fn maybe_get() -> Option<T> {
///     # const IGNORE: &str = stringify! {
///     ...
///     # };
///     # unimplemented!()
/// }
///
/// fn demo() -> Result<()> {
///     let t = maybe_get().context("there is no T")?;
///     # const IGNORE: &str = stringify! {
///     ...
///     # };
///     # unimplemented!()
/// }
/// ```
impl<T> Context<T, Infallible> for Option<T> {
    fn context<C>(self, context: C) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
    {
        // Not using ok_or_else to save 2 useless frames off the captured
        // backtrace.
        match self {
            Some(ok) => Ok(ok),
            None => Err(Error::from_display(context, backtrace!())),
        }
    }

    fn with_context<C, F>(self, context: F) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
        F: FnOnce() -> C,
    {
        match self {
            Some(ok) => Ok(ok),
            None => Err(Error::from_display(context(), backtrace!())),
        }
    }
}

impl<C, E> Debug for ContextError<C, E>
where
    C: Display,
    E: Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Error")
            .field("context", &Quoted(&self.context))
            .field("source", &self.error)
            .finish()
    }
}

impl<C, E> Display for ContextError<C, E>
where
    C: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.context, f)
    }
}

impl<C, E> StdError for ContextError<C, E>
where
    C: Display,
    E: StdError + 'static,
{
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        Some(&self.error)
    }

    #[cfg(backtrace)]
    fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
        self.error.provide(demand);
    }
}

impl<C> StdError for ContextError<C, Error>
where
    C: Display,
{
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) })
    }

    #[cfg(backtrace)]
    fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
        self.error.provide(demand);
    }
}

struct Quoted<C>(C);

impl<C> Debug for Quoted<C>
where
    C: Display,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_char('"')?;
        Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?;
        formatter.write_char('"')?;
        Ok(())
    }
}

impl Write for Quoted<&mut fmt::Formatter<'_>> {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        Display::fmt(&s.escape_debug(), self.0)
    }
}

pub(crate) mod private {
    use super::*;

    pub trait Sealed {}

    impl<T, E> Sealed for Result<T, E> where E: ext::StdError {}
    impl<T> Sealed for Option<T> {}
}
<commit_msg>Call Provider::provide not Error::provide<commit_after>use crate::error::ContextError;
use crate::{Context, Error, StdError};
use core::convert::Infallible;
use core::fmt::{self, Debug, Display, Write};

#[cfg(backtrace)]
use std::any::{Demand, Provider};

mod ext {
    use super::*;

    pub trait StdError {
        fn ext_context<C>(self, context: C) -> Error
        where
            C: Display + Send + Sync + 'static;
    }

    #[cfg(feature = "std")]
    impl<E> StdError for E
    where
        E: std::error::Error + Send + Sync + 'static,
    {
        fn ext_context<C>(self, context: C) -> Error
        where
            C: Display + Send + Sync + 'static,
        {
            let backtrace = backtrace_if_absent!(&self);
            Error::from_context(context, self, backtrace)
        }
    }

    impl StdError for Error {
        fn ext_context<C>(self, context: C) -> Error
        where
            C: Display + Send + Sync + 'static,
        {
            self.context(context)
        }
    }
}

impl<T, E> Context<T, E> for Result<T, E>
where
    E: ext::StdError + Send + Sync + 'static,
{
    fn context<C>(self, context: C) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
    {
        // Not using map_err to save 2 useless frames off the captured backtrace
        // in ext_context.
        match self {
            Ok(ok) => Ok(ok),
            Err(error) => Err(error.ext_context(context)),
        }
    }

    fn with_context<C, F>(self, context: F) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
        F: FnOnce() -> C,
    {
        match self {
            Ok(ok) => Ok(ok),
            Err(error) => Err(error.ext_context(context())),
        }
    }
}

/// ```
/// # type T = ();
/// #
/// use anyhow::{Context, Result};
///
/// fn maybe_get() -> Option<T> {
///     # const IGNORE: &str = stringify! {
///     ...
///     # };
///     # unimplemented!()
/// }
///
/// fn demo() -> Result<()> {
///     let t = maybe_get().context("there is no T")?;
///     # const IGNORE: &str = stringify! {
///     ...
///     # };
///     # unimplemented!()
/// }
/// ```
impl<T> Context<T, Infallible> for Option<T> {
    fn context<C>(self, context: C) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
    {
        // Not using ok_or_else to save 2 useless frames off the captured
        // backtrace.
        match self {
            Some(ok) => Ok(ok),
            None => Err(Error::from_display(context, backtrace!())),
        }
    }

    fn with_context<C, F>(self, context: F) -> Result<T, Error>
    where
        C: Display + Send + Sync + 'static,
        F: FnOnce() -> C,
    {
        match self {
            Some(ok) => Ok(ok),
            None => Err(Error::from_display(context(), backtrace!())),
        }
    }
}

impl<C, E> Debug for ContextError<C, E>
where
    C: Display,
    E: Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Error")
            .field("context", &Quoted(&self.context))
            .field("source", &self.error)
            .finish()
    }
}

impl<C, E> Display for ContextError<C, E>
where
    C: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.context, f)
    }
}

impl<C, E> StdError for ContextError<C, E>
where
    C: Display,
    E: StdError + 'static,
{
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        Some(&self.error)
    }

    #[cfg(backtrace)]
    fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
        self.error.provide(demand);
    }
}

impl<C> StdError for ContextError<C, Error>
where
    C: Display,
{
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) })
    }

    #[cfg(backtrace)]
    fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
        Provider::provide(&self.error, demand);
    }
}

struct Quoted<C>(C);

impl<C> Debug for Quoted<C>
where
    C: Display,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_char('"')?;
        Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?;
        formatter.write_char('"')?;
        Ok(())
    }
}

impl Write for Quoted<&mut fmt::Formatter<'_>> {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        Display::fmt(&s.escape_debug(), self.0)
    }
}

pub(crate) mod private {
    use super::*;

    pub trait Sealed {}

    impl<T, E> Sealed for Result<T, E> where E: ext::StdError {}
    impl<T> Sealed for Option<T> {}
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::hash_map::Entry;
use syntax::ast::{Expr, Ident, TokenTree};
use syntax::codemap::{BytePos, CodeMap};
use syntax::ext::base::ExtCtxt;
use syntax::ext::quote::rt::ToTokens;
use syntax::fold::{self, Folder};
use syntax::parse::{self, token};
use syntax::ptr::P;
use syntax::print::pprust;

fn register_pos(map: &mut HashMap<BytePos, i32>, org_pos: BytePos, pp_pos: i32) {
    match map.entry(org_pos) {
        Entry::Occupied(e) => {
            assert_eq!(e.get(), &pp_pos);
        }
        Entry::Vacant(e) => {
            let _ = e.insert(pp_pos);
        }
    }
}

fn register_pos_rec(map: &mut HashMap<BytePos, i32>, codemap: &CodeMap, tt: &TokenTree, ptt: &TokenTree) {
    let line = codemap.span_to_lines(ptt.get_span()).unwrap();
    register_pos(map, tt.get_span().lo, line.lines[0].start_col.0 as i32);
    register_pos(map, tt.get_span().hi, line.lines[0].end_col.0 as i32);
    assert_eq!(tt.len(), ptt.len());
    for i in 0..tt.len() {
        register_pos_rec(map, codemap, &tt.get_tt(i), &ptt.get_tt(i));
    }
}

fn create_pos_map(
    cx: &mut ExtCtxt, ppstr: String, original_tokens: &[TokenTree])
    -> HashMap<BytePos, i32>
{
    let codemap = cx.parse_sess().codemap();
    let filemap = codemap.new_filemap("".to_string(), ppstr);
    let ptokens = parse::filemap_to_tts(cx.parse_sess(), filemap);

    let mut map = HashMap::new();
    for (tt, ptt) in original_tokens.iter().zip(ptokens) {
        register_pos_rec(&mut map, &codemap, &tt, &ptt);
    }
    map
}

struct AssertFolder<'cx> {
    cx: &'cx ExtCtxt<'cx>,
    pos_map: &'cx HashMap<BytePos, i32>,
    ident: Ident
}

impl<'cx> Folder for AssertFolder<'cx> {
    fn fold_expr(&mut self, expr: P<Expr>) -> P<Expr> {
        expr.and_then(|expr| {
            use syntax::ast::*;
            match expr.node {
                // ExprBox
                // ExprVec
                ExprCall(ref i, ref args) => {
                    let col = self.pos_map.get(&i.span.lo).unwrap();
                    let args = args.iter()
                        .map(|expr| self.fold_expr(expr.clone()))
                        .collect::<Vec<_>>();
                    let ident = self.ident;
                    let mut call_expr = expr.clone();
                    call_expr.node = ExprCall(i.clone(), args);

                    let call_expr = P(call_expr);
                    quote_expr!(self.cx, {
                        let expr = $call_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                ExprMethodCall(i, _, _) => {
                    // TODO: fix column
                    let col = self.pos_map.get(&i.span.lo).unwrap();
                    let conv_expr = P(fold::noop_fold_expr(expr, self));
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        let expr = $conv_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                // ExprTup
                ExprBinary(op, _, _) => {
                    let col = self.pos_map.get(&op.span.lo).unwrap();
                    let conv_expr = P(fold::noop_fold_expr(expr, self));
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        let expr = $conv_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                // ExprUnary
                // ExprLit
                // ExprCast
                ExprIf(_, _, _) |
                ExprIfLet(_, _, _, _) |
                ExprMatch(_, _, _) => {
                    let col = self.pos_map.get(&expr.span.lo).unwrap();
                    let conv_expr = P(fold::noop_fold_expr(expr, self));
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        let expr = $conv_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                // ExprWhile
                // ExprWhileLet
                // ExprForLoop
                // ExprLoop
                // ExprMatch: See above
                // ExprClosure
                // ExprBlock
                // ExprAssign
                // ExprAssignOp
                ExprField(_, _) => {
                    self.convert_field(P(expr.clone()))
                }
                ExprTupField(_, _) => {
                    self.convert_field(P(expr.clone()))
                }
                ExprIndex(_, ref i) => {
                    // TODO: Fix column
                    let col = self.pos_map.get(&i.span.lo).unwrap();
                    let conv_expr = P(fold::noop_fold_expr(expr.clone(), self));
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        let expr = $conv_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                // ExprRange
                ExprPath(_, _) => {
                    let col = self.pos_map.get(&expr.span.lo).unwrap();
                    let expr = P(expr);
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        $ident.push(($col, format!("{:?}", $expr)));
                        $expr
                    })
                }
                // ExprAddrOf
                // ExprBreak
                // ExprAgain
                // ExprRet
                // ExprInlineAsm
                // ExprMac
                // ExprStruct
                // ExprRepeat
                // ExprParen
                _ => P(fold::noop_fold_expr(expr, self))
            }
        })
    }
}

impl<'cx> AssertFolder<'cx> {
    fn convert_field(&mut self, expr: P<Expr>) -> P<Expr> {
        use syntax::ast::*;
        let mut exprs = vec![];
        let mut cur_expr = expr.clone();
        let prelude;
        let ident;
        loop {
            cur_expr = match cur_expr.node {
                ExprField(ref e, _) | ExprTupField(ref e, _) => {
                    exprs.push(cur_expr.clone());
                    e.clone()
                }
                ExprPath(_, _) => {
                    ident = cur_expr.clone();
                    let id = self.ident;
                    let col = self.pos_map.get(&expr.span.lo).unwrap();
                    prelude = quote_stmt!(self.cx, $id.push(($col, format!("{:?}", $ident))));
                    break;
                }
                _ => {
                    let id = token::gensym_ident("a");
                    ident = quote_expr!(self.cx, $id);
                    let conv_expr = P(fold::noop_fold_expr((*cur_expr).clone(), self));
                    prelude = quote_stmt!(self.cx, let $id = $conv_expr;);
                    break;
                }
            }
        }
        exprs.reverse();
        let exprs = exprs.into_iter().scan(ident, |st, item| {
            let mut item = (*item).clone();
            let col = match item.node {
                ExprField(_, i) => {
                    item.node = ExprField(st.clone(), i);
                    self.pos_map.get(&i.span.lo).unwrap()
                }
                ExprTupField(_, i) => {
                    item.node = ExprTupField(st.clone(), i);
                    self.pos_map.get(&i.span.lo).unwrap()
                }
                _ => panic!()
            };
            *st = P(item);
            Some((st.clone(), col))
        }).collect::<Vec<_>>();
        let last_expr = exprs[exprs.len() - 1].0.clone();
        let mut stmts = vec![prelude];
        for (e, col) in exprs {
            let ident = self.ident;
            stmts.push(quote_stmt!(self.cx, $ident.push(($col, format!("{:?}", $e)));));
        }
        quote_expr!(self.cx, {
            $stmts;
            $last_expr
        })
    }
}

pub fn convert_expr(cx: &mut ExtCtxt, expr: P<Expr>, ident: Ident, tts: &[TokenTree]) -> P<Expr> {
    // Pretty-printed snippet is used for showing assersion failed message, but
    // its tokens may have different spans from original code snippet's tokens.
    // Power-assert using those spans, so, parse the pretty-printed snippet
    // again to get tokens that have the same spans with pretty-printed snippet.
    let ppexpr_str = pprust::expr_to_string(&expr);
    let pos_map = create_pos_map(cx, ppexpr_str, tts);

    // Convert
    let mut folder = AssertFolder { cx: cx, pos_map: &pos_map, ident: ident };
    folder.fold_expr(expr)
}
<commit_msg>update to rustc 1.6.0-nightly (2e07996a9 2015-10-29)<commit_after>use std::collections::HashMap;
use std::collections::hash_map::Entry;
use syntax::ast::{Expr, Ident, TokenTree};
use syntax::codemap::{BytePos, CodeMap};
use syntax::ext::base::ExtCtxt;
use syntax::ext::quote::rt::ToTokens;
use syntax::fold::{self, Folder};
use syntax::parse::{self, token};
use syntax::ptr::P;
use syntax::print::pprust;

fn register_pos(map: &mut HashMap<BytePos, i32>, org_pos: BytePos, pp_pos: i32) {
    match map.entry(org_pos) {
        Entry::Occupied(e) => {
            assert_eq!(e.get(), &pp_pos);
        }
        Entry::Vacant(e) => {
            let _ = e.insert(pp_pos);
        }
    }
}

fn register_pos_rec(map: &mut HashMap<BytePos, i32>, codemap: &CodeMap, tt: &TokenTree, ptt: &TokenTree) {
    let line = codemap.span_to_lines(ptt.get_span()).unwrap();
    register_pos(map, tt.get_span().lo, line.lines[0].start_col.0 as i32);
    register_pos(map, tt.get_span().hi, line.lines[0].end_col.0 as i32);
    assert_eq!(tt.len(), ptt.len());
    for i in 0..tt.len() {
        register_pos_rec(map, codemap, &tt.get_tt(i), &ptt.get_tt(i));
    }
}

fn create_pos_map(
    cx: &mut ExtCtxt, ppstr: String, original_tokens: &[TokenTree])
    -> HashMap<BytePos, i32>
{
    let codemap = cx.parse_sess().codemap();
    let filemap = codemap.new_filemap("".to_string(), ppstr);
    let ptokens = parse::filemap_to_tts(cx.parse_sess(), filemap);

    let mut map = HashMap::new();
    for (tt, ptt) in original_tokens.iter().zip(ptokens) {
        register_pos_rec(&mut map, &codemap, &tt, &ptt);
    }
    map
}

struct AssertFolder<'cx> {
    cx: &'cx ExtCtxt<'cx>,
    pos_map: &'cx HashMap<BytePos, i32>,
    ident: Ident
}

impl<'cx> Folder for AssertFolder<'cx> {
    fn fold_expr(&mut self, expr: P<Expr>) -> P<Expr> {
        expr.and_then(|expr| {
            use syntax::ast::*;
            match expr.node {
                // ExprBox
                // ExprVec
                ExprCall(ref i, ref args) => {
                    let col = self.pos_map.get(&i.span.lo).unwrap();
                    let args = args.iter()
                        .map(|expr| self.fold_expr(expr.clone()))
                        .collect::<Vec<_>>();
                    let ident = self.ident;
                    let mut call_expr = expr.clone();
                    call_expr.node = ExprCall(i.clone(), args);

                    let call_expr = P(call_expr);
                    quote_expr!(self.cx, {
                        let expr = $call_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                ExprMethodCall(i, _, _) => {
                    // TODO: fix column
                    let col = self.pos_map.get(&i.span.lo).unwrap();
                    let conv_expr = P(fold::noop_fold_expr(expr, self));
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        let expr = $conv_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                // ExprTup
                ExprBinary(op, _, _) => {
                    let col = self.pos_map.get(&op.span.lo).unwrap();
                    let conv_expr = P(fold::noop_fold_expr(expr, self));
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        let expr = $conv_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                // ExprUnary
                // ExprLit
                // ExprCast
                ExprIf(..) |
                ExprIfLet(..) |
                ExprMatch(..) => {
                    let col = self.pos_map.get(&expr.span.lo).unwrap();
                    let conv_expr = P(fold::noop_fold_expr(expr, self));
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        let expr = $conv_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                // ExprWhile
                // ExprWhileLet
                // ExprForLoop
                // ExprLoop
                // ExprMatch: See above
                // ExprClosure
                // ExprBlock
                // ExprAssign
                // ExprAssignOp
                ExprField(..) => {
                    self.convert_field(P(expr.clone()))
                }
                ExprTupField(..) => {
                    self.convert_field(P(expr.clone()))
                }
                ExprIndex(_, ref i) => {
                    // TODO: Fix column
                    let col = self.pos_map.get(&i.span.lo).unwrap();
                    let conv_expr = P(fold::noop_fold_expr(expr.clone(), self));
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        let expr = $conv_expr;
                        $ident.push(($col, format!("{:?}", expr)));
                        expr
                    })
                }
                // ExprRange
                ExprPath(..) => {
                    let col = self.pos_map.get(&expr.span.lo).unwrap();
                    let expr = P(expr);
                    let ident = self.ident;
                    quote_expr!(self.cx, {
                        $ident.push(($col, format!("{:?}", $expr)));
                        $expr
                    })
                }
                // ExprAddrOf
                // ExprBreak
                // ExprAgain
                // ExprRet
                // ExprInlineAsm
                // ExprMac
                // ExprStruct
                // ExprRepeat
                // ExprParen
                _ => P(fold::noop_fold_expr(expr, self))
            }
        })
    }
}

impl<'cx> AssertFolder<'cx> {
    fn convert_field(&mut self, expr: P<Expr>) -> P<Expr> {
        use syntax::ast::*;
        let mut exprs = vec![];
        let mut cur_expr = expr.clone();
        let prelude;
        let ident;
        loop {
            cur_expr = match cur_expr.node {
                ExprField(ref e, _) | ExprTupField(ref e, _) => {
                    exprs.push(cur_expr.clone());
                    e.clone()
                }
                ExprPath(..) => {
                    ident = cur_expr.clone();
                    let id = self.ident;
                    let col = self.pos_map.get(&expr.span.lo).unwrap();
                    prelude = quote_stmt!(self.cx, $id.push(($col, format!("{:?}", $ident))));
                    break;
                }
                _ => {
                    let id = token::gensym_ident("a");
                    ident = quote_expr!(self.cx, $id);
                    let conv_expr = P(fold::noop_fold_expr((*cur_expr).clone(), self));
                    prelude = quote_stmt!(self.cx, let $id = $conv_expr;);
                    break;
                }
            }
        }
        exprs.reverse();
        let exprs = exprs.into_iter().scan(ident, |st, item| {
            let mut item = (*item).clone();
            let col = match item.node {
                ExprField(_, i) => {
                    item.node = ExprField(st.clone(), i);
                    self.pos_map.get(&i.span.lo).unwrap()
                }
                ExprTupField(_, i) => {
                    item.node = ExprTupField(st.clone(), i);
                    self.pos_map.get(&i.span.lo).unwrap()
                }
                _ => panic!()
            };
            *st = P(item);
            Some((st.clone(), col))
        }).collect::<Vec<_>>();
        let last_expr = exprs[exprs.len() - 1].0.clone();
        let mut stmts = vec![prelude];
        for (e, col) in exprs {
            let ident = self.ident;
            stmts.push(quote_stmt!(self.cx, $ident.push(($col, format!("{:?}", $e)));));
        }
        quote_expr!(self.cx, {
            $stmts;
            $last_expr
        })
    }
}

pub fn convert_expr(cx: &mut ExtCtxt, expr: P<Expr>, ident: Ident, tts: &[TokenTree]) -> P<Expr> {
    // Pretty-printed snippet is used for showing assersion failed message, but
    // its tokens may have different spans from original code snippet's tokens.
    // Power-assert using those spans, so, parse the pretty-printed snippet
    // again to get tokens that have the same spans with pretty-printed snippet.
    let ppexpr_str = pprust::expr_to_string(&expr);
    let pos_map = create_pos_map(cx, ppexpr_str, tts);

    // Convert
    let mut folder = AssertFolder { cx: cx, pos_map: &pos_map, ident: ident };
    folder.fold_expr(expr)
}
<|endoftext|>


<commit_before>#![allow(experimental)]

use std::io::{File,fs};
use std::io::process::Command;
use std::path::posix::Path;
use std::os::{homedir};
use std::rand::random;
use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = if muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
      Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string()))
    } else {
      create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
      create_project_file(path)
    } else {
      println!("Project already exists.");
    }
}

fn create_project_file(path: &Path) {
    File::create(path);

    let output = match Command::new("cat").arg("foot.txt").output() {
        Ok(output) => output,
        Err(e) => fail!("failed to execute process: {}", e),
    };
}

fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    fs::mkdir(path, ::std::io::UserRWX);
    path.clone()
}

fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

#[test]
fn muxed_dir_exists_returns_false() {
  let dir = format!("test_dir_{}", random::<f64>());
  assert!(!muxed_dir_exists(&dir));
}

#[test]
fn muxed_dir_exists_returns_true() {
  let dir = format!("test_dir_{}", random::<f64>());
  create_muxed_dir(&dir);
  assert!(muxed_dir_exists(&dir));

  let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir.as_slice()));
  fs::rmdir_recursive(muxed_path);
}

#[test]
fn creates_muxed_dir() {
    let name        = format!("test_project_{}", random::<f64>());
    let dir         = format!("test_dir_{}", random::<f64>());
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir.as_slice()));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    fs::rmdir_recursive(muxed_path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = format!("test_project_{}", random::<f64>());
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    fs::unlink(path);
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = format!("test_project_{}", random::<f64>());
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        fs::unlink(path);
    })
}
<commit_msg>Comment out the command call for now.<commit_after>#![allow(experimental)]

use std::io::{File,fs};
use std::io::process::Command;
use std::path::posix::Path;
use std::os::{homedir};
use std::rand::random;
use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = if muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
      Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string()))
    } else {
      create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
      create_project_file(path)
    } else {
      println!("Project already exists.");
    }
}

fn create_project_file(path: &Path) {
    File::create(path);
//    Command::new("vim").arg(format!("{}", path.display())).detached();
}

fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    fs::mkdir(path, ::std::io::UserRWX);
    path.clone()
}

fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

#[test]
fn muxed_dir_exists_returns_false() {
  let dir = format!("test_dir_{}", random::<f64>());
  assert!(!muxed_dir_exists(&dir));
}

#[test]
fn muxed_dir_exists_returns_true() {
  let dir = format!("test_dir_{}", random::<f64>());
  create_muxed_dir(&dir);
  assert!(muxed_dir_exists(&dir));

  let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir.as_slice()));
  fs::rmdir_recursive(muxed_path);
}

#[test]
fn creates_muxed_dir() {
    let name        = format!("test_project_{}", random::<f64>());
    let dir         = format!("test_dir_{}", random::<f64>());
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir.as_slice()));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    fs::rmdir_recursive(muxed_path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = format!("test_project_{}", random::<f64>());
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    fs::unlink(path);
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = format!("test_project_{}", random::<f64>());
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        fs::unlink(path);
    })
}
<|endoftext|>


<commit_before>//! Module that defines `SyntaxError`.

use std::fmt;

use crate::{TextRange, TextUnit};

/// Represents the result of unsuccessful tokenization, parsing
/// or tree validation.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SyntaxError(String, TextRange);

// FIXME: there was an unused SyntaxErrorKind previously (before this enum was removed)
// It was introduced in this PR: https://github.com/rust-analyzer/rust-analyzer/pull/846/files#diff-827da9b03b8f9faa1bade5cdd44d5dafR95
// but it was not removed by a mistake.
//
// So, we need to find a place where to stick validation for attributes in match clauses.
// Code before refactor:
// InvalidMatchInnerAttr => {
//    write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
// }

impl SyntaxError {
    pub fn new(message: impl Into<String>, range: TextRange) -> Self {
        Self(message.into(), range)
    }
    pub fn new_at_offset(message: impl Into<String>, offset: TextUnit) -> Self {
        Self(message.into(), TextRange::offset_len(offset, 1.into()))
    }

    pub fn message(&self) -> &str {
        &self.0
    }
    pub fn range(&self) -> &TextRange {
        &self.1
    }

    pub fn with_range(mut self, range: TextRange) -> Self {
        self.1 = range;
        self
    }
}

impl fmt::Display for SyntaxError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}
<commit_msg>ra_syntax: Apply Aleksei Kladov suggestion about TextRange of TextUnit<commit_after>//! Module that defines `SyntaxError`.

use std::fmt;

use crate::{TextRange, TextUnit};

/// Represents the result of unsuccessful tokenization, parsing
/// or tree validation.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SyntaxError(String, TextRange);

// FIXME: there was an unused SyntaxErrorKind previously (before this enum was removed)
// It was introduced in this PR: https://github.com/rust-analyzer/rust-analyzer/pull/846/files#diff-827da9b03b8f9faa1bade5cdd44d5dafR95
// but it was not removed by a mistake.
//
// So, we need to find a place where to stick validation for attributes in match clauses.
// Code before refactor:
// InvalidMatchInnerAttr => {
//    write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
// }

impl SyntaxError {
    pub fn new(message: impl Into<String>, range: TextRange) -> Self {
        Self(message.into(), range)
    }
    pub fn new_at_offset(message: impl Into<String>, offset: TextUnit) -> Self {
        Self(message.into(), TextRange::offset_len(offset, 0.into()))
    }

    pub fn message(&self) -> &str {
        &self.0
    }
    pub fn range(&self) -> &TextRange {
        &self.1
    }

    pub fn with_range(mut self, range: TextRange) -> Self {
        self.1 = range;
        self
    }
}

impl fmt::Display for SyntaxError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}
<|endoftext|>


<commit_before>use types::{OscPacket, OscType, OscResult, OscMessage, OscBundle};
use errors::OscError;
use utils;

use std::io;
use std::io::{Read, BufRead};

use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8]) -> OscResult<OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(OscError::BadPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8]) -> OscResult<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let addr: String = try!(read_osc_string(&mut cursor));
    let type_tags: String = try!(read_osc_string(&mut cursor));

    if type_tags.len() > 1 {
        let args: Vec<OscType> = try!(read_osc_args(&mut cursor, type_tags));

        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: Some(args),
        }))
    } else {
        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: None,
        }))
    }
}

fn decode_bundle(msg: &[u8]) -> OscResult<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let b = try!(read_osc_string(&mut cursor));
    if b != "bundle" {
        return Err(OscError::BadBundle);
    }

    let time_tag = try!(read_time_tag(&mut cursor));
    let mut bundle: Vec<OscPacket> = Vec::new();
    let size: usize = try!(cursor.read_u32::<BigEndian>()
                   .map_err(OscError::ByteOrderError)) as usize;
    let mut buf: Vec<u8> = Vec::new();
    let cnt: usize = try!(cursor.take(size as u64)
                                .read_to_end(&mut buf)
                                .map_err(OscError::ReadError));
    if cnt == size {
        try!(decode(&mut buf).map(|p| bundle.push(p)));
    } else {
        return Err(OscError::BadBundle);
    }

    Ok(OscPacket::Bundle(OscBundle {
        timetag: time_tag,
        content: bundle,
    }))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => {
            pad_cursor(cursor);
            String::from_utf8(str_buf)
                .map_err(|e| OscError::StringError(e))
                .map(|s| s.trim_matches(0u8 as char).to_string())
        }
        Err(e) => Err(OscError::ReadError(e)),
    }
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>,
                 raw_type_tags: String)
                 -> OscResult<Vec<OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
                                            .skip(1)
                                            .map(|c| c as char)
                                            .collect();
    let mut args: Vec<OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        match read_osc_arg(cursor, tag) {
            Ok(arg) => {
                args.push(arg);
            }
            Err(e) => return Err(e),
        }
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> OscResult<OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
                  .map(|f| OscType::Float(f))
                  .map_err(|e| OscError::ByteOrderError(e))
        }
        'd' => {
            cursor.read_f64::<BigEndian>()
                  .map(|d| OscType::Double(d))
                  .map_err(|e| OscError::ByteOrderError(e))
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
                  .map(|i| OscType::Int(i))
                  .map_err(|e| OscError::ByteOrderError(e))
        }
        'h' => {
            cursor.read_i64::<BigEndian>()
                  .map(|l| OscType::Long(l))
                  .map_err(|e| OscError::ByteOrderError(e))
        }
        's' => {
            read_osc_string(cursor).map(|s| OscType::String(s))
        }
        't' => {
            // http://opensoundcontrol.org/node/3/#timetags
            read_time_tag(cursor)
        }
        'b' => {
            match cursor.read_u32::<BigEndian>() {
                Ok(size) => {
                    let mut buf: Vec<u8> = Vec::with_capacity(size as usize);
                    match cursor.take(size as u64).read(&mut buf) {
                        Ok(blob_size) => Ok(OscType::Blob(buf)),
                        Err(e) => Err(OscError::ReadError(e)),
                    }
                }
                // TODO: use correct error type
                Err(e) => return Err(OscError::BadBundle),
            }
        }
        _ => Err(OscError::BadArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> OscResult<OscType> {
    match cursor.read_u32::<BigEndian>() {
        Ok(date) => {
            match cursor.read_u32::<BigEndian>() {
                Ok(frac) => Ok(OscType::Time(date, frac)),
                Err(e) => Err(OscError::ByteOrderError(e)),
            }
        }
        Err(e) => Err(OscError::ByteOrderError(e)),
    }
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    cursor.set_position(utils::pad(pos));
}
<commit_msg>Rustfmt<commit_after>use types::{OscPacket, OscType, OscResult, OscMessage, OscBundle};
use errors::OscError;
use utils;

use std::io;
use std::io::{Read, BufRead};

use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8]) -> OscResult<OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(OscError::BadPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8]) -> OscResult<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let addr: String = try!(read_osc_string(&mut cursor));
    let type_tags: String = try!(read_osc_string(&mut cursor));

    if type_tags.len() > 1 {
        let args: Vec<OscType> = try!(read_osc_args(&mut cursor, type_tags));

        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: Some(args),
        }))
    } else {
        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: None,
        }))
    }
}

fn decode_bundle(msg: &[u8]) -> OscResult<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let b = try!(read_osc_string(&mut cursor));
    if b != "bundle" {
        return Err(OscError::BadBundle);
    }

    let time_tag = try!(read_time_tag(&mut cursor));
    let mut bundle: Vec<OscPacket> = Vec::new();
    let size: usize = try!(cursor.read_u32::<BigEndian>()
                                 .map_err(OscError::ByteOrderError)) as usize;
    let mut buf: Vec<u8> = Vec::new();
    let cnt: usize = try!(cursor.take(size as u64)
                                .read_to_end(&mut buf)
                                .map_err(OscError::ReadError));
    if cnt == size {
        try!(decode(&mut buf).map(|p| bundle.push(p)));
    } else {
        return Err(OscError::BadBundle);
    }

    Ok(OscPacket::Bundle(OscBundle {
        timetag: time_tag,
        content: bundle,
    }))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => {
            pad_cursor(cursor);
            String::from_utf8(str_buf)
                .map_err(|e| OscError::StringError(e))
                .map(|s| s.trim_matches(0u8 as char).to_string())
        }
        Err(e) => Err(OscError::ReadError(e)),
    }
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>, raw_type_tags: String) -> OscResult<Vec<OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
                                            .skip(1)
                                            .map(|c| c as char)
                                            .collect();
    let mut args: Vec<OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        match read_osc_arg(cursor, tag) {
            Ok(arg) => {
                args.push(arg);
            }
            Err(e) => return Err(e),
        }
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> OscResult<OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
                  .map(|f| OscType::Float(f))
                  .map_err(|e| OscError::ByteOrderError(e))
        }
        'd' => {
            cursor.read_f64::<BigEndian>()
                  .map(|d| OscType::Double(d))
                  .map_err(|e| OscError::ByteOrderError(e))
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
                  .map(|i| OscType::Int(i))
                  .map_err(|e| OscError::ByteOrderError(e))
        }
        'h' => {
            cursor.read_i64::<BigEndian>()
                  .map(|l| OscType::Long(l))
                  .map_err(|e| OscError::ByteOrderError(e))
        }
        's' => {
            read_osc_string(cursor).map(|s| OscType::String(s))
        }
        't' => {
            // http://opensoundcontrol.org/node/3/#timetags
            read_time_tag(cursor)
        }
        'b' => {
            match cursor.read_u32::<BigEndian>() {
                Ok(size) => {
                    let mut buf: Vec<u8> = Vec::with_capacity(size as usize);
                    match cursor.take(size as u64).read(&mut buf) {
                        Ok(blob_size) => Ok(OscType::Blob(buf)),
                        Err(e) => Err(OscError::ReadError(e)),
                    }
                }
                // TODO: use correct error type
                Err(e) => return Err(OscError::BadBundle),
            }
        }
        _ => Err(OscError::BadArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> OscResult<OscType> {
    match cursor.read_u32::<BigEndian>() {
        Ok(date) => {
            match cursor.read_u32::<BigEndian>() {
                Ok(frac) => Ok(OscType::Time(date, frac)),
                Err(e) => Err(OscError::ByteOrderError(e)),
            }
        }
        Err(e) => Err(OscError::ByteOrderError(e)),
    }
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    cursor.set_position(utils::pad(pos));
}
<|endoftext|>


<commit_before>use std;
use std::collections::HashMap;
use std::sync::Arc;
use parking_lot::RwLock;
use bincode::{SizeLimit, serde as bincode};
use serde;

use bifrost_hasher::{hash_str, hash_bytes};
use membership::client::{Client as MembershipClient, Member};
use dht::weights::DEFAULT_SERVICE_ID;
use dht::weights::client::{SMClient as WeightSMClient};
use raft::client::{RaftClient, SubscriptionError};
use std::cmp::max;

pub mod weights;

pub static DEFAULT_NODE_LIST_SIZE: f64 = 2048f64;

pub enum Action {
    Joined,
    Left,
}

struct Node {
    start: u64,
    server: u64,
}

struct LookupTables {
    nodes: Vec<Node>,
    addrs: HashMap<u64, String>
}

pub struct DHT {
    tables: RwLock<LookupTables>,
    membership: Arc<MembershipClient>,
    weight_sm_client: WeightSMClient,
    group_name: String,
    watchers: RwLock<Vec<Box<Fn(&Member, &Action, &LookupTables, &Vec<Node>) + Send + Sync>>>
}

impl DHT {
    pub fn new(group: &String, raft_client: &Arc<RaftClient>) -> Option<Arc<DHT>>  {
        let membership = Arc::new(MembershipClient::new(raft_client));
        let dht = Arc::new(DHT {
            tables: RwLock::new(LookupTables {
                nodes: Vec::new(),
                addrs: HashMap::new()
            }),
            membership: membership.clone(),
            weight_sm_client: WeightSMClient::new(DEFAULT_SERVICE_ID, &raft_client),
            group_name: group.clone(),
            watchers: RwLock::new(Vec::new())
        });
        {
            let dht = dht.clone();
            let res = membership.on_group_member_joined(move |r| {
                if let Ok(member) = r { dht.server_joined(member); }
            }, group);
            if let Ok(Ok(_)) = res {} else {return None;}
        }
        {
            let dht = dht.clone();
            let res = membership.on_group_member_online(move |r| {
                if let Ok(member) = r { dht.server_joined(member) }
            }, group);
            if let Ok(Ok(_)) = res {} else {return None;}
        }
        {
            let dht = dht.clone();
            let res = membership.on_group_member_left(move |r| {
                if let Ok(member) = r { dht.server_left(member) }
            }, group);
            if let Ok(Ok(_)) = res {} else {return None;}
        }
        {
            let dht = dht.clone();
            let res = membership.on_group_member_offline(move |r| {
                if let Ok(member) = r { dht.server_left(member) }
            }, group);
            if let Ok(Ok(_)) = res {} else {return None;}
        }
        if !dht.init_table() {return None;}
        return Some(dht);
    }
    pub fn get_server(&self, hash: u64) -> Option<String> {
        let lookup_table = self.tables.read();
        let nodes = &lookup_table.nodes;
        let len = nodes.len();
        if len == 0 {return None;}
        let first_node = nodes.first().unwrap();
        let last_ndoe = nodes.last().unwrap();
        if hash < first_node.start {return Some(lookup_table.addrs.get(&first_node.server).unwrap().clone())}
        if hash >= last_ndoe.start {return Some(lookup_table.addrs.get(&last_ndoe.server).unwrap().clone())}
        let mut low = 0;
        let mut high = len - 1;
        while low < high {
            let mid = low + (high - low) / 2;
            let curr_node = &nodes[mid];
            let next_node = &nodes[mid + 1];
            if hash >= curr_node.start && hash < next_node.start {
                return Some(lookup_table.addrs.get(&curr_node.server).unwrap().clone());
            } else if hash < curr_node.start {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        None
    }
    pub fn get_server_by_string(&self, string: &String) -> Option<String> {
        self.get_server(hash_str(string))
    }
    pub fn get_server_by<T>(&self, obj: &T) -> Option<String> where T: serde::Serialize {
        self.get_server(hash_bytes(serialize!(obj).as_slice()))
    }
    pub fn set_weight(&self, server_name: &String, weight: u64) -> bool {
        let group_id = hash_str(&self.group_name);
        let server_id = hash_str(server_name);
        if let Ok(Ok(_)) = self.weight_sm_client.set_weight(group_id, server_id, weight) { true } else { false }
    }
    pub fn watch_all_actions<F>(&self, f: F)
        where F: Fn(&Member, &Action, &LookupTables, &Vec<Node>) + 'static + Send + Sync {
        let mut watchers = self.watchers.write();
        watchers.push(Box::new(f));
    }
    pub fn watch_server_nodes_range_changed<F>(&self, server: &String, f: F)
        // return ranges [...,...)
        where F: Fn(Vec<(u64, u64)>) + 'static + Send + Sync {
        let server_id = hash_str(server);
        let wrapper = move |
            _: &Member,_: &Action,
            lookup_table: &LookupTables, _: &Vec<Node>| {
            let nodes = &lookup_table.nodes;
            let node_len = nodes.len();
            let mut ranges: Vec<(u64, u64)> = Vec::new();
            for ni in 0..node_len {
                let node = &nodes[ni];
                if node.server == server_id {
                    ranges.push((node.start, if ni == node_len - 1 {
                        std::u64::MAX
                    } else {
                        nodes[ni + 1].start
                    }));
                }
            }
            f(ranges)
        };
    }

    fn init_table(&self) -> bool {
        if let Ok(Ok(members)) = self.membership.group_members(&self.group_name, true) {
            let group_id = hash_str(&self.group_name);
            if let Ok(Ok(Some(weights))) = self.weight_sm_client.get_weights(group_id) {
                if let Some(min_weight) = weights.values().min() {
                    let mut factors: HashMap<u64, f64> = HashMap::new();
                    let min_weight = *min_weight as f64;
                    for (k, w) in weights.iter() {factors.insert(*k, *w as f64 / min_weight);}
                    let factor_sum: f64 = factors.values().sum();
                    let nodes_size = if factor_sum > DEFAULT_NODE_LIST_SIZE {factor_sum} else {DEFAULT_NODE_LIST_SIZE};
                    let factor_scale = nodes_size / factor_sum;
                    let mut lookup_table = self.tables.write();
                    for member in members.iter() {lookup_table.addrs.insert(member.id, member.address.clone());}
                    for (k, f) in factors.iter() {
                        let weight = (*f * factor_scale) as u64;
                        for i in 0..weight {
                            let node_key = format!("{}_{}", k, i);
                            let hash = hash_str(&node_key);
                            lookup_table.nodes.push(Node{
                                start: hash, server: *k
                            });
                        }
                    };
                    lookup_table.nodes.sort_by(|n1, n2| n1.start.cmp(&n2.start));
                    return true;
                }
            }
        }
        return false;
    }
    fn server_joined(&self, member: Member) {
        self.init_table();
    }
    fn server_left(&self, member: Member) {
        self.init_table();
    }
}<commit_msg>link watcher events<commit_after>use std;
use std::collections::HashMap;
use std::sync::Arc;
use parking_lot::{RwLock, RwLockWriteGuard};
use bincode::{SizeLimit, serde as bincode};
use serde;

use bifrost_hasher::{hash_str, hash_bytes};
use membership::client::{Client as MembershipClient, Member};
use dht::weights::DEFAULT_SERVICE_ID;
use dht::weights::client::{SMClient as WeightSMClient};
use raft::client::{RaftClient, SubscriptionError};
use std::cmp::max;

pub mod weights;

pub static DEFAULT_NODE_LIST_SIZE: f64 = 2048f64;

pub enum Action {
    Joined,
    Left,
}

#[derive(Clone)]
struct Node {
    start: u64,
    server: u64,
}

struct LookupTables {
    nodes: Vec<Node>,
    addrs: HashMap<u64, String>
}

pub struct DHT {
    tables: RwLock<LookupTables>,
    membership: Arc<MembershipClient>,
    weight_sm_client: WeightSMClient,
    group_name: String,
    watchers: RwLock<Vec<Box<Fn(&Member, &Action, &RwLockWriteGuard<LookupTables>, &Vec<Node>) + Send + Sync>>>
}

impl DHT {
    pub fn new(group: &String, raft_client: &Arc<RaftClient>) -> Option<Arc<DHT>>  {
        let membership = Arc::new(MembershipClient::new(raft_client));
        let dht = Arc::new(DHT {
            tables: RwLock::new(LookupTables {
                nodes: Vec::new(),
                addrs: HashMap::new()
            }),
            membership: membership.clone(),
            weight_sm_client: WeightSMClient::new(DEFAULT_SERVICE_ID, &raft_client),
            group_name: group.clone(),
            watchers: RwLock::new(Vec::new())
        });
        {
            let dht = dht.clone();
            let res = membership.on_group_member_joined(move |r| {
                if let Ok(member) = r { dht.server_joined(member); }
            }, group);
            if let Ok(Ok(_)) = res {} else {return None;}
        }
        {
            let dht = dht.clone();
            let res = membership.on_group_member_online(move |r| {
                if let Ok(member) = r { dht.server_joined(member) }
            }, group);
            if let Ok(Ok(_)) = res {} else {return None;}
        }
        {
            let dht = dht.clone();
            let res = membership.on_group_member_left(move |r| {
                if let Ok(member) = r { dht.server_left(member) }
            }, group);
            if let Ok(Ok(_)) = res {} else {return None;}
        }
        {
            let dht = dht.clone();
            let res = membership.on_group_member_offline(move |r| {
                if let Ok(member) = r { dht.server_left(member) }
            }, group);
            if let Ok(Ok(_)) = res {} else {return None;}
        }
        if !dht.init_table(&mut dht.tables.write()) {return None;}
        return Some(dht);
    }
    pub fn get_server(&self, hash: u64) -> Option<String> {
        let lookup_table = self.tables.read();
        let nodes = &lookup_table.nodes;
        let len = nodes.len();
        if len == 0 {return None;}
        let first_node = nodes.first().unwrap();
        let last_ndoe = nodes.last().unwrap();
        if hash < first_node.start {return Some(lookup_table.addrs.get(&first_node.server).unwrap().clone())}
        if hash >= last_ndoe.start {return Some(lookup_table.addrs.get(&last_ndoe.server).unwrap().clone())}
        let mut low = 0;
        let mut high = len - 1;
        while low < high {
            let mid = low + (high - low) / 2;
            let curr_node = &nodes[mid];
            let next_node = &nodes[mid + 1];
            if hash >= curr_node.start && hash < next_node.start {
                return Some(lookup_table.addrs.get(&curr_node.server).unwrap().clone());
            } else if hash < curr_node.start {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        None
    }
    pub fn get_server_by_string(&self, string: &String) -> Option<String> {
        self.get_server(hash_str(string))
    }
    pub fn get_server_by<T>(&self, obj: &T) -> Option<String> where T: serde::Serialize {
        self.get_server(hash_bytes(serialize!(obj).as_slice()))
    }
    pub fn set_weight(&self, server_name: &String, weight: u64) -> bool {
        let group_id = hash_str(&self.group_name);
        let server_id = hash_str(server_name);
        if let Ok(Ok(_)) = self.weight_sm_client.set_weight(group_id, server_id, weight) { true } else { false }
    }
    pub fn watch_all_actions<F>(&self, f: F)
        where F: Fn(&Member, &Action, &RwLockWriteGuard<LookupTables>, &Vec<Node>) + 'static + Send + Sync {
        let mut watchers = self.watchers.write();
        watchers.push(Box::new(f));
    }
    pub fn watch_server_nodes_range_changed<F>(&self, server: &String, f: F)
        // return ranges [...,...)
        where F: Fn(Vec<(u64, u64)>) + 'static + Send + Sync {
        let server_id = hash_str(server);
        let wrapper = move |
            _: &Member,_: &Action,
            lookup_table: &RwLockWriteGuard<LookupTables>, _: &Vec<Node>| {
            let nodes = &lookup_table.nodes;
            let node_len = nodes.len();
            let mut ranges: Vec<(u64, u64)> = Vec::new();
            for ni in 0..node_len {
                let node = &nodes[ni];
                if node.server == server_id {
                    ranges.push((node.start, if ni == node_len - 1 {
                        std::u64::MAX
                    } else {
                        nodes[ni + 1].start
                    }));
                }
            }
            f(ranges)
        };
        self.watch_all_actions(wrapper);
    }

    fn init_table(&self, lookup_table: &mut RwLockWriteGuard<LookupTables>) -> bool {
        if let Ok(Ok(members)) = self.membership.group_members(&self.group_name, true) {
            let group_id = hash_str(&self.group_name);
            if let Ok(Ok(Some(weights))) = self.weight_sm_client.get_weights(group_id) {
                if let Some(min_weight) = weights.values().min() {
                    let mut factors: HashMap<u64, f64> = HashMap::new();
                    let min_weight = *min_weight as f64;
                    for (k, w) in weights.iter() {factors.insert(*k, *w as f64 / min_weight);}
                    let factor_sum: f64 = factors.values().sum();
                    let nodes_size = if factor_sum > DEFAULT_NODE_LIST_SIZE {factor_sum} else {DEFAULT_NODE_LIST_SIZE};
                    let factor_scale = nodes_size / factor_sum;
                    for member in members.iter() {lookup_table.addrs.insert(member.id, member.address.clone());}
                    for (k, f) in factors.iter() {
                        let weight = (*f * factor_scale) as u64;
                        for i in 0..weight {
                            let node_key = format!("{}_{}", k, i);
                            let hash = hash_str(&node_key);
                            lookup_table.nodes.push(Node{
                                start: hash, server: *k
                            });
                        }
                    };
                    lookup_table.nodes.sort_by(|n1, n2| n1.start.cmp(&n2.start));
                    return true;
                }
            }
        }
        return false;
    }
    fn server_joined(&self, member: Member) {
        self.server_changed(member, Action::Joined);
    }
    fn server_left(&self, member: Member) {
        self.server_changed(member, Action::Left);
    }
    fn server_changed(&self, member: Member, action: Action) {
        let mut lookup_table = self.tables.write();
        let watchers = self.watchers.read();
        let old_nodes = lookup_table.nodes.clone();
        self.init_table(&mut lookup_table);
        for watch in watchers.iter() {
            watch(&member, &action, &lookup_table, &old_nodes);
        }
    }
}<|endoftext|>