<commit_before>use crate::request::ToParams;
use crate::errors::*;

use std::str::FromStr;

#[derive(Debug)]
pub struct AppId(String);
#[derive(Debug)]
pub struct AppKey(String);
#[derive(Debug)]
pub struct UserKey(String);
#[derive(Debug)]
pub struct OAuthToken(String);

// These trait impls provide a way to reference our types as &str
impl AsRef<str> for AppId {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

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

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

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

// These trait impls provide a way to &str#parse() our Application type
impl FromStr for AppId {
    type Err = Error;

    fn from_str(s: &str) -> Result<AppId> {
        Ok(AppId(s.into()))
    }
}

impl FromStr for AppKey {
    type Err = Error;

    fn from_str(s: &str) -> Result<AppKey> {
        Ok(AppKey(s.into()))
    }
}

impl FromStr for UserKey {
    type Err = Error;

    fn from_str(s: &str) -> Result<UserKey> {
        Ok(UserKey(s.into()))
    }
}

impl FromStr for OAuthToken {
    type Err = Error;

    fn from_str(s: &str) -> Result<OAuthToken> {
        Ok(OAuthToken(s.into()))
    }
}

// These trait impls are similar to FromStr (but are infallible)
impl<'a> From<&'a str> for AppId where Self: FromStr {
    fn from(s: &'a str) -> AppId {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for AppKey where Self: FromStr {
    fn from(s: &'a str) -> AppKey {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for UserKey where Self: FromStr {
    fn from(s: &'a str) -> UserKey {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for OAuthToken where Self: FromStr {
    fn from(s: &'a str) -> OAuthToken {
        s.parse().unwrap()
    }
}

// These trait impls take ownership of a given String and also provide Into<AppId> for String
impl From<String> for AppId {
    fn from(s: String) -> AppId {
        AppId(s)
    }
}

impl From<String> for AppKey {
    fn from(s: String) -> AppKey {
        AppKey(s)
    }
}

impl From<String> for UserKey {
    fn from(s: String) -> UserKey {
        UserKey(s)
    }
}

impl From<String> for OAuthToken {
    fn from(s: String) -> OAuthToken {
        OAuthToken(s)
    }
}

#[derive(Debug)]
pub enum Application {
    AppId(AppId, Option<AppKey>),
    UserKey(UserKey),
    OAuthToken(OAuthToken)
}

// These trait impls build an Application variant out of its required types
impl Into<Application> for AppId {
    fn into(self) -> Application {
        Application::AppId(self, None)
    }
}

impl Into<Application> for (AppId, AppKey) {
    fn into(self) -> Application {
        Application::AppId(self.0, Some(self.1))
    }
}

impl Into<Application> for UserKey {
    fn into(self) -> Application {
        Application::UserKey(self)
    }
}

impl Into<Application> for OAuthToken {
    fn into(self) -> Application {
        Application::OAuthToken(self)
    }
}

impl Application {
    /// Creates a new `Application` from an `AppId`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_app_id("my_app_id");
    /// ```
    pub fn from_app_id<T: Into<AppId>>(app_id: T) -> Self {
        Application::AppId(app_id.into(), None)
    }

    /// Creates a new `Application` from an `AppId` and an `AppKey`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_app_id_and_key("my_app_id", "my_app_key");
    /// ```
    pub fn from_app_id_and_key<T: Into<AppId>, U: Into<AppKey>>(app_id: T, app_key: U) -> Self {
        Application::AppId(app_id.into(), Some(app_key.into()))
    }

    /// Creates a new `Application` from a `UserKey`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_user_key("my_user_key");
    /// ```
    pub fn from_user_key<T: Into<UserKey>>(user_key: T) -> Self {
        Application::UserKey(user_key.into())
    }

    /// Creates a new `Application` from an `AppId`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_oauth_token("my_token");
    /// ```
    pub fn from_oauth_token<T: Into<OAuthToken>>(token: T) -> Self {
        Application::OAuthToken(token.into())
    }
}

impl ToParams for Application {
    fn to_params(&self) -> Vec<(&str, &str)>{
        use self::Application::*;

        let mut v = Vec::<(&str, &str)>::with_capacity(2);
        match self {
            AppId(app_id, None) => {
                v.push(("app_id", app_id.as_ref()));
            },
            AppId(app_id, Some(app_key)) => {
                v.push(("app_id", app_id.as_ref()));
                v.push(("app_key", app_key.as_ref()));
            },
            UserKey(user_key) => v.push(("user_key", user_key.as_ref())),
            OAuthToken(token) => v.push(("access_token", token.as_ref())),
        };

        v
    }
}

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

    #[test]
    fn transforms_app_id_into_params() {
        let app_id = "my_app_id";
        let app = Application::from_app_id(app_id);

        let result = app.to_params();

        let expected = vec![("app_id", app_id)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_app_id_and_key_into_params() {
        let app_id = "my_app_id";
        let key = "my_key";
        let app = Application::from_app_id_and_key(app_id, key);

        let result = app.to_params();

        let expected = vec![("app_id", app_id), ("app_key", key)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_user_key_into_params() {
        let user_key = "my_user_key";
        let app = Application::from_user_key(user_key);

        let result = app.to_params();

        let expected = vec![("user_key", user_key)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_oauth_token_into_params() {
        let oauth_token = "my_token";
        let app = Application::from_oauth_token(oauth_token);

        let result = app.to_params();

        let expected = vec![("access_token", oauth_token)];
        assert_eq!(expected, result);
    }
}
<commit_msg>application: fix description of from_oauth_token()<commit_after>use crate::request::ToParams;
use crate::errors::*;

use std::str::FromStr;

#[derive(Debug)]
pub struct AppId(String);
#[derive(Debug)]
pub struct AppKey(String);
#[derive(Debug)]
pub struct UserKey(String);
#[derive(Debug)]
pub struct OAuthToken(String);

// These trait impls provide a way to reference our types as &str
impl AsRef<str> for AppId {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

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

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

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

// These trait impls provide a way to &str#parse() our Application type
impl FromStr for AppId {
    type Err = Error;

    fn from_str(s: &str) -> Result<AppId> {
        Ok(AppId(s.into()))
    }
}

impl FromStr for AppKey {
    type Err = Error;

    fn from_str(s: &str) -> Result<AppKey> {
        Ok(AppKey(s.into()))
    }
}

impl FromStr for UserKey {
    type Err = Error;

    fn from_str(s: &str) -> Result<UserKey> {
        Ok(UserKey(s.into()))
    }
}

impl FromStr for OAuthToken {
    type Err = Error;

    fn from_str(s: &str) -> Result<OAuthToken> {
        Ok(OAuthToken(s.into()))
    }
}

// These trait impls are similar to FromStr (but are infallible)
impl<'a> From<&'a str> for AppId where Self: FromStr {
    fn from(s: &'a str) -> AppId {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for AppKey where Self: FromStr {
    fn from(s: &'a str) -> AppKey {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for UserKey where Self: FromStr {
    fn from(s: &'a str) -> UserKey {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for OAuthToken where Self: FromStr {
    fn from(s: &'a str) -> OAuthToken {
        s.parse().unwrap()
    }
}

// These trait impls take ownership of a given String and also provide Into<AppId> for String
impl From<String> for AppId {
    fn from(s: String) -> AppId {
        AppId(s)
    }
}

impl From<String> for AppKey {
    fn from(s: String) -> AppKey {
        AppKey(s)
    }
}

impl From<String> for UserKey {
    fn from(s: String) -> UserKey {
        UserKey(s)
    }
}

impl From<String> for OAuthToken {
    fn from(s: String) -> OAuthToken {
        OAuthToken(s)
    }
}

#[derive(Debug)]
pub enum Application {
    AppId(AppId, Option<AppKey>),
    UserKey(UserKey),
    OAuthToken(OAuthToken)
}

// These trait impls build an Application variant out of its required types
impl Into<Application> for AppId {
    fn into(self) -> Application {
        Application::AppId(self, None)
    }
}

impl Into<Application> for (AppId, AppKey) {
    fn into(self) -> Application {
        Application::AppId(self.0, Some(self.1))
    }
}

impl Into<Application> for UserKey {
    fn into(self) -> Application {
        Application::UserKey(self)
    }
}

impl Into<Application> for OAuthToken {
    fn into(self) -> Application {
        Application::OAuthToken(self)
    }
}

impl Application {
    /// Creates a new `Application` from an `AppId`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_app_id("my_app_id");
    /// ```
    pub fn from_app_id<T: Into<AppId>>(app_id: T) -> Self {
        Application::AppId(app_id.into(), None)
    }

    /// Creates a new `Application` from an `AppId` and an `AppKey`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_app_id_and_key("my_app_id", "my_app_key");
    /// ```
    pub fn from_app_id_and_key<T: Into<AppId>, U: Into<AppKey>>(app_id: T, app_key: U) -> Self {
        Application::AppId(app_id.into(), Some(app_key.into()))
    }

    /// Creates a new `Application` from a `UserKey`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_user_key("my_user_key");
    /// ```
    pub fn from_user_key<T: Into<UserKey>>(user_key: T) -> Self {
        Application::UserKey(user_key.into())
    }

    /// Creates a new `Application` from an `OAuthToken`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_oauth_token("my_token");
    /// ```
    pub fn from_oauth_token<T: Into<OAuthToken>>(token: T) -> Self {
        Application::OAuthToken(token.into())
    }
}

impl ToParams for Application {
    fn to_params(&self) -> Vec<(&str, &str)>{
        use self::Application::*;

        let mut v = Vec::<(&str, &str)>::with_capacity(2);
        match self {
            AppId(app_id, None) => {
                v.push(("app_id", app_id.as_ref()));
            },
            AppId(app_id, Some(app_key)) => {
                v.push(("app_id", app_id.as_ref()));
                v.push(("app_key", app_key.as_ref()));
            },
            UserKey(user_key) => v.push(("user_key", user_key.as_ref())),
            OAuthToken(token) => v.push(("access_token", token.as_ref())),
        };

        v
    }
}

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

    #[test]
    fn transforms_app_id_into_params() {
        let app_id = "my_app_id";
        let app = Application::from_app_id(app_id);

        let result = app.to_params();

        let expected = vec![("app_id", app_id)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_app_id_and_key_into_params() {
        let app_id = "my_app_id";
        let key = "my_key";
        let app = Application::from_app_id_and_key(app_id, key);

        let result = app.to_params();

        let expected = vec![("app_id", app_id), ("app_key", key)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_user_key_into_params() {
        let user_key = "my_user_key";
        let app = Application::from_user_key(user_key);

        let result = app.to_params();

        let expected = vec![("user_key", user_key)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_oauth_token_into_params() {
        let oauth_token = "my_token";
        let app = Application::from_oauth_token(oauth_token);

        let result = app.to_params();

        let expected = vec![("access_token", oauth_token)];
        assert_eq!(expected, result);
    }
}
<|endoftext|>


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

use std::sync::{Mutex, Arc};

use futures;
use futures::Future;
use futures::stream;
use futures::sync::mpsc::UnboundedSender;
use tokio_core::net::TcpStream;

use core::core;
use core::core::hash::Hash;
use core::ser;
use conn::TimeoutConnection;
use msg::*;
use types::*;
use util::OneTime;

pub struct ProtocolV1 {
	conn: OneTime<TimeoutConnection>,

	expected_responses: Mutex<Vec<(Type, Hash)>>,
}

impl ProtocolV1 {
	pub fn new() -> ProtocolV1 {
		ProtocolV1 {
			conn: OneTime::new(),
			expected_responses: Mutex::new(vec![]),
		}
	}
}

impl Protocol for ProtocolV1 {
	/// Sets up the protocol reading, writing and closing logic.
	fn handle(&self,
	          conn: TcpStream,
	          adapter: Arc<NetAdapter>)
	          -> Box<Future<Item = (), Error = Error>> {

		let (conn, listener) = TimeoutConnection::listen(conn, move |sender, header, data| {
			let adapt = adapter.as_ref();
			handle_payload(adapt, sender, header, data)
		});

		self.conn.init(conn);

		listener
	}

	/// Bytes sent and received.
	fn transmitted_bytes(&self) -> (u64, u64) {
		self.conn.borrow().transmitted_bytes()
	}

	/// Sends a ping message to the remote peer. Will panic if handle has never
	/// been called on this protocol.
	fn send_ping(&self) -> Result<(), Error> {
		self.send_request(Type::Ping, Type::Pong, &Empty {}, None)
	}

	/// Serializes and sends a block to our remote peer
	fn send_block(&self, b: &core::Block) -> Result<(), Error> {
		self.send_msg(Type::Block, b)
	}

	/// Serializes and sends a transaction to our remote peer
	fn send_transaction(&self, tx: &core::Transaction) -> Result<(), Error> {
		self.send_msg(Type::Transaction, tx)
	}

	fn send_header_request(&self, locator: Vec<Hash>) -> Result<(), Error> {
		self.send_request(Type::GetHeaders,
		                  Type::Headers,
		                  &Locator { hashes: locator },
		                  None)
	}

	fn send_block_request(&self, h: Hash) -> Result<(), Error> {
		self.send_request(Type::GetBlock, Type::Block, &h, Some(h))
	}

	fn send_peer_request(&self, capab: Capabilities) -> Result<(), Error> {
		self.send_request(Type::GetPeerAddrs,
		                  Type::PeerAddrs,
		                  &GetPeerAddrs { capabilities: capab },
		                  None)
	}

	/// Close the connection to the remote peer
	fn close(&self) {
		// TODO some kind of shutdown signal
	}
}

impl ProtocolV1 {
	fn send_msg<W: ser::Writeable>(&self, t: Type, body: &W) -> Result<(), Error> {
		self.conn.borrow().send_msg(t, body)
	}

	fn send_request<W: ser::Writeable>(&self,
	                                   t: Type,
	                                   rt: Type,
	                                   body: &W,
	                                   expect_resp: Option<Hash>)
	                                   -> Result<(), Error> {
		self.conn.borrow().send_request(t, rt, body, expect_resp)
	}
}

fn handle_payload(adapter: &NetAdapter,
                  sender: UnboundedSender<Vec<u8>>,
                  header: MsgHeader,
                  buf: Vec<u8>)
                  -> Result<Option<Hash>, ser::Error> {
	match header.msg_type {
		Type::Ping => {
			let data = ser::ser_vec(&MsgHeader::new(Type::Pong, 0))?;
			sender.send(data);
			Ok(None)
		}
		Type::Pong => Ok(None),
		Type::Transaction => {
			let tx = ser::deserialize::<core::Transaction>(&mut &buf[..])?;
			adapter.transaction_received(tx);
			Ok(None)
		}
		Type::GetBlock => {
			let h = ser::deserialize::<Hash>(&mut &buf[..])?;
			let bo = adapter.get_block(h);
			if let Some(b) = bo {
				// serialize and send the block over
				let mut body_data = vec![];
				try!(ser::serialize(&mut body_data, &b));
				let mut data = vec![];
				try!(ser::serialize(&mut data,
				                    &MsgHeader::new(Type::Block, body_data.len() as u64)));
				data.append(&mut body_data);
				sender.send(data);
			}
			Ok(None)
		}
		Type::Block => {
			let b = ser::deserialize::<core::Block>(&mut &buf[..])?;
			let bh = b.hash();
			adapter.block_received(b);
			Ok(Some(bh))
		}
		Type::GetHeaders => {
			// load headers from the locator
			let loc = ser::deserialize::<Locator>(&mut &buf[..])?;

            if let Some(headers) = adapter.locate_headers(loc.hashes) {
                // serialize and send all the headers over
                let mut body_data = vec![];
                try!(ser::serialize(&mut body_data, &Headers { headers: headers }));
                let mut data = vec![];
                try!(ser::serialize(&mut data,
                                    &MsgHeader::new(Type::Headers, body_data.len() as u64)));
                data.append(&mut body_data);
                sender.send(data);
            }

			Ok(None)
		}
		Type::Headers => {
			let headers = ser::deserialize::<Headers>(&mut &buf[..])?;
			adapter.headers_received(headers.headers);
			Ok(None)
		}
		Type::GetPeerAddrs => {
			let get_peers = ser::deserialize::<GetPeerAddrs>(&mut &buf[..])?;

            if let Some(peer_addrs) = adapter.find_peer_addrs(get_peers.capabilities) {
                // serialize and send all the headers over
                let mut body_data = vec![];
                try!(ser::serialize(&mut body_data,
                                    &PeerAddrs {
                                        peers: peer_addrs.iter().map(|sa| SockAddr(*sa)).collect(),
                                    }));
                let mut data = vec![];
                try!(ser::serialize(&mut data,
                                    &MsgHeader::new(Type::PeerAddrs, body_data.len() as u64)));
                data.append(&mut body_data);
                sender.send(data);
            }

			Ok(None)
		}
		Type::PeerAddrs => {
			let peer_addrs = ser::deserialize::<PeerAddrs>(&mut &buf[..])?;
			adapter.peer_addrs_received(peer_addrs.peers.iter().map(|pa| pa.0).collect());
			Ok(None)
		}
		_ => {
			debug!("unknown message type {:?}", header.msg_type);
			Ok(None)
		}
	}
}
<commit_msg>Set Handling in V1<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::sync::{Mutex, Arc};

use futures;
use futures::Future;
use futures::stream;
use futures::sync::mpsc::UnboundedSender;
use tokio_core::net::TcpStream;

use core::core;
use core::core::hash::Hash;
use core::ser;
use conn::TimeoutConnection;
use msg::*;
use types::*;
use util::OneTime;

pub struct ProtocolV1 {
	conn: OneTime<TimeoutConnection>,

	expected_responses: Mutex<Vec<(Type, Hash)>>,
}

impl ProtocolV1 {
	pub fn new() -> ProtocolV1 {
		ProtocolV1 {
			conn: OneTime::new(),
			expected_responses: Mutex::new(vec![]),
		}
	}
}

impl Protocol for ProtocolV1 {
	/// Sets up the protocol reading, writing and closing logic.
	fn handle(&self,
	          conn: TcpStream,
	          adapter: Arc<NetAdapter>)
	          -> Box<Future<Item = (), Error = Error>> {

		let (conn, listener) = TimeoutConnection::listen(conn, move |sender, header, data| {
			let adapt = adapter.as_ref();
			handle_payload(adapt, sender, header, data).map_err(|_| ser::Error::CorruptedData)
		});

		self.conn.init(conn);

		listener
	}

	/// Bytes sent and received.
	fn transmitted_bytes(&self) -> (u64, u64) {
		self.conn.borrow().transmitted_bytes()
	}

	/// Sends a ping message to the remote peer. Will panic if handle has never
	/// been called on this protocol.
	fn send_ping(&self) -> Result<(), Error> {
		self.send_request(Type::Ping, Type::Pong, &Empty {}, None)
	}

	/// Serializes and sends a block to our remote peer
	fn send_block(&self, b: &core::Block) -> Result<(), Error> {
		self.send_msg(Type::Block, b)
	}

	/// Serializes and sends a transaction to our remote peer
	fn send_transaction(&self, tx: &core::Transaction) -> Result<(), Error> {
		self.send_msg(Type::Transaction, tx)
	}

	fn send_header_request(&self, locator: Vec<Hash>) -> Result<(), Error> {
		self.send_request(Type::GetHeaders,
		                  Type::Headers,
		                  &Locator { hashes: locator },
		                  None)
	}

	fn send_block_request(&self, h: Hash) -> Result<(), Error> {
		self.send_request(Type::GetBlock, Type::Block, &h, Some(h))
	}

	fn send_peer_request(&self, capab: Capabilities) -> Result<(), Error> {
		self.send_request(Type::GetPeerAddrs,
		                  Type::PeerAddrs,
		                  &GetPeerAddrs { capabilities: capab },
		                  None)
	}

	/// Close the connection to the remote peer
	fn close(&self) {
		// TODO some kind of shutdown signal
	}
}

impl ProtocolV1 {
	fn send_msg<W: ser::Writeable>(&self, t: Type, body: &W) -> Result<(), Error> {
		self.conn.borrow().send_msg(t, body)
	}

	fn send_request<W: ser::Writeable>(&self,
	                                   t: Type,
	                                   rt: Type,
	                                   body: &W,
	                                   expect_resp: Option<Hash>)
	                                   -> Result<(), Error> {
		self.conn.borrow().send_request(t, rt, body, expect_resp)
	}
}

fn handle_payload(adapter: &NetAdapter,
                  sender: UnboundedSender<Vec<u8>>,
                  header: MsgHeader,
                  buf: Vec<u8>)
                  -> Result<Option<Hash>, Error> {
	match header.msg_type {
		Type::Ping => {
			let data = ser::ser_vec(&MsgHeader::new(Type::Pong, 0))?;
			sender.send(data);
            Ok(None)
		}
		Type::Pong => Ok(None),
		Type::Transaction => {
			let tx = ser::deserialize::<core::Transaction>(&mut &buf[..])?;
			adapter.transaction_received(tx).and(Ok(None))

		}
		Type::GetBlock => {
			let h = ser::deserialize::<Hash>(&mut &buf[..])?;
			let bo = adapter.get_block(h);
			if let Some(b) = bo {
				// serialize and send the block over
				let mut body_data = vec![];
				try!(ser::serialize(&mut body_data, &b));
				let mut data = vec![];
				try!(ser::serialize(&mut data,
				                    &MsgHeader::new(Type::Block, body_data.len() as u64)));
				data.append(&mut body_data);
				sender.send(data);
			}
			Ok(None)
		}
		Type::Block => {
			let b = ser::deserialize::<core::Block>(&mut &buf[..])?;
			let bh = b.hash();
			adapter.block_received(b);
			Ok(Some(bh))
		}
		Type::GetHeaders => {
			// load headers from the locator
			let loc = ser::deserialize::<Locator>(&mut &buf[..])?;

            if let Some(headers) = adapter.locate_headers(loc.hashes) {
                // serialize and send all the headers over
                let mut body_data = vec![];
                try!(ser::serialize(&mut body_data, &Headers { headers: headers }));
                let mut data = vec![];
                try!(ser::serialize(&mut data,
                                    &MsgHeader::new(Type::Headers, body_data.len() as u64)));
                data.append(&mut body_data);
                sender.send(data);
            }

			Ok(None)
		}
		Type::Headers => {
			let headers = ser::deserialize::<Headers>(&mut &buf[..])?;
			adapter.headers_received(headers.headers).and(Ok(None))
		}
		Type::GetPeerAddrs => {
			let get_peers = ser::deserialize::<GetPeerAddrs>(&mut &buf[..])?;

            if let Some(peer_addrs) = adapter.find_peer_addrs(get_peers.capabilities) {
                // serialize and send all the headers over
                let mut body_data = vec![];
                try!(ser::serialize(&mut body_data,
                                    &PeerAddrs {
                                        peers: peer_addrs.iter().map(|sa| SockAddr(*sa)).collect(),
                                    }));
                let mut data = vec![];
                try!(ser::serialize(&mut data,
                                    &MsgHeader::new(Type::PeerAddrs, body_data.len() as u64)));
                data.append(&mut body_data);
                sender.send(data);
            }

			Ok(None)
		}
		Type::PeerAddrs => {
			let peer_addrs = ser::deserialize::<PeerAddrs>(&mut &buf[..])?;
			adapter.peer_addrs_received(peer_addrs.peers.iter().map(|pa| pa.0).collect()).map(|_| None)
		}
		_ => {
			debug!("unknown message type {:?}", header.msg_type);
			Ok(None)
		}
	}
}
<|endoftext|>


<commit_before>use super::*;

impl Editor {
    /// Go to next char
    pub fn next(&mut self) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() >= self.text.len() {
                self.text.push_back(VecDeque::new())
            }
            if self.y() < self.text.len() - 1 {
                self.cursor_mut().x = 0;
                self.cursor_mut().y += 1;
            }
        } else {
            self.cursor_mut().x += 1;
        }
    }

    /// Go to previous char
    pub fn previous(&mut self) {
        if self.x() == 0 {
            if self.y() > 0 {
                self.cursor_mut().y -= 1;
                self.cursor_mut().x = self.text[self.y()].len();
            }
        } else {
            self.cursor_mut().x -= 1;
        }
    }

    /// Go right
    pub fn right(&mut self, n: usize) {
        let x = self.x() + n;
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.x += n;

        if x > text[y].len() {
            curs.x = text[y].len();
        }
    }

    /// Go left
    pub fn left(&mut self, n: usize) {
        let x = self.x();
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        if n <= x {
            curs.x = x - n;
        } else {
            curs.x = 0;
        }

    }

    /// Go up
    pub fn up(&mut self, n: usize) {
        let y = self.y();
        let curs = self.cursor_mut();
        if n <= y {
            curs.y -= n;
        } else {
            curs.y = 0;
        }
    }

    /// Go down
    pub fn down(&mut self, n: usize) {
        let x = self.x();
        let y = self.y() + n;

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.y += n;

        if y >= text.len() {
            curs.y = text.len() - 1;
        }
    }
}
<commit_msg>Refactor into methods returning the position<commit_after>use super::*;

impl Editor {
    /// Get pos of next char
    pub fn next_pos(&mut self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get pos of previous char
    pub fn previous_pos(&mut self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y()].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    pub fn next(&mut self) {
        let (x, y) = self.next_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }
    pub fn previous(&mut self) {
        let (x, y) = self.previous_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Go right
    pub fn right(&mut self, n: usize) {
        let x = self.x() + n;
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.x += n;

        if x > text[y].len() {
            curs.x = text[y].len();
        }
    }

    /// Go left
    pub fn left(&mut self, n: usize) {
        let x = self.x();
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        if n <= x {
            curs.x = x - n;
        } else {
            curs.x = 0;
        }

    }

    /// Go up
    pub fn up(&mut self, n: usize) {
        let y = self.y();
        let curs = self.cursor_mut();
        if n <= y {
            curs.y -= n;
        } else {
            curs.y = 0;
        }
    }

    /// Go down
    pub fn down(&mut self, n: usize) {
        let x = self.x();
        let y = self.y() + n;

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.y += n;

        if y >= text.len() {
            curs.y = text.len() - 1;
        }
    }
}
<|endoftext|>


<commit_before>
use syn::*;
use quote::{ToTokens, Tokens};

use error::MacroError;
use super::*;

use ast_converters::*;

pub fn parse_com_lib_attribute(
    crate_name : &str,
    attr : &Attribute,
) -> Result<( guid::GUID, Vec<String> ), MacroError>
{
    let params = get_parameters( attr )
            .ok_or( "Bad parameters on com_library" )?;

    let ( libid_param, cls_params ) = params.split_first()
            .ok_or( "Not enough com_library parameters" )?;

    Ok( (
        parameter_to_guid(
            libid_param,
            crate_name,
            "",
            "LIBID" )?
            .ok_or( "Library must specify LIBID" )?,
        cls_params
            .into_iter()
            .map( |cls| match *cls {
                AttrParam::Word( ref w ) => Ok( format!( "{}", w ) ),
                _ => Err( "Bad interface" ),
            } ).collect::<Result<_,_>>()?
    ) )
}

pub fn parse_attr_tokens(
    attr_name: &str,
    attr_tokens: &str,
) -> Result< Attribute, MacroError >
{
    let attr_rendered = format!( "#[{}{}]", attr_name, attr_tokens );
    Ok( match syn::parse_outer_attr( &attr_rendered ) {
        Ok(t) => t,
        Err(_) => Err(
                format!( "Could not parse [{}] attribute", attr_name ) )?,
    } )
}

#[derive(PartialEq, Clone, Copy)]
pub enum InterfaceType { Trait, Struct }

pub type InterfaceData<'a> = (
    Ident,
    Vec< ( &'a Ident, &'a MethodSig ) >,
    InterfaceType
);

pub fn get_ident_and_fns(
    item : &Item
) -> Option< InterfaceData >
{
    match item.node {
        ItemKind::Impl( .., ref trait_ref, ref ty, ref items ) => {
            let ( _, struct_ident, items ) =
                    get_impl_data_raw( trait_ref, ty, items );
            Some( ( struct_ident, items, InterfaceType::Struct ) )
        },
        ItemKind::Trait( .., ref items ) => {

            let methods : Option< Vec< (&Ident, &MethodSig) > > = items
                    .into_iter()
                    .map( |i| get_trait_method( i ).map( |m| ( &i.ident, m ) ) )
                    .collect();

            match methods {
                Some( m ) => Some( ( item.ident.clone(), m, InterfaceType::Trait ) ),
                None => None
            }
        },
        _ => None
    }
}

pub type ImplData<'a> = (
    Option<Ident>,
    Ident,
    Vec< ( &'a Ident, &'a MethodSig ) >
);

pub fn get_impl_data(
    item : &Item
) -> Option< ImplData >
{
    if let ItemKind::Impl( .., ref trait_ref, ref ty, ref items ) = item.node {
        return Some( get_impl_data_raw( trait_ref, ty, items ) );
    }
    None
}

fn get_impl_data_raw<'a>(
    trait_ref : &'a Option<Path>,
    struct_ty : &'a Ty,
    items : &'a [ImplItem]
) -> ImplData<'a>
{

    let struct_ident = struct_ty.get_ident().unwrap();
    let trait_ident = match *trait_ref {
        Some( ref tr ) => tr.get_ident().ok(),
        None => None
    };

    let methods_opt : Option< Vec< (&Ident, &MethodSig) > > = items
            .into_iter()
            .map( |i| get_impl_method( i ).map( |m| ( &i.ident, m ) ) )
            .collect();
    let methods = methods_opt.unwrap_or_else( || vec![] );

    ( trait_ident, struct_ident, methods )
}

#[derive(PartialEq, Eq, Debug)]
pub enum AttrParam {
    Literal( syn::Lit ),
    Word( syn::Ident ),
}

pub fn iter_parameters(
    attr : &syn::Attribute
) -> Box< Iterator<Item = AttrParam > >
{
    match attr.value {

        // Attributes without parameter lists don't have params.
        syn::MetaItem::Word(..)
            | syn::MetaItem::NameValue(..) => Box::new( std::iter::empty() ),

        syn::MetaItem::List( _, ref l ) =>
            Box::new( l.to_owned().into_iter().map( |i| {

                match i {

                    syn::NestedMetaItem::MetaItem( mi ) =>

                            AttrParam::Word( match mi {
                                syn::MetaItem::Word( i )
                                    | syn::MetaItem::List( i, _ )
                                    | syn::MetaItem::NameValue( i, _ )
                                    => i,
                            } ),

                    syn::NestedMetaItem::Literal( l ) =>
                            AttrParam::Literal( l ),
                }
            } ) ),
    }
}

pub fn get_parameters(
    attr : &syn::Attribute
) -> Option< Vec< AttrParam > >
{
    Some( match attr.value {

        // Attributes without parameter lists don't have params.
        syn::MetaItem::Word(..)
            | syn::MetaItem::NameValue(..) => return None,

        syn::MetaItem::List( _, ref l ) =>
            l.to_owned().into_iter().map( |i| {

                match i {

                    syn::NestedMetaItem::MetaItem( mi ) =>

                            AttrParam::Word( match mi {
                                syn::MetaItem::Word( i )
                                    | syn::MetaItem::List( i, _ )
                                    | syn::MetaItem::NameValue( i, _ )
                                    => i,
                            } ),

                    syn::NestedMetaItem::Literal( l ) =>
                            AttrParam::Literal( l ),
                }
            } ).collect() ,
    } )
}

pub fn get_ty_ident(
    ty : &Ty
) -> Option<&Ident>
{
    match *ty {
        Ty::Path( _, ref p ) =>
            p.segments.last().map( |l| &l.ident ),
        _ => None
    }
}

pub fn get_impl_method(
    i : &ImplItem
) -> Option< &MethodSig >
{
    if let ImplItemKind::Method( ref method_sig, _ ) = i.node {
        return Some( method_sig );
    }
    None
}

pub fn get_trait_method(
    i : &TraitItem
) -> Option< &MethodSig >
{
    if let TraitItemKind::Method( ref method_sig, _ ) = i.node {
        return Some( method_sig );
    }
    None
}

const AUTO_GUID_BASE : guid::GUID = guid::GUID {
    data1: 0x4449_494C,
    data2: 0xDE1F,
    data3: 0x4525,
    data4: [ 0xB9, 0x57, 0x89, 0xD6, 0x0C, 0xE9, 0x34, 0x77 ]
};

pub fn parameter_to_guid(
    p : &AttrParam,
    crate_name : &str,
    item_name : &str,
    item_type : &str,
) -> Result< Option< guid::GUID >, String >
{
    if let AttrParam::Word( ref i ) = *p {
        return Ok( match i.as_ref() {
            "AUTO_GUID" =>
                Some( generate_guid( crate_name, item_name, item_type ) ),
            "NO_GUID" =>
                None,
            _ => return Err( format!( "Invalid GUID: {:?}", i ) ),
        } );
    }

    if let AttrParam::Literal( Lit::Str( ref s, _ ) ) = *p {
        return Ok( Some( guid::GUID::parse( s.as_str() )? ) );
    }

    Err( "GUID parameter must be literal string".to_owned() )
}

pub fn generate_guid(
    crate_name : &str,
    item_name : &str,
    item_type : &str,
) -> guid::GUID
{
    // Hash the name. The name will be hashed in a form similar to:
    // AUTO_GUID_BASE + "CLSID:random_rust_crate:FooBar"
    let mut hash = sha1::Sha1::new();
    hash.update( AUTO_GUID_BASE.as_bytes() );
    hash.update( item_type.as_bytes() );
    hash.update( b":" );
    hash.update( crate_name.as_bytes() );
    hash.update( b":" );
    hash.update( item_name.as_bytes() );

    let digest = hash.digest();
    let bytes = digest.bytes();

    // Set the GUID bytes according to RFC-4122, section 4.3.
    let time_low : u32
        = ( u32::from( bytes[0] ) << 24 )
        + ( u32::from( bytes[1] ) << 16 )
        + ( u32::from( bytes[2] ) << 8 )
        + u32::from( bytes[3] );
    let time_mid : u16
        = ( u16::from( bytes[4] ) << 8 )
        + ( u16::from( bytes[5] ) );
    let time_hi_and_version : u16
        = (
            (
                ( u16::from( bytes[6] ) << 8 ) + u16::from( bytes[7] )
            ) & 0x0fff
        ) | 0x3000;
    let clk_seq_hi_res : u8
        = ( bytes[8] & 0b0011_1111 ) | 0b0100_0000;
    let clk_seq_low : u8 = bytes[9];

    guid::GUID {
        data1: time_low,
        data2: time_mid,
        data3: time_hi_and_version,
        data4: [
            clk_seq_hi_res, clk_seq_low,
            bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15] ]
    }
}

pub fn ty_to_string( ty : &syn::Ty ) -> String
{
    let mut tokens = Tokens::new();
    ty.to_tokens( &mut tokens );
    tokens.to_string().replace( " ", "" ).replace( ",", ", " )
}

pub fn is_unit(
    tk : &Ty
) -> bool
{
    if let Ty::Tup( ref v ) = *tk {
        v.is_empty()
    } else {
        false
    }
}

pub fn unit_ty() -> Ty
{
    Ty::Tup( vec![] )
}

pub fn get_guid_tokens(
    g : &guid::GUID
) -> Tokens
{
    let d1 = g.data1;
    let d2 = g.data2;
    let d3 = g.data3;
    let d4_0 = g.data4[ 0 ];
    let d4_1 = g.data4[ 1 ];
    let d4_2 = g.data4[ 2 ];
    let d4_3 = g.data4[ 3 ];
    let d4_4 = g.data4[ 4 ];
    let d4_5 = g.data4[ 5 ];
    let d4_6 = g.data4[ 6 ];
    let d4_7 = g.data4[ 7 ];
    quote!(
        ::intercom::GUID {
            data1: #d1, data2: #d2, data3: #d3,
            data4: [ #d4_0, #d4_1, #d4_2, #d4_3, #d4_4, #d4_5, #d4_6, #d4_7 ]
        }
    )
}

/// Convert the Rust identifier from `snake_case` to `PascalCase`
pub fn pascal_case( input : &str ) -> String {

    // Allocate the output string. We'll never increase the amount of
    // characters so we can reserve string buffer using the input string length.
    let mut output = String::new();
    output.reserve( input.len() );

    // Process each character from the input.
    let mut capitalize = true;
    for c in input.chars() {

        // Check the capitalization requirement.
        if c == '_' {

            // Skip '_' but capitalize the following character.
            capitalize = true;

        } else if capitalize {

            // Capitalize. Add the uppercase characters.
            for c_up in c.to_uppercase() {
                output.push( c_up )
            }

            // No need to capitalize any more.
            capitalize = false;

        } else {

            // No need to capitalize. Just add the character as is.
            output.push( c );
        }

    }
    output
}

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

    /// Tests the `ty_to_string` by converting parameter to Ty and back to
    /// String to ensure they equal.
    fn test_ty( ty_str : &str ) {
        let ty = parse_type( ty_str ).unwrap();
        let as_string = ty_to_string( &ty );
        assert_eq!( ty_str, as_string );
    }

    #[test] fn path_to_test() { test_ty( "::path::Foo" ) }
    #[test] fn generics_to_test() { test_ty( "Result<Foo, Bar>" ) }
    #[test] fn unit_to_test() { test_ty( "()" ) }
}
<commit_msg>Remove dead code<commit_after>
use syn::*;
use quote::{ToTokens, Tokens};

use error::MacroError;
use super::*;

use ast_converters::*;

pub fn parse_attr_tokens(
    attr_name: &str,
    attr_tokens: &str,
) -> Result< Attribute, MacroError >
{
    let attr_rendered = format!( "#[{}{}]", attr_name, attr_tokens );
    Ok( match syn::parse_outer_attr( &attr_rendered ) {
        Ok(t) => t,
        Err(_) => Err(
                format!( "Could not parse [{}] attribute", attr_name ) )?,
    } )
}

#[derive(PartialEq, Clone, Copy)]
pub enum InterfaceType { Trait, Struct }

pub type InterfaceData<'a> = (
    Ident,
    Vec< ( &'a Ident, &'a MethodSig ) >,
    InterfaceType
);

pub fn get_ident_and_fns(
    item : &Item
) -> Option< InterfaceData >
{
    match item.node {
        ItemKind::Impl( .., ref trait_ref, ref ty, ref items ) => {
            let ( _, struct_ident, items ) =
                    get_impl_data_raw( trait_ref, ty, items );
            Some( ( struct_ident, items, InterfaceType::Struct ) )
        },
        ItemKind::Trait( .., ref items ) => {

            let methods : Option< Vec< (&Ident, &MethodSig) > > = items
                    .into_iter()
                    .map( |i| get_trait_method( i ).map( |m| ( &i.ident, m ) ) )
                    .collect();

            match methods {
                Some( m ) => Some( ( item.ident.clone(), m, InterfaceType::Trait ) ),
                None => None
            }
        },
        _ => None
    }
}

pub type ImplData<'a> = (
    Option<Ident>,
    Ident,
    Vec< ( &'a Ident, &'a MethodSig ) >
);

pub fn get_impl_data(
    item : &Item
) -> Option< ImplData >
{
    if let ItemKind::Impl( .., ref trait_ref, ref ty, ref items ) = item.node {
        return Some( get_impl_data_raw( trait_ref, ty, items ) );
    }
    None
}

fn get_impl_data_raw<'a>(
    trait_ref : &'a Option<Path>,
    struct_ty : &'a Ty,
    items : &'a [ImplItem]
) -> ImplData<'a>
{

    let struct_ident = struct_ty.get_ident().unwrap();
    let trait_ident = match *trait_ref {
        Some( ref tr ) => tr.get_ident().ok(),
        None => None
    };

    let methods_opt : Option< Vec< (&Ident, &MethodSig) > > = items
            .into_iter()
            .map( |i| get_impl_method( i ).map( |m| ( &i.ident, m ) ) )
            .collect();
    let methods = methods_opt.unwrap_or_else( || vec![] );

    ( trait_ident, struct_ident, methods )
}

#[derive(PartialEq, Eq, Debug)]
pub enum AttrParam {
    Literal( syn::Lit ),
    Word( syn::Ident ),
}

pub fn iter_parameters(
    attr : &syn::Attribute
) -> Box< Iterator<Item = AttrParam > >
{
    match attr.value {

        // Attributes without parameter lists don't have params.
        syn::MetaItem::Word(..)
            | syn::MetaItem::NameValue(..) => Box::new( std::iter::empty() ),

        syn::MetaItem::List( _, ref l ) =>
            Box::new( l.to_owned().into_iter().map( |i| {

                match i {

                    syn::NestedMetaItem::MetaItem( mi ) =>

                            AttrParam::Word( match mi {
                                syn::MetaItem::Word( i )
                                    | syn::MetaItem::List( i, _ )
                                    | syn::MetaItem::NameValue( i, _ )
                                    => i,
                            } ),

                    syn::NestedMetaItem::Literal( l ) =>
                            AttrParam::Literal( l ),
                }
            } ) ),
    }
}

pub fn get_ty_ident(
    ty : &Ty
) -> Option<&Ident>
{
    match *ty {
        Ty::Path( _, ref p ) =>
            p.segments.last().map( |l| &l.ident ),
        _ => None
    }
}

pub fn get_impl_method(
    i : &ImplItem
) -> Option< &MethodSig >
{
    if let ImplItemKind::Method( ref method_sig, _ ) = i.node {
        return Some( method_sig );
    }
    None
}

pub fn get_trait_method(
    i : &TraitItem
) -> Option< &MethodSig >
{
    if let TraitItemKind::Method( ref method_sig, _ ) = i.node {
        return Some( method_sig );
    }
    None
}

const AUTO_GUID_BASE : guid::GUID = guid::GUID {
    data1: 0x4449_494C,
    data2: 0xDE1F,
    data3: 0x4525,
    data4: [ 0xB9, 0x57, 0x89, 0xD6, 0x0C, 0xE9, 0x34, 0x77 ]
};

pub fn parameter_to_guid(
    p : &AttrParam,
    crate_name : &str,
    item_name : &str,
    item_type : &str,
) -> Result< Option< guid::GUID >, String >
{
    if let AttrParam::Word( ref i ) = *p {
        return Ok( match i.as_ref() {
            "AUTO_GUID" =>
                Some( generate_guid( crate_name, item_name, item_type ) ),
            "NO_GUID" =>
                None,
            _ => return Err( format!( "Invalid GUID: {:?}", i ) ),
        } );
    }

    if let AttrParam::Literal( Lit::Str( ref s, _ ) ) = *p {
        return Ok( Some( guid::GUID::parse( s.as_str() )? ) );
    }

    Err( "GUID parameter must be literal string".to_owned() )
}

pub fn generate_guid(
    crate_name : &str,
    item_name : &str,
    item_type : &str,
) -> guid::GUID
{
    // Hash the name. The name will be hashed in a form similar to:
    // AUTO_GUID_BASE + "CLSID:random_rust_crate:FooBar"
    let mut hash = sha1::Sha1::new();
    hash.update( AUTO_GUID_BASE.as_bytes() );
    hash.update( item_type.as_bytes() );
    hash.update( b":" );
    hash.update( crate_name.as_bytes() );
    hash.update( b":" );
    hash.update( item_name.as_bytes() );

    let digest = hash.digest();
    let bytes = digest.bytes();

    // Set the GUID bytes according to RFC-4122, section 4.3.
    let time_low : u32
        = ( u32::from( bytes[0] ) << 24 )
        + ( u32::from( bytes[1] ) << 16 )
        + ( u32::from( bytes[2] ) << 8 )
        + u32::from( bytes[3] );
    let time_mid : u16
        = ( u16::from( bytes[4] ) << 8 )
        + ( u16::from( bytes[5] ) );
    let time_hi_and_version : u16
        = (
            (
                ( u16::from( bytes[6] ) << 8 ) + u16::from( bytes[7] )
            ) & 0x0fff
        ) | 0x3000;
    let clk_seq_hi_res : u8
        = ( bytes[8] & 0b0011_1111 ) | 0b0100_0000;
    let clk_seq_low : u8 = bytes[9];

    guid::GUID {
        data1: time_low,
        data2: time_mid,
        data3: time_hi_and_version,
        data4: [
            clk_seq_hi_res, clk_seq_low,
            bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15] ]
    }
}

pub fn ty_to_string( ty : &syn::Ty ) -> String
{
    let mut tokens = Tokens::new();
    ty.to_tokens( &mut tokens );
    tokens.to_string().replace( " ", "" ).replace( ",", ", " )
}

pub fn is_unit(
    tk : &Ty
) -> bool
{
    if let Ty::Tup( ref v ) = *tk {
        v.is_empty()
    } else {
        false
    }
}

pub fn unit_ty() -> Ty
{
    Ty::Tup( vec![] )
}

pub fn get_guid_tokens(
    g : &guid::GUID
) -> Tokens
{
    let d1 = g.data1;
    let d2 = g.data2;
    let d3 = g.data3;
    let d4_0 = g.data4[ 0 ];
    let d4_1 = g.data4[ 1 ];
    let d4_2 = g.data4[ 2 ];
    let d4_3 = g.data4[ 3 ];
    let d4_4 = g.data4[ 4 ];
    let d4_5 = g.data4[ 5 ];
    let d4_6 = g.data4[ 6 ];
    let d4_7 = g.data4[ 7 ];
    quote!(
        ::intercom::GUID {
            data1: #d1, data2: #d2, data3: #d3,
            data4: [ #d4_0, #d4_1, #d4_2, #d4_3, #d4_4, #d4_5, #d4_6, #d4_7 ]
        }
    )
}

/// Convert the Rust identifier from `snake_case` to `PascalCase`
pub fn pascal_case( input : &str ) -> String {

    // Allocate the output string. We'll never increase the amount of
    // characters so we can reserve string buffer using the input string length.
    let mut output = String::new();
    output.reserve( input.len() );

    // Process each character from the input.
    let mut capitalize = true;
    for c in input.chars() {

        // Check the capitalization requirement.
        if c == '_' {

            // Skip '_' but capitalize the following character.
            capitalize = true;

        } else if capitalize {

            // Capitalize. Add the uppercase characters.
            for c_up in c.to_uppercase() {
                output.push( c_up )
            }

            // No need to capitalize any more.
            capitalize = false;

        } else {

            // No need to capitalize. Just add the character as is.
            output.push( c );
        }

    }
    output
}

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

    /// Tests the `ty_to_string` by converting parameter to Ty and back to
    /// String to ensure they equal.
    fn test_ty( ty_str : &str ) {
        let ty = parse_type( ty_str ).unwrap();
        let as_string = ty_to_string( &ty );
        assert_eq!( ty_str, as_string );
    }

    #[test] fn path_to_test() { test_ty( "::path::Foo" ) }
    #[test] fn generics_to_test() { test_ty( "Result<Foo, Bar>" ) }
    #[test] fn unit_to_test() { test_ty( "()" ) }
}
<|endoftext|>


<commit_before>use bit_set::BitSet;
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use futures::sync::{mpsc, oneshot};
use futures::Stream;
use futures::{Async, Future, Poll};
use std::cmp::min;
use std::fs;
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::sync::{Arc, Condvar, Mutex};
use tempfile::NamedTempFile;

use core::channel::{Channel, ChannelData, ChannelError, ChannelHeaders};
use core::session::Session;
use core::spotify_id::FileId;

const CHUNK_SIZE: usize = 0x20000;

pub enum AudioFile {
    Cached(fs::File),
    Streaming(AudioFileStreaming),
}

pub enum AudioFileOpen {
    Cached(Option<fs::File>),
    Streaming(AudioFileOpenStreaming),
}

pub struct AudioFileOpenStreaming {
    session: Session,
    data_rx: Option<ChannelData>,
    headers: ChannelHeaders,
    file_id: FileId,
    complete_tx: Option<oneshot::Sender<NamedTempFile>>,
}

pub struct AudioFileStreaming {
    read_file: fs::File,

    position: u64,
    seek: mpsc::UnboundedSender<u64>,

    shared: Arc<AudioFileShared>,
}

struct AudioFileShared {
    file_id: FileId,
    chunk_count: usize,
    cond: Condvar,
    bitmap: Mutex<BitSet>,
}

impl AudioFileOpenStreaming {
    fn finish(&mut self, size: usize) -> AudioFileStreaming {
        let chunk_count = (size + CHUNK_SIZE - 1) / CHUNK_SIZE;

        let shared = Arc::new(AudioFileShared {
            file_id: self.file_id,
            chunk_count: chunk_count,
            cond: Condvar::new(),
            bitmap: Mutex::new(BitSet::with_capacity(chunk_count)),
        });

        let mut write_file = NamedTempFile::new().unwrap();
        write_file.set_len(size as u64).unwrap();
        write_file.seek(SeekFrom::Start(0)).unwrap();

        let read_file = write_file.reopen().unwrap();

        let data_rx = self.data_rx.take().unwrap();
        let complete_tx = self.complete_tx.take().unwrap();
        let (seek_tx, seek_rx) = mpsc::unbounded();

        let fetcher = AudioFileFetch::new(
            self.session.clone(),
            shared.clone(),
            data_rx,
            write_file,
            seek_rx,
            complete_tx,
        );
        self.session.spawn(move |_| fetcher);

        AudioFileStreaming {
            read_file: read_file,

            position: 0,
            seek: seek_tx,

            shared: shared,
        }
    }
}

impl Future for AudioFileOpen {
    type Item = AudioFile;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<AudioFile, ChannelError> {
        match *self {
            AudioFileOpen::Streaming(ref mut open) => {
                let file = try_ready!(open.poll());
                Ok(Async::Ready(AudioFile::Streaming(file)))
            }
            AudioFileOpen::Cached(ref mut file) => {
                let file = file.take().unwrap();
                Ok(Async::Ready(AudioFile::Cached(file)))
            }
        }
    }
}

impl Future for AudioFileOpenStreaming {
    type Item = AudioFileStreaming;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<AudioFileStreaming, ChannelError> {
        loop {
            let (id, data) = try_ready!(self.headers.poll()).unwrap();

            if id == 0x3 {
                let size = BigEndian::read_u32(&data) as usize * 4;
                let file = self.finish(size);

                return Ok(Async::Ready(file));
            }
        }
    }
}

impl AudioFile {
    pub fn open(session: &Session, file_id: FileId) -> AudioFileOpen {
        let cache = session.cache().cloned();

        if let Some(file) = cache.as_ref().and_then(|cache| cache.file(file_id)) {
            debug!("File {} already in cache", file_id);
            return AudioFileOpen::Cached(Some(file));
        }

        debug!("Downloading file {}", file_id);

        let (complete_tx, complete_rx) = oneshot::channel();
        let (headers, data) = request_chunk(session, file_id, 0).split();

        let open = AudioFileOpenStreaming {
            session: session.clone(),
            file_id: file_id,

            headers: headers,
            data_rx: Some(data),

            complete_tx: Some(complete_tx),
        };

        let session_ = session.clone();
        session.spawn(move |_| {
            complete_rx
                .map(move |mut file| {
                    if let Some(cache) = session_.cache() {
                        cache.save_file(file_id, &mut file);
                        debug!("File {} complete, saving to cache", file_id);
                    } else {
                        debug!("File {} complete", file_id);
                    }
                })
                .or_else(|oneshot::Canceled| Ok(()))
        });

        AudioFileOpen::Streaming(open)
    }
}

fn request_chunk(session: &Session, file: FileId, index: usize) -> Channel {
    trace!("requesting chunk {}", index);

    let start = (index * CHUNK_SIZE / 4) as u32;
    let end = ((index + 1) * CHUNK_SIZE / 4) as u32;

    let (id, channel) = session.channel().allocate();

    let mut data: Vec<u8> = Vec::new();
    data.write_u16::<BigEndian>(id).unwrap();
    data.write_u8(0).unwrap();
    data.write_u8(1).unwrap();
    data.write_u16::<BigEndian>(0x0000).unwrap();
    data.write_u32::<BigEndian>(0x00000000).unwrap();
    data.write_u32::<BigEndian>(0x00009C40).unwrap();
    data.write_u32::<BigEndian>(0x00020000).unwrap();
    data.write(&file.0).unwrap();
    data.write_u32::<BigEndian>(start).unwrap();
    data.write_u32::<BigEndian>(end).unwrap();

    session.send_packet(0x8, data);

    channel
}

struct AudioFileFetch {
    session: Session,
    shared: Arc<AudioFileShared>,
    output: Option<NamedTempFile>,

    index: usize,
    data_rx: ChannelData,

    seek_rx: mpsc::UnboundedReceiver<u64>,
    complete_tx: Option<oneshot::Sender<NamedTempFile>>,
}

impl AudioFileFetch {
    fn new(
        session: Session,
        shared: Arc<AudioFileShared>,
        data_rx: ChannelData,
        output: NamedTempFile,
        seek_rx: mpsc::UnboundedReceiver<u64>,
        complete_tx: oneshot::Sender<NamedTempFile>,
    ) -> AudioFileFetch {
        AudioFileFetch {
            session: session,
            shared: shared,
            output: Some(output),

            index: 0,
            data_rx: data_rx,

            seek_rx: seek_rx,
            complete_tx: Some(complete_tx),
        }
    }

    fn download(&mut self, mut new_index: usize) {
        assert!(new_index < self.shared.chunk_count);

        {
            let bitmap = self.shared.bitmap.lock().unwrap();
            while bitmap.contains(new_index) {
                new_index = (new_index + 1) % self.shared.chunk_count;
            }
        }

        if self.index != new_index {
            self.index = new_index;

            let offset = self.index * CHUNK_SIZE;

            self.output
                .as_mut()
                .unwrap()
                .seek(SeekFrom::Start(offset as u64))
                .unwrap();

            let (_headers, data) = request_chunk(&self.session, self.shared.file_id, self.index).split();
            self.data_rx = data;
        }
    }

    fn finish(&mut self) {
        let mut output = self.output.take().unwrap();
        let complete_tx = self.complete_tx.take().unwrap();

        output.seek(SeekFrom::Start(0)).unwrap();
        let _ = complete_tx.send(output);
    }
}

impl Future for AudioFileFetch {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        loop {
            let mut progress = false;

            match self.seek_rx.poll() {
                Ok(Async::Ready(None)) => {
                    return Ok(Async::Ready(()));
                }
                Ok(Async::Ready(Some(offset))) => {
                    progress = true;
                    let index = offset as usize / CHUNK_SIZE;
                    self.download(index);
                }
                Ok(Async::NotReady) => (),
                Err(()) => unreachable!(),
            }

            match self.data_rx.poll() {
                Ok(Async::Ready(Some(data))) => {
                    progress = true;

                    self.output.as_mut().unwrap().write_all(data.as_ref()).unwrap();
                }
                Ok(Async::Ready(None)) => {
                    progress = true;

                    trace!("chunk {} / {} complete", self.index, self.shared.chunk_count);

                    let full = {
                        let mut bitmap = self.shared.bitmap.lock().unwrap();
                        bitmap.insert(self.index as usize);
                        self.shared.cond.notify_all();

                        bitmap.len() >= self.shared.chunk_count
                    };

                    if full {
                        self.finish();
                        return Ok(Async::Ready(()));
                    }

                    let new_index = (self.index + 1) % self.shared.chunk_count;
                    self.download(new_index);
                }
                Ok(Async::NotReady) => (),
                Err(ChannelError) => {
                    warn!("error from channel");
                    return Ok(Async::Ready(()));
                }
            }

            if !progress {
                return Ok(Async::NotReady);
            }
        }
    }
}

impl Read for AudioFileStreaming {
    fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
        let index = self.position as usize / CHUNK_SIZE;
        let offset = self.position as usize % CHUNK_SIZE;
        let len = min(output.len(), CHUNK_SIZE - offset);

        let mut bitmap = self.shared.bitmap.lock().unwrap();
        while !bitmap.contains(index) {
            bitmap = self.shared.cond.wait(bitmap).unwrap();
        }
        drop(bitmap);

        let read_len = try!(self.read_file.read(&mut output[..len]));

        self.position += read_len as u64;

        Ok(read_len)
    }
}

impl Seek for AudioFileStreaming {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.position = try!(self.read_file.seek(pos));

        // Notify the fetch thread to get the correct block
        // This can fail if fetch thread has completed, in which case the
        // block is ready. Just ignore the error.
        let _ = self.seek.unbounded_send(self.position);
        Ok(self.position)
    }
}

impl Read for AudioFile {
    fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
        match *self {
            AudioFile::Cached(ref mut file) => file.read(output),
            AudioFile::Streaming(ref mut file) => file.read(output),
        }
    }
}

impl Seek for AudioFile {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        match *self {
            AudioFile::Cached(ref mut file) => file.seek(pos),
            AudioFile::Streaming(ref mut file) => file.seek(pos),
        }
    }
}
<commit_msg>Fix seek past EOF panic for some tracks<commit_after>use bit_set::BitSet;
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use futures::sync::{mpsc, oneshot};
use futures::Stream;
use futures::{Async, Future, Poll};
use std::cmp::min;
use std::fs;
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::sync::{Arc, Condvar, Mutex};
use tempfile::NamedTempFile;

use core::channel::{Channel, ChannelData, ChannelError, ChannelHeaders};
use core::session::Session;
use core::spotify_id::FileId;

const CHUNK_SIZE: usize = 0x20000;

pub enum AudioFile {
    Cached(fs::File),
    Streaming(AudioFileStreaming),
}

pub enum AudioFileOpen {
    Cached(Option<fs::File>),
    Streaming(AudioFileOpenStreaming),
}

pub struct AudioFileOpenStreaming {
    session: Session,
    data_rx: Option<ChannelData>,
    headers: ChannelHeaders,
    file_id: FileId,
    complete_tx: Option<oneshot::Sender<NamedTempFile>>,
}

pub struct AudioFileStreaming {
    read_file: fs::File,

    position: u64,
    seek: mpsc::UnboundedSender<u64>,

    shared: Arc<AudioFileShared>,
}

struct AudioFileShared {
    file_id: FileId,
    chunk_count: usize,
    cond: Condvar,
    bitmap: Mutex<BitSet>,
}

impl AudioFileOpenStreaming {
    fn finish(&mut self, size: usize) -> AudioFileStreaming {
        let chunk_count = (size + CHUNK_SIZE - 1) / CHUNK_SIZE;

        let shared = Arc::new(AudioFileShared {
            file_id: self.file_id,
            chunk_count: chunk_count,
            cond: Condvar::new(),
            bitmap: Mutex::new(BitSet::with_capacity(chunk_count)),
        });

        let mut write_file = NamedTempFile::new().unwrap();
        write_file.set_len(size as u64).unwrap();
        write_file.seek(SeekFrom::Start(0)).unwrap();

        let read_file = write_file.reopen().unwrap();

        let data_rx = self.data_rx.take().unwrap();
        let complete_tx = self.complete_tx.take().unwrap();
        let (seek_tx, seek_rx) = mpsc::unbounded();

        let fetcher = AudioFileFetch::new(
            self.session.clone(),
            shared.clone(),
            data_rx,
            write_file,
            seek_rx,
            complete_tx,
        );
        self.session.spawn(move |_| fetcher);

        AudioFileStreaming {
            read_file: read_file,

            position: 0,
            seek: seek_tx,

            shared: shared,
        }
    }
}

impl Future for AudioFileOpen {
    type Item = AudioFile;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<AudioFile, ChannelError> {
        match *self {
            AudioFileOpen::Streaming(ref mut open) => {
                let file = try_ready!(open.poll());
                Ok(Async::Ready(AudioFile::Streaming(file)))
            }
            AudioFileOpen::Cached(ref mut file) => {
                let file = file.take().unwrap();
                Ok(Async::Ready(AudioFile::Cached(file)))
            }
        }
    }
}

impl Future for AudioFileOpenStreaming {
    type Item = AudioFileStreaming;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<AudioFileStreaming, ChannelError> {
        loop {
            let (id, data) = try_ready!(self.headers.poll()).unwrap();

            if id == 0x3 {
                let size = BigEndian::read_u32(&data) as usize * 4;
                let file = self.finish(size);

                return Ok(Async::Ready(file));
            }
        }
    }
}

impl AudioFile {
    pub fn open(session: &Session, file_id: FileId) -> AudioFileOpen {
        let cache = session.cache().cloned();

        if let Some(file) = cache.as_ref().and_then(|cache| cache.file(file_id)) {
            debug!("File {} already in cache", file_id);
            return AudioFileOpen::Cached(Some(file));
        }

        debug!("Downloading file {}", file_id);

        let (complete_tx, complete_rx) = oneshot::channel();
        let (headers, data) = request_chunk(session, file_id, 0).split();

        let open = AudioFileOpenStreaming {
            session: session.clone(),
            file_id: file_id,

            headers: headers,
            data_rx: Some(data),

            complete_tx: Some(complete_tx),
        };

        let session_ = session.clone();
        session.spawn(move |_| {
            complete_rx
                .map(move |mut file| {
                    if let Some(cache) = session_.cache() {
                        cache.save_file(file_id, &mut file);
                        debug!("File {} complete, saving to cache", file_id);
                    } else {
                        debug!("File {} complete", file_id);
                    }
                })
                .or_else(|oneshot::Canceled| Ok(()))
        });

        AudioFileOpen::Streaming(open)
    }
}

fn request_chunk(session: &Session, file: FileId, index: usize) -> Channel {
    trace!("requesting chunk {}", index);

    let start = (index * CHUNK_SIZE / 4) as u32;
    let end = ((index + 1) * CHUNK_SIZE / 4) as u32;

    let (id, channel) = session.channel().allocate();

    let mut data: Vec<u8> = Vec::new();
    data.write_u16::<BigEndian>(id).unwrap();
    data.write_u8(0).unwrap();
    data.write_u8(1).unwrap();
    data.write_u16::<BigEndian>(0x0000).unwrap();
    data.write_u32::<BigEndian>(0x00000000).unwrap();
    data.write_u32::<BigEndian>(0x00009C40).unwrap();
    data.write_u32::<BigEndian>(0x00020000).unwrap();
    data.write(&file.0).unwrap();
    data.write_u32::<BigEndian>(start).unwrap();
    data.write_u32::<BigEndian>(end).unwrap();

    session.send_packet(0x8, data);

    channel
}

struct AudioFileFetch {
    session: Session,
    shared: Arc<AudioFileShared>,
    output: Option<NamedTempFile>,

    index: usize,
    data_rx: ChannelData,

    seek_rx: mpsc::UnboundedReceiver<u64>,
    complete_tx: Option<oneshot::Sender<NamedTempFile>>,
}

impl AudioFileFetch {
    fn new(
        session: Session,
        shared: Arc<AudioFileShared>,
        data_rx: ChannelData,
        output: NamedTempFile,
        seek_rx: mpsc::UnboundedReceiver<u64>,
        complete_tx: oneshot::Sender<NamedTempFile>,
    ) -> AudioFileFetch {
        AudioFileFetch {
            session: session,
            shared: shared,
            output: Some(output),

            index: 0,
            data_rx: data_rx,

            seek_rx: seek_rx,
            complete_tx: Some(complete_tx),
        }
    }

    fn download(&mut self, mut new_index: usize) {
        assert!(new_index < self.shared.chunk_count);

        {
            let bitmap = self.shared.bitmap.lock().unwrap();
            while bitmap.contains(new_index) {
                new_index = (new_index + 1) % self.shared.chunk_count;
            }
        }

        if self.index != new_index {
            self.index = new_index;

            let offset = self.index * CHUNK_SIZE;

            self.output
                .as_mut()
                .unwrap()
                .seek(SeekFrom::Start(offset as u64))
                .unwrap();

            let (_headers, data) = request_chunk(&self.session, self.shared.file_id, self.index).split();
            self.data_rx = data;
        }
    }

    fn finish(&mut self) {
        let mut output = self.output.take().unwrap();
        let complete_tx = self.complete_tx.take().unwrap();

        output.seek(SeekFrom::Start(0)).unwrap();
        let _ = complete_tx.send(output);
    }
}

impl Future for AudioFileFetch {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        loop {
            let mut progress = false;

            match self.seek_rx.poll() {
                Ok(Async::Ready(None)) => {
                    return Ok(Async::Ready(()));
                }
                Ok(Async::Ready(Some(offset))) => {
                    progress = true;
                    let index = offset as usize / CHUNK_SIZE;
                    self.download(index);
                }
                Ok(Async::NotReady) => (),
                Err(()) => unreachable!(),
            }

            match self.data_rx.poll() {
                Ok(Async::Ready(Some(data))) => {
                    progress = true;

                    self.output.as_mut().unwrap().write_all(data.as_ref()).unwrap();
                }
                Ok(Async::Ready(None)) => {
                    progress = true;

                    trace!("chunk {} / {} complete", self.index, self.shared.chunk_count);

                    let full = {
                        let mut bitmap = self.shared.bitmap.lock().unwrap();
                        bitmap.insert(self.index as usize);
                        self.shared.cond.notify_all();

                        bitmap.len() >= self.shared.chunk_count
                    };

                    if full {
                        self.finish();
                        return Ok(Async::Ready(()));
                    }

                    let new_index = (self.index + 1) % self.shared.chunk_count;
                    self.download(new_index);
                }
                Ok(Async::NotReady) => (),
                Err(ChannelError) => {
                    warn!("error from channel");
                    return Ok(Async::Ready(()));
                }
            }

            if !progress {
                return Ok(Async::NotReady);
            }
        }
    }
}

impl Read for AudioFileStreaming {
    fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
        let index = self.position as usize / CHUNK_SIZE;
        let offset = self.position as usize % CHUNK_SIZE;
        let len = min(output.len(), CHUNK_SIZE - offset);

        let mut bitmap = self.shared.bitmap.lock().unwrap();
        while !bitmap.contains(index) {
            bitmap = self.shared.cond.wait(bitmap).unwrap();
        }
        drop(bitmap);

        let read_len = try!(self.read_file.read(&mut output[..len]));

        self.position += read_len as u64;

        Ok(read_len)
    }
}

impl Seek for AudioFileStreaming {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.position = try!(self.read_file.seek(pos));
        // Do not seek past EOF
        if (self.position as usize % CHUNK_SIZE) != 0  {
            // Notify the fetch thread to get the correct block
            // This can fail if fetch thread has completed, in which case the
            // block is ready. Just ignore the error.
            let _ = self.seek.unbounded_send(self.position);
        } else {
            warn!("Trying to seek past EOF");
        }

        Ok(self.position)
    }
}

impl Read for AudioFile {
    fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
        match *self {
            AudioFile::Cached(ref mut file) => file.read(output),
            AudioFile::Streaming(ref mut file) => file.read(output),
        }
    }
}

impl Seek for AudioFile {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        match *self {
            AudioFile::Cached(ref mut file) => file.seek(pos),
            AudioFile::Streaming(ref mut file) => file.seek(pos),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Dmitry "Divius" Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

//! KRPC protocol bits as described in
//! [BEP 0005](http://www.bittorrent.org/beps/bep_0005.html).

use std::collections;
use std::path::BytesContainer;

use bencode::{mod, FromBencode, ToBencode};
use bencode::util::ByteString;
use num;

use super::super::base;
use super::super::utils;

// TODO(divius): actually validate it
static ID_BYTE_SIZE: uint = 20;

/// Type of payload dict.
pub type PayloadDict = bencode::DictMap;

/// Package payload in KRPC: either Query (request) or Response or Error.
#[deriving(Show)]
pub enum Payload {
    /// Request to a node.
    Query(PayloadDict),
    /// Response to request.
    Response(PayloadDict),
    /// Error: code and string message.
    Error(i64, String)
}

/// KRPC package.
pub struct Package {
    /// Transaction ID generated by requester and passed back by responder.
    pub transaction_id: Vec<u8>,
    /// Package payload.
    pub payload: Payload,
    /// Sender node if known.
    ///
    /// Note that as per BEP 0005 it is stored in payload and thus is not set
    /// for errors.
    pub sender: Option<base::Node>
}

const QUERY: &'static str = "q";
const RESPONSE: &'static str = "r";
const ERROR: &'static str = "e";

const TYPE: &'static str = "y";
const TR_ID: &'static str = "tt";
const SENDER: &'static str = "id";

fn id_to_netbytes(id: &num::BigUint) -> Vec<u8> {
    assert!(id.bits() <= ID_BYTE_SIZE * 8);

    let mut id_c = id.clone();
    let mask = FromPrimitive::from_u8(0xFF).unwrap();
    let mut result = Vec::from_elem(ID_BYTE_SIZE, 0);

    for i in result.iter_mut().rev() {
        let part = id_c & mask;
        *i = part.to_u8().unwrap();
        id_c = id_c >> 8;
    }

    result
}

fn id_from_netbytes(bytes: &[u8]) -> num::BigUint {
    let mut result: num::BigUint = FromPrimitive::from_int(0).unwrap();
    let mut shift = 0;
    for i in bytes.iter().rev() {
        let val: num::BigUint = FromPrimitive::from_u8(*i).unwrap();
        result = result + (val << shift);
        shift += 8;
    }
    result
}

impl ToBencode for base::Node {
    fn to_bencode(&self) -> bencode::Bencode {
        let mut result = id_to_netbytes(&self.id);
        result.push_all(utils::netaddr_to_netbytes(&self.address).as_slice());
        bencode::ByteString(result)
    }
}

impl FromBencode for base::Node {
    fn from_bencode(b: &bencode::Bencode) -> Option<base::Node> {
        match *b {
            bencode::ByteString(ref v) if v.len() == 26 => Some(base::Node {
                id: id_from_netbytes(v.slice(0, 20)),
                address: utils::netaddr_from_netbytes(v.slice(20, 26))
            }),
            _ => {
                debug!("{} is unexpected representation for a node", b);
                None
            }
        }
    }
}

fn dict_with_sender(dict: &PayloadDict, maybe_sender: &Option<base::Node>)
        -> bencode::Bencode {
    let mut d = dict.clone();
    if let Some(ref sender) = *maybe_sender {
        d.insert(ByteString::from_str(SENDER), sender.to_bencode());
    }
    bencode::Dict(d)
}

impl ToBencode for Package {
    fn to_bencode(&self) -> bencode::Bencode {
        let mut result: bencode::DictMap = collections::TreeMap::new();

        result.insert(ByteString::from_str(TR_ID),
                      bencode::ByteString(self.transaction_id.clone()));
        let (typ, payload) = match self.payload {
            Query(ref d) => (QUERY, dict_with_sender(d, &self.sender)),
            Response(ref d) => (RESPONSE, dict_with_sender(d, &self.sender)),
            Error(code, ref s) => {
                let l = vec![code.to_bencode(), s.to_bencode()];
                (ERROR, bencode::List(l))
            }
        };
        result.insert(ByteString::from_str(TYPE), typ.to_string().to_bencode());
        result.insert(ByteString::from_str(typ), payload);

        bencode::Dict(result)
    }
}

macro_rules! debug_and_return(
    ($( $arg:expr ),*) => ({
        debug!($( $arg ),*);
        return None;
    })
)

macro_rules! bytes_or_none(
    ($dict:ident, $key:expr, $msg:expr) => (
        match $dict.find(&ByteString::from_str($key)) {
            Some(&bencode::ByteString(ref val)) => val,
            _ => debug_and_return!($msg)
        }
    )
)

impl FromBencode for Package {
    fn from_bencode(b: &bencode::Bencode) -> Option<Package> {
        let dict = match *b {
            bencode::Dict(ref d) => d,
            _ => debug_and_return!("Expected dict as top-level package, got {}", b)
        };

        let typ = bytes_or_none!(dict, TYPE, "No type");
        let payload_data = match dict.find(&ByteString::from_vec(typ.clone())) {
            Some(val) => val,
            None => debug_and_return!("No payload")
        };
        let mut sender = None;

        let payload = match typ.container_as_str() {
            Some(ERROR) => match *payload_data {
                bencode::List(ref v) => match v.as_slice() {
                    [bencode::Number(code), bencode::ByteString(ref msg)] => {
                        let str_msg = match msg.container_as_str() {
                            Some(s) => s,
                            None => {
                                debug!("Error message is not UTF8: {}", msg);
                                "Unknown error"
                            }
                        };
                        Error(code, str_msg.to_string())
                    },
                    _ => debug_and_return!(
                        "Error body of unknown structure {}", v)
                },
                _ => debug_and_return!("Error body of unexpected type: {}",
                                       payload_data)
            },
            Some(QUERY) => match *payload_data {
                bencode::Dict(ref d) => {
                    let mut d2 = d.clone();
                    sender = d2.pop(&ByteString::from_str(SENDER));
                    if sender.is_none() {
                        debug_and_return!("No sender ID in query");
                    };
                    Query(d2)
                },
                _ => debug_and_return!("Query body of unexpected type: {}",
                                       payload_data)
            },
            Some(RESPONSE) => match *payload_data {
                bencode::Dict(ref d) => {
                    let mut d2 = d.clone();
                    sender = d2.pop(&ByteString::from_str(SENDER));
                    if sender.is_none() {
                        debug_and_return!("No sender ID in response");
                    };
                    Response(d2)
                },
                _ => debug_and_return!("Response body of unexpected type: {}",
                                       payload_data)
            },
            Some(unknown) => debug_and_return!("Unexpected payload type {}",
                                               unknown),
            None => debug_and_return!("Not a UTF8 string: field y, value {}",
                                      typ)
        };

        let sender_node = sender.and_then(|s| FromBencode::from_bencode(&s));

        let tt = bytes_or_none!(dict, TR_ID, "No transaction id");
        Some(Package {
            transaction_id: tt.clone(),
            payload: payload,
            sender: sender_node
        })
    }
}

#[cfg(test)]
mod test {
    use std::collections;

    use bencode::{mod, FromBencode, ToBencode};

    use super::super::super::base;
    use super::super::super::utils::test;

    use super::PayloadDict;
    use super::Error;
    use super::Package;
    use super::Payload;
    use super::Query;
    use super::Response;

    const FAKE_TR_ID: &'static [u8] = [1, 2, 254, 255];

    fn new_package(payload: Payload) -> Package {
        Package {
            transaction_id: FAKE_TR_ID.to_vec(),
            sender: Some(test::new_node(42)),
            payload: payload
        }
    }

    fn common<'a>(b: &'a bencode::Bencode, typ: &str) -> &'a bencode::DictMap {
        match *b {
            bencode::Dict(ref d) => {
                let tt_val = &d[bencode::util::ByteString::from_str("tt")];
                match *tt_val {
                    bencode::ByteString(ref v) => {
                        assert_eq!(vec![1, 2, 254, 255], *v);
                    },
                    _ => fail!("unexpected {}", tt_val)
                };

                let y_val = &d[bencode::util::ByteString::from_str("y")];
                match *y_val {
                    bencode::ByteString(ref v) => {
                        assert_eq!(typ.as_bytes(), v.as_slice());
                    },
                    _ => fail!("unexpected {}", y_val)
                };

                d
            },
            _ => fail!("unexpected {}", b)
        }
    }

    fn dict<'a>(b: &'a bencode::Bencode, typ: &str) -> &'a bencode::DictMap {
        let d = common(b, typ);

        let typ_val = &d[bencode::util::ByteString::from_str(typ)];
        match *typ_val {
            bencode::Dict(ref m) => m,
            _ => fail!("unexpected {}", typ_val)
        }
    }

    fn list<'a>(b: &'a bencode::Bencode, typ: &str) -> &'a bencode::ListVec {
        let d = common(b, typ);

        let typ_val = &d[bencode::util::ByteString::from_str(typ)];
        match *typ_val {
            bencode::List(ref l) => l,
            _ => fail!("unexpected {}", typ_val)
        }
    }

    #[test]
    fn test_error_to_bencode() {
        let p = new_package(Error(10, "error".to_string()));
        let enc = p.to_bencode();
        let l = list(&enc, "e");
        assert_eq!(vec![bencode::Number(10),
                        "error".to_string().to_bencode()],
                   *l);
    }

    #[test]
    fn test_error_to_from_bencode() {
        let p = new_package(Error(10, "error".to_string()));
        let enc = p.to_bencode();
        let p2: Package = FromBencode::from_bencode(&enc).unwrap();
        assert_eq!(FAKE_TR_ID, p2.transaction_id.as_slice());
        assert!(p2.sender.is_none());
        if let Error(code, msg) = p2.payload {
            assert_eq!(10, code);
            assert_eq!("error", msg.as_slice());
        }
        else {
            fail!("Expected Error, got {}", p2.payload);
        }
    }

    #[test]
    fn test_query_to_bencode() {
        let payload: PayloadDict = collections::TreeMap::new();
        let p = new_package(Query(payload));
        let enc = p.to_bencode();
        dict(&enc, "q");
        // TODO(divius): Moar tests
    }

    #[test]
    fn test_response_to_bencode() {
        let payload: PayloadDict = collections::TreeMap::new();
        let p = new_package(Response(payload));
        let enc = p.to_bencode();
        dict(&enc, "r");
        // TODO(divius): Moar tests
    }

    #[test]
    fn test_id_to_netbytes() {
        let id = test::uint_to_id(0x0A0B0C0D);
        let b = super::id_to_netbytes(&id);
        let mut expected = Vec::from_elem(16, 0u8);
        expected.push_all([0x0A, 0x0b, 0x0C, 0x0D]);
        assert_eq!(expected, b);
    }

    #[test]
    fn test_id_from_netbytes() {
        let mut bytes = Vec::from_elem(16, 0u8);
        bytes.push_all([0x0A, 0x0b, 0x0C, 0x0D]);
        let expected = test::uint_to_id(0x0A0B0C0D);
        let id = super::id_from_netbytes(bytes.as_slice());
        assert_eq!(expected, id);
    }

    #[test]
    fn test_node_to_bencode() {
        let n = test::new_node(42);
        let enc = n.to_bencode();
        let mut expected = Vec::from_elem(19, 0u8);
        expected.push_all([42, 127, 0, 0, 1, 31, 72]);
        assert_eq!(bencode::ByteString(expected), enc);
    }

    #[test]
    fn test_node_from_bencode() {
        let mut b = Vec::from_elem(19, 0u8);
        b.push_all([42, 127, 0, 0, 1, 0, 80]);
        let n: base::Node =
            FromBencode::from_bencode(&bencode::ByteString(b)).unwrap();
        assert_eq!(n.id, test::uint_to_id(42));
        assert_eq!(n.address.to_string().as_slice(), "127.0.0.1:80");
    }

    #[test]
    fn test_node_from_bencode_none() {
        let n: Option<base::Node> =
            FromBencode::from_bencode(&bencode::Number(42));
        assert!(n.is_none());
    }

    #[test]
    fn test_node_to_from_bencode() {
        let n = test::new_node(42);
        let enc = n.to_bencode();
        let n2: base::Node = FromBencode::from_bencode(&enc).unwrap();
        assert_eq!(n.id, n2.id);
        assert_eq!(n.address, n2.address);
    }
}
<commit_msg>Improved code of FromBencode for Package and add more tests (even more needed)<commit_after>// Copyright 2014 Dmitry "Divius" Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

//! KRPC protocol bits as described in
//! [BEP 0005](http://www.bittorrent.org/beps/bep_0005.html).

use std::collections;
use std::path::BytesContainer;

use bencode::{mod, FromBencode, ToBencode};
use bencode::util::ByteString;
use num;

use super::super::base;
use super::super::utils;

// TODO(divius): actually validate it
static ID_BYTE_SIZE: uint = 20;

/// Type of payload dict.
pub type PayloadDict = bencode::DictMap;

/// Package payload in KRPC: either Query (request) or Response or Error.
#[deriving(Show)]
pub enum Payload {
    /// Request to a node.
    Query(PayloadDict),
    /// Response to request.
    Response(PayloadDict),
    /// Error: code and string message.
    Error(i64, String)
}

/// KRPC package.
pub struct Package {
    /// Transaction ID generated by requester and passed back by responder.
    pub transaction_id: Vec<u8>,
    /// Package payload.
    pub payload: Payload,
    /// Sender node if known.
    ///
    /// Note that as per BEP 0005 it is stored in payload and thus is not set
    /// for errors.
    pub sender: Option<base::Node>
}

const QUERY: &'static str = "q";
const RESPONSE: &'static str = "r";
const ERROR: &'static str = "e";

const TYPE: &'static str = "y";
const TR_ID: &'static str = "tt";
const SENDER: &'static str = "id";

fn id_to_netbytes(id: &num::BigUint) -> Vec<u8> {
    assert!(id.bits() <= ID_BYTE_SIZE * 8);

    let mut id_c = id.clone();
    let mask = FromPrimitive::from_u8(0xFF).unwrap();
    let mut result = Vec::from_elem(ID_BYTE_SIZE, 0);

    for i in result.iter_mut().rev() {
        let part = id_c & mask;
        *i = part.to_u8().unwrap();
        id_c = id_c >> 8;
    }

    result
}

fn id_from_netbytes(bytes: &[u8]) -> num::BigUint {
    let mut result: num::BigUint = FromPrimitive::from_int(0).unwrap();
    let mut shift = 0;
    for i in bytes.iter().rev() {
        let val: num::BigUint = FromPrimitive::from_u8(*i).unwrap();
        result = result + (val << shift);
        shift += 8;
    }
    result
}

impl ToBencode for base::Node {
    fn to_bencode(&self) -> bencode::Bencode {
        let mut result = id_to_netbytes(&self.id);
        result.push_all(utils::netaddr_to_netbytes(&self.address).as_slice());
        bencode::ByteString(result)
    }
}

impl FromBencode for base::Node {
    fn from_bencode(b: &bencode::Bencode) -> Option<base::Node> {
        match *b {
            bencode::ByteString(ref v) if v.len() == 26 => Some(base::Node {
                id: id_from_netbytes(v.slice(0, 20)),
                address: utils::netaddr_from_netbytes(v.slice(20, 26))
            }),
            _ => {
                debug!("{} is unexpected representation for a node", b);
                None
            }
        }
    }
}

fn dict_with_sender(dict: &PayloadDict, maybe_sender: &Option<base::Node>)
        -> bencode::Bencode {
    let mut d = dict.clone();
    if let Some(ref sender) = *maybe_sender {
        d.insert(ByteString::from_str(SENDER), sender.to_bencode());
    }
    bencode::Dict(d)
}

impl ToBencode for Package {
    fn to_bencode(&self) -> bencode::Bencode {
        let mut result: bencode::DictMap = collections::TreeMap::new();

        result.insert(ByteString::from_str(TR_ID),
                      bencode::ByteString(self.transaction_id.clone()));
        let (typ, payload) = match self.payload {
            Query(ref d) => (QUERY, dict_with_sender(d, &self.sender)),
            Response(ref d) => (RESPONSE, dict_with_sender(d, &self.sender)),
            Error(code, ref s) => {
                let l = vec![code.to_bencode(), s.to_bencode()];
                (ERROR, bencode::List(l))
            }
        };
        result.insert(ByteString::from_str(TYPE), typ.to_string().to_bencode());
        result.insert(ByteString::from_str(typ), payload);

        bencode::Dict(result)
    }
}

macro_rules! debug_and_return(
    ($( $arg:expr ),*) => ({
        debug!($( $arg ),*);
        return None;
    })
)

macro_rules! bytes_or_none(
    ($dict:ident, $key:expr, $msg:expr) => (
        match $dict.find(&ByteString::from_str($key)) {
            Some(&bencode::ByteString(ref val)) => val,
            _ => debug_and_return!($msg)
        }
    )
)

macro_rules! extract_sender(
    ($dict:ident, $ty:expr, $msg:expr) => ({
        let mut d = $dict.clone();
        if let Some(sender_be) = d.pop(&ByteString::from_str(SENDER)) {
            if let Some(sender) = FromBencode::from_bencode(&sender_be) {
                ($ty(d), sender)
            }
            else {
                debug_and_return!("Cannot decode sender {}", sender_be);
            }
        }
        else {
            debug_and_return!($msg);
        }
    })
)

impl FromBencode for Package {
    fn from_bencode(b: &bencode::Bencode) -> Option<Package> {
        let dict = match *b {
            bencode::Dict(ref d) => d,
            _ => debug_and_return!("Expected dict as top-level package, got {}", b)
        };

        let typ = bytes_or_none!(dict, TYPE, "No type");
        let payload_data = match dict.find(&ByteString::from_vec(typ.clone())) {
            Some(val) => val,
            None => debug_and_return!("No payload")
        };

        let (payload, sender) = match typ.container_as_str() {
            Some(ERROR) => match *payload_data {
                bencode::List(ref v) => match v.as_slice() {
                    [bencode::Number(code), bencode::ByteString(ref msg)] => {
                        let str_msg = match msg.container_as_str() {
                            Some(s) => s,
                            None => {
                                debug!("Error message is not UTF8: {}", msg);
                                "Unknown error"
                            }
                        };
                        (Error(code, str_msg.to_string()), None)
                    },
                    _ => debug_and_return!(
                        "Error body of unknown structure {}", v)
                },
                _ => debug_and_return!("Error body of unexpected type: {}",
                                       payload_data)
            },
            Some(QUERY) => match *payload_data {
                bencode::Dict(ref d) =>
                    extract_sender!(d, Query, "No sender ID in query"),
                _ => debug_and_return!("Query body of unexpected type: {}",
                                       payload_data)
            },
            Some(RESPONSE) => match *payload_data {
                bencode::Dict(ref d) =>
                    extract_sender!(d, Response, "No sender ID in response"),
                _ => debug_and_return!("Response body of unexpected type: {}",
                                       payload_data)
            },
            Some(unknown) => debug_and_return!("Unexpected payload type {}",
                                               unknown),
            None => debug_and_return!("Not a UTF8 string: field y, value {}",
                                      typ)
        };

        let tt = bytes_or_none!(dict, TR_ID, "No transaction id");
        Some(Package {
            transaction_id: tt.clone(),
            payload: payload,
            sender: sender
        })
    }
}

#[cfg(test)]
mod test {
    use std::collections;

    use bencode::{mod, FromBencode, ToBencode};

    use super::super::super::base;
    use super::super::super::utils::test;

    use super::PayloadDict;
    use super::Error;
    use super::Package;
    use super::Payload;
    use super::Query;
    use super::Response;

    const FAKE_TR_ID: &'static [u8] = [1, 2, 254, 255];

    fn new_package(payload: Payload) -> Package {
        Package {
            transaction_id: FAKE_TR_ID.to_vec(),
            sender: Some(test::new_node(42)),
            payload: payload
        }
    }

    fn common<'a>(b: &'a bencode::Bencode, typ: &str) -> &'a bencode::DictMap {
        match *b {
            bencode::Dict(ref d) => {
                let tt_val = &d[bencode::util::ByteString::from_str("tt")];
                match *tt_val {
                    bencode::ByteString(ref v) => {
                        assert_eq!(vec![1, 2, 254, 255], *v);
                    },
                    _ => fail!("unexpected {}", tt_val)
                };

                let y_val = &d[bencode::util::ByteString::from_str("y")];
                match *y_val {
                    bencode::ByteString(ref v) => {
                        assert_eq!(typ.as_bytes(), v.as_slice());
                    },
                    _ => fail!("unexpected {}", y_val)
                };

                d
            },
            _ => fail!("unexpected {}", b)
        }
    }

    fn dict<'a>(b: &'a bencode::Bencode, typ: &str) -> &'a bencode::DictMap {
        let d = common(b, typ);

        let typ_val = &d[bencode::util::ByteString::from_str(typ)];
        match *typ_val {
            bencode::Dict(ref m) => m,
            _ => fail!("unexpected {}", typ_val)
        }
    }

    fn list<'a>(b: &'a bencode::Bencode, typ: &str) -> &'a bencode::ListVec {
        let d = common(b, typ);

        let typ_val = &d[bencode::util::ByteString::from_str(typ)];
        match *typ_val {
            bencode::List(ref l) => l,
            _ => fail!("unexpected {}", typ_val)
        }
    }

    #[test]
    fn test_error_to_bencode() {
        let p = new_package(Error(10, "error".to_string()));
        let enc = p.to_bencode();
        let l = list(&enc, "e");
        assert_eq!(vec![bencode::Number(10),
                        "error".to_string().to_bencode()],
                   *l);
    }

    #[test]
    fn test_error_to_from_bencode() {
        let p = new_package(Error(10, "error".to_string()));
        let enc = p.to_bencode();
        let p2: Package = FromBencode::from_bencode(&enc).unwrap();
        assert_eq!(FAKE_TR_ID, p2.transaction_id.as_slice());
        assert!(p2.sender.is_none());
        if let Error(code, msg) = p2.payload {
            assert_eq!(10, code);
            assert_eq!("error", msg.as_slice());
        }
        else {
            fail!("Expected Error, got {}", p2.payload);
        }
    }

    #[test]
    fn test_query_to_bencode() {
        let payload: PayloadDict = collections::TreeMap::new();
        let p = new_package(Query(payload));
        let enc = p.to_bencode();
        dict(&enc, "q");
        // TODO(divius): Moar tests
    }

    #[test]
    fn test_query_to_from_bencode() {
        let payload: PayloadDict = collections::TreeMap::new();
        let p = new_package(Query(payload));
        let enc = p.to_bencode();
        let p2: Package = FromBencode::from_bencode(&enc).unwrap();
        assert_eq!(FAKE_TR_ID, p2.transaction_id.as_slice());
        assert_eq!(test::uint_to_id(42), p2.sender.unwrap().id);
        if let Query(d) = p2.payload {
            // TODO(divius): test
        }
        else {
            fail!("Expected Query, got {}", p2.payload);
        }
    }

    #[test]
    fn test_response_to_bencode() {
        let payload: PayloadDict = collections::TreeMap::new();
        let p = new_package(Response(payload));
        let enc = p.to_bencode();
        dict(&enc, "r");
        // TODO(divius): Moar tests
    }

    #[test]
    fn test_response_to_from_bencode() {
        let payload: PayloadDict = collections::TreeMap::new();
        let p = new_package(Response(payload));
        let enc = p.to_bencode();
        let p2: Package = FromBencode::from_bencode(&enc).unwrap();
        assert_eq!(FAKE_TR_ID, p2.transaction_id.as_slice());
        assert_eq!(test::uint_to_id(42), p2.sender.unwrap().id);
        if let Response(d) = p2.payload {
            // TODO(divius): test
        }
        else {
            fail!("Expected Response, got {}", p2.payload);
        }
    }

    #[test]
    fn test_id_to_netbytes() {
        let id = test::uint_to_id(0x0A0B0C0D);
        let b = super::id_to_netbytes(&id);
        let mut expected = Vec::from_elem(16, 0u8);
        expected.push_all([0x0A, 0x0b, 0x0C, 0x0D]);
        assert_eq!(expected, b);
    }

    #[test]
    fn test_id_from_netbytes() {
        let mut bytes = Vec::from_elem(16, 0u8);
        bytes.push_all([0x0A, 0x0b, 0x0C, 0x0D]);
        let expected = test::uint_to_id(0x0A0B0C0D);
        let id = super::id_from_netbytes(bytes.as_slice());
        assert_eq!(expected, id);
    }

    #[test]
    fn test_node_to_bencode() {
        let n = test::new_node(42);
        let enc = n.to_bencode();
        let mut expected = Vec::from_elem(19, 0u8);
        expected.push_all([42, 127, 0, 0, 1, 31, 72]);
        assert_eq!(bencode::ByteString(expected), enc);
    }

    #[test]
    fn test_node_from_bencode() {
        let mut b = Vec::from_elem(19, 0u8);
        b.push_all([42, 127, 0, 0, 1, 0, 80]);
        let n: base::Node =
            FromBencode::from_bencode(&bencode::ByteString(b)).unwrap();
        assert_eq!(n.id, test::uint_to_id(42));
        assert_eq!(n.address.to_string().as_slice(), "127.0.0.1:80");
    }

    #[test]
    fn test_node_from_bencode_none() {
        let n: Option<base::Node> =
            FromBencode::from_bencode(&bencode::Number(42));
        assert!(n.is_none());
    }

    #[test]
    fn test_node_to_from_bencode() {
        let n = test::new_node(42);
        let enc = n.to_bencode();
        let n2: base::Node = FromBencode::from_bencode(&enc).unwrap();
        assert_eq!(n.id, n2.id);
        assert_eq!(n.address, n2.address);
    }
}
<|endoftext|>


<commit_before>//! Various builders to generate/alter wasm components

mod invoke;
mod module;
mod code;
mod misc;
mod import;
mod memory;
mod table;
mod export;
mod global;
mod data;

pub use self::code::{
    signatures, signature, function, SignatureBuilder, SignaturesBuilder,
    FunctionBuilder, TypeRefBuilder, FuncBodyBuilder, FunctionDefinition,
};
pub use self::invoke::Identity;
pub use self::module::{module, from_module, ModuleBuilder};
pub use self::memory::MemoryBuilder;
pub use self::import::{import, ImportBuilder};
pub use self::export::{export, ExportBuilder};
pub use self::global::{global, GlobalBuilder};
<commit_msg>rearrange exports<commit_after>//! Various builders to generate/alter wasm components

mod invoke;
mod module;
mod code;
mod misc;
mod import;
mod memory;
mod table;
mod export;
mod global;
mod data;

pub use self::code::{
    signatures, signature, function, SignatureBuilder, SignaturesBuilder,
    FunctionBuilder, TypeRefBuilder, FuncBodyBuilder, FunctionDefinition,
};
pub use self::data::DataSegmentBuilder;
pub use self::export::{export, ExportBuilder};
pub use self::global::{global, GlobalBuilder};
pub use self::import::{import, ImportBuilder};
pub use self::invoke::Identity;
pub use self::memory::MemoryBuilder;
pub use self::module::{module, from_module, ModuleBuilder};
<|endoftext|>