<commit_before>use crate::stream::{StreamExt, Fuse};
use core::pin::Pin;
use futures_core::future::Future;
use futures_core::stream::Stream;
use futures_core::task::{Context, Poll};
use futures_sink::Sink;

/// Future for the [`send_all`](super::SinkExt::send_all) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct SendAll<'a, Si, St>
where
    Si: Sink<St::Item> + Unpin + ?Sized,
    St: Stream + Unpin + ?Sized,
{
    sink: &'a mut Si,
    stream: Fuse<&'a mut St>,
    buffered: Option<St::Item>,
}

// Pinning is never projected to any fields
impl<Si, St> Unpin for SendAll<'_, Si, St>
where
    Si: Sink<St::Item> + Unpin + ?Sized,
    St: Stream + Unpin + ?Sized,
{}

impl<'a, Si, St> SendAll<'a, Si, St>
where
    Si: Sink<St::Item> + Unpin + ?Sized,
    St: Stream + Unpin + ?Sized,
{
    pub(super) fn new(
        sink: &'a mut Si,
        stream: &'a mut St,
    ) -> SendAll<'a, Si, St> {
        SendAll {
            sink,
            stream: stream.fuse(),
            buffered: None,
        }
    }

    fn try_start_send(
        &mut self,
        cx: &mut Context<'_>,
        item: St::Item,
    ) -> Poll<Result<(), Si::Error>> {
        debug_assert!(self.buffered.is_none());
        match Pin::new(&mut self.sink).poll_ready(cx)? {
            Poll::Ready(()) => {
                Poll::Ready(Pin::new(&mut self.sink).start_send(item))
            }
            Poll::Pending => {
                self.buffered = Some(item);
                Poll::Pending
            }
        }
    }
}

impl<Si, St> Future for SendAll<'_, Si, St>
where
    Si: Sink<St::Item> + Unpin + ?Sized,
    St: Stream + Unpin + ?Sized,
{
    type Output = Result<(), Si::Error>;

    fn poll(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Self::Output> {
        let this = &mut *self;
        // If we've got an item buffered already, we need to write it to the
        // sink before we can do anything else
        if let Some(item) = this.buffered.take() {
            ready!(this.try_start_send(cx, item))?
        }

        loop {
            match this.stream.poll_next_unpin(cx) {
                Poll::Ready(Some(item)) => {
                    ready!(this.try_start_send(cx, item))?
                }
                Poll::Ready(None) => {
                    ready!(Pin::new(&mut this.sink).poll_flush(cx))?;
                    return Poll::Ready(Ok(()))
                }
                Poll::Pending => {
                    ready!(Pin::new(&mut this.sink).poll_ready(cx))?;
                    return Poll::Pending
                }
            }
        }
    }
}
<commit_msg>Flush sink when source stream is pending in SendAll<commit_after>use crate::stream::{StreamExt, Fuse};
use core::pin::Pin;
use futures_core::future::Future;
use futures_core::stream::Stream;
use futures_core::task::{Context, Poll};
use futures_sink::Sink;

/// Future for the [`send_all`](super::SinkExt::send_all) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct SendAll<'a, Si, St>
where
    Si: Sink<St::Item> + Unpin + ?Sized,
    St: Stream + Unpin + ?Sized,
{
    sink: &'a mut Si,
    stream: Fuse<&'a mut St>,
    buffered: Option<St::Item>,
}

// Pinning is never projected to any fields
impl<Si, St> Unpin for SendAll<'_, Si, St>
where
    Si: Sink<St::Item> + Unpin + ?Sized,
    St: Stream + Unpin + ?Sized,
{}

impl<'a, Si, St> SendAll<'a, Si, St>
where
    Si: Sink<St::Item> + Unpin + ?Sized,
    St: Stream + Unpin + ?Sized,
{
    pub(super) fn new(
        sink: &'a mut Si,
        stream: &'a mut St,
    ) -> SendAll<'a, Si, St> {
        SendAll {
            sink,
            stream: stream.fuse(),
            buffered: None,
        }
    }

    fn try_start_send(
        &mut self,
        cx: &mut Context<'_>,
        item: St::Item,
    ) -> Poll<Result<(), Si::Error>> {
        debug_assert!(self.buffered.is_none());
        match Pin::new(&mut self.sink).poll_ready(cx)? {
            Poll::Ready(()) => {
                Poll::Ready(Pin::new(&mut self.sink).start_send(item))
            }
            Poll::Pending => {
                self.buffered = Some(item);
                Poll::Pending
            }
        }
    }
}

impl<Si, St> Future for SendAll<'_, Si, St>
where
    Si: Sink<St::Item> + Unpin + ?Sized,
    St: Stream + Unpin + ?Sized,
{
    type Output = Result<(), Si::Error>;

    fn poll(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Self::Output> {
        let this = &mut *self;
        // If we've got an item buffered already, we need to write it to the
        // sink before we can do anything else
        if let Some(item) = this.buffered.take() {
            ready!(this.try_start_send(cx, item))?
        }

        loop {
            match this.stream.poll_next_unpin(cx) {
                Poll::Ready(Some(item)) => {
                    ready!(this.try_start_send(cx, item))?
                }
                Poll::Ready(None) => {
                    ready!(Pin::new(&mut this.sink).poll_flush(cx))?;
                    return Poll::Ready(Ok(()))
                }
                Poll::Pending => {
                    ready!(Pin::new(&mut this.sink).poll_flush(cx))?;
                    return Poll::Pending
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use string_cache::Atom;

use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error as DeserializationError, Type as DeserializationType};

use std::cmp::PartialEq;
use std::hash::{Hash, Hasher};

/// A marker for a request that a expects a specific value.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Exactly<T> {
    /// No constraint.
    Always,

    /// Expect a specific value.
    Exactly(T),

    /// Never accept a constraint. This can happen, for instance, we have have
    /// attempted to `and` two conflicting `Exactly`
    Never,
}

impl<T> Exactly<T> where T: PartialEq {
    /// Combine two constraints.
    pub fn and(self, other: Self) -> Self {
        use self::Exactly::*;
        match (self, other) {
            (Never, _) | (_, Never) => Never,
            (Always, x) | (x, Always) => x,
            (Exactly(x), Exactly(y)) =>
                if x == y {
                    Exactly(y)
                } else {
                    Never
                }
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            Exactly::Always => true,
            _ => false,
        }
    }

    pub fn matches(&self, value: &T) -> bool {
        match *self {
            Exactly::Always => true,
            Exactly::Exactly(ref id) => id == value,
            _ => false
        }
    }
}

impl<T> Default for Exactly<T> {
    fn default() -> Self {
        Exactly::Always
    }
}

/// A variant of `PhantomData` that supports [De]serialization
#[derive(Clone, Debug, PartialEq, Hash, Eq)]
pub struct Phantom<T> {
    phantom: PhantomData<T>
}

impl<T> Default for Phantom<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Phantom<T> {
    pub fn new() -> Self {
        Phantom {
            phantom: PhantomData
        }
    }
}
impl<T> Serialize for Phantom<T> {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
            ().serialize(serializer)
    }
}
impl<T> Deserialize for Phantom<T> {
    fn deserialize<D>(_: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        // Nothing to consume
        Ok(Phantom {
            phantom: PhantomData
        })
    }
}

/// A unique id for values of a given kind.
///
/// # Performance
///
/// This data structure is tuned for specific use cases and should be used accordingly.
///
/// - Using an instances of `Id` as a key in a `HashMap` or `HashSet` is much faster than
///   using a `String`.
/// - Comparing two instances of `Id` is much faster than comparing two `String`s.
/// - Instances of `Id` take very little memory.
/// - Cloning an instance of `Id` is relatively fast, but should be avoided if possible.
/// - Calling `Id::new`, on the other hand, is *very slow*. **Always prefer cloning to calling
///   `Id::new`**.
///
/// # (De)serialization
///
/// Serialized values of this type are represented by plain strings.
///
/// ```
/// extern crate serde;
/// extern crate serde_json;
/// extern crate foxbox_taxonomy;
///
/// #[derive(Debug)]
/// struct UniqueId;
///
/// let my_id = foxbox_taxonomy::util::Id::<UniqueId>::new("Unique Identifier".to_owned());
///
/// let my_serialized_id = serde_json::to_string(&my_id).unwrap();
/// assert_eq!(my_serialized_id, "\"Unique Identifier\"");
///
/// let my_deserialized_id: foxbox_taxonomy::util::Id<UniqueId> =
///     serde_json::from_str("\"Unique Identifier\"").unwrap();
/// assert_eq!(my_deserialized_id, my_id);
/// ```
#[derive(Debug, Clone)]
pub struct Id<T> {
    id: Atom,

    phantom: Phantom<T>,
}

impl<T> Id<T> {
    pub fn new(id: String) -> Self {
        Id {
            id: Atom::from(id),
            phantom: Phantom::new(),
        }
    }

    pub fn as_atom(&self) -> &Atom {
        &self.id
    }
}

impl<T> PartialEq for Id<T> {
    fn eq(&self, other: &Self) -> bool {
        self.id.eq(&other.id)
    }
}

impl<T> Eq for Id<T> {
}

impl<T> Hash for Id<T> {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.id.hash(state)
    }
}

impl<T> Serialize for Id<T> {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        self.id.as_ref().serialize(serializer)
    }
}

impl<T> Deserialize for Id<T> {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let deserialized_string = try!(String::deserialize(deserializer));

        Ok(Id {
            id: Atom::from(deserialized_string),
            phantom: Phantom::new(),
        })
    }
}

/// A bunch of results grouped in an array of (key, result).
pub type ResultSet<I, T, E> = Vec<(I, Result<T, E>)>;

/// By default, the (de)serialization of trivial enums by Serde is surprising, e.g.
/// in JSON,  `enum Foo {A, B, C}` will produce `{"\"A\": []"}` for `A`, where `"\"A\""`
/// would be expected.
///
/// Implementing serialization is very simple, but deserialization is much more annoying.
/// This struct lets us implement simply the deserialization to a predictable and well-specified
/// list of strings.
///
/// # Example
///
/// ```
/// extern crate serde;
/// use serde::de::{Deserialize, Deserializer};
///
/// extern crate foxbox_taxonomy;
/// use foxbox_taxonomy::util::TrivialEnumVisitor;
///
/// enum Foo { A, B, C }
///
/// impl Deserialize for Foo {
///   fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
///     deserializer.visit_string(TrivialEnumVisitor::new(|source| {
///       match source {
///         "A" => Ok(Foo::A),
///         "B" => Ok(Foo::B),
///         "C" => Ok(Foo::C),
///          _ => Err(())
///       }
///    }))
///   }
/// }
///
/// # fn main() {}
/// ```
pub struct TrivialEnumVisitor<T> where T: Deserialize {
    parser: Box<Fn(&str) -> Result<T, ()>>
}

impl<T> TrivialEnumVisitor<T> where T: Deserialize {
    pub fn new<F>(parser: F) -> Self
        where F: Fn(&str) -> Result<T, ()> + 'static {
            TrivialEnumVisitor {
                parser: Box::new(parser)
            }
        }
    fn parse<E>(&self, source: &str) -> Result<T, E>
        where E: DeserializationError
    {
        (self.parser)(source)
            .map_err(|()| E::unknown_field(&source.to_owned()))
    }
}

use serde::de::Visitor;
impl<T> Visitor for TrivialEnumVisitor<T> where T: Deserialize {
    type Value = T;
    fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
        where E: DeserializationError,
    {
        self.parse(v)
    }

    fn visit_string<E>(&mut self, v: String) -> Result<T, E>
        where E: DeserializationError,
    {
        self.parse(&v)
    }

    fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<T, E>
        where E: DeserializationError,
    {
        use std::str;
        match str::from_utf8(v) {
            Ok(s) => self.parse(s),
            Err(_) => Err(E::type_mismatch(DeserializationType::String)),
        }
    }

    fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<T, E>
        where E: DeserializationError,
    {
        match String::from_utf8(v) {
            Ok(s) => self.parse(&s),
            Err(_) => Err(DeserializationError::type_mismatch(DeserializationType::String)),
        }
    }
}
<commit_msg>[fxbox/taxonomy] Issue #21 - Implement ToString for Id<commit_after>use std::marker::PhantomData;

use string_cache::Atom;

use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error as DeserializationError, Type as DeserializationType};

use std::cmp::PartialEq;
use std::hash::{Hash, Hasher};
use std::string::ToString;

/// A marker for a request that a expects a specific value.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Exactly<T> {
    /// No constraint.
    Always,

    /// Expect a specific value.
    Exactly(T),

    /// Never accept a constraint. This can happen, for instance, we have have
    /// attempted to `and` two conflicting `Exactly`
    Never,
}

impl<T> Exactly<T> where T: PartialEq {
    /// Combine two constraints.
    pub fn and(self, other: Self) -> Self {
        use self::Exactly::*;
        match (self, other) {
            (Never, _) | (_, Never) => Never,
            (Always, x) | (x, Always) => x,
            (Exactly(x), Exactly(y)) =>
                if x == y {
                    Exactly(y)
                } else {
                    Never
                }
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            Exactly::Always => true,
            _ => false,
        }
    }

    pub fn matches(&self, value: &T) -> bool {
        match *self {
            Exactly::Always => true,
            Exactly::Exactly(ref id) => id == value,
            _ => false
        }
    }
}

impl<T> Default for Exactly<T> {
    fn default() -> Self {
        Exactly::Always
    }
}

/// A variant of `PhantomData` that supports [De]serialization
#[derive(Clone, Debug, PartialEq, Hash, Eq)]
pub struct Phantom<T> {
    phantom: PhantomData<T>
}

impl<T> Default for Phantom<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Phantom<T> {
    pub fn new() -> Self {
        Phantom {
            phantom: PhantomData
        }
    }
}
impl<T> Serialize for Phantom<T> {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
            ().serialize(serializer)
    }
}
impl<T> Deserialize for Phantom<T> {
    fn deserialize<D>(_: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        // Nothing to consume
        Ok(Phantom {
            phantom: PhantomData
        })
    }
}

/// A unique id for values of a given kind.
///
/// # Performance
///
/// This data structure is tuned for specific use cases and should be used accordingly.
///
/// - Using an instances of `Id` as a key in a `HashMap` or `HashSet` is much faster than
///   using a `String`.
/// - Comparing two instances of `Id` is much faster than comparing two `String`s.
/// - Instances of `Id` take very little memory.
/// - Cloning an instance of `Id` is relatively fast, but should be avoided if possible.
/// - Calling `Id::new`, on the other hand, is *very slow*. **Always prefer cloning to calling
///   `Id::new`**.
///
/// # (De)serialization
///
/// Serialized values of this type are represented by plain strings.
///
/// ```
/// extern crate serde;
/// extern crate serde_json;
/// extern crate foxbox_taxonomy;
///
/// #[derive(Debug)]
/// struct UniqueId;
///
/// let my_id = foxbox_taxonomy::util::Id::<UniqueId>::new("Unique Identifier".to_owned());
///
/// assert_eq!(my_id.to_string(), "Unique Identifier");
///
/// let my_serialized_id = serde_json::to_string(&my_id).unwrap();
/// assert_eq!(my_serialized_id, "\"Unique Identifier\"");
///
/// let my_deserialized_id: foxbox_taxonomy::util::Id<UniqueId> =
///     serde_json::from_str("\"Unique Identifier\"").unwrap();
/// assert_eq!(my_deserialized_id, my_id);
/// ```
#[derive(Debug, Clone)]
pub struct Id<T> {
    id: Atom,

    phantom: Phantom<T>,
}

impl<T> Id<T> {
    pub fn new(id: String) -> Self {
        Id {
            id: Atom::from(id),
            phantom: Phantom::new(),
        }
    }

    pub fn as_atom(&self) -> &Atom {
        &self.id
    }
}

impl<T> ToString for Id<T> {
    fn to_string(&self) -> String {
        String::from(self.id.as_ref())
    }
}

impl<T> PartialEq for Id<T> {
    fn eq(&self, other: &Self) -> bool {
        self.id.eq(&other.id)
    }
}

impl<T> Eq for Id<T> {
}

impl<T> Hash for Id<T> {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.id.hash(state)
    }
}

impl<T> Serialize for Id<T> {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer {
        self.id.as_ref().serialize(serializer)
    }
}

impl<T> Deserialize for Id<T> {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: Deserializer {
        let deserialized_string = try!(String::deserialize(deserializer));

        Ok(Id {
            id: Atom::from(deserialized_string),
            phantom: Phantom::new(),
        })
    }
}

/// A bunch of results grouped in an array of (key, result).
pub type ResultSet<I, T, E> = Vec<(I, Result<T, E>)>;

/// By default, the (de)serialization of trivial enums by Serde is surprising, e.g.
/// in JSON,  `enum Foo {A, B, C}` will produce `{"\"A\": []"}` for `A`, where `"\"A\""`
/// would be expected.
///
/// Implementing serialization is very simple, but deserialization is much more annoying.
/// This struct lets us implement simply the deserialization to a predictable and well-specified
/// list of strings.
///
/// # Example
///
/// ```
/// extern crate serde;
/// use serde::de::{Deserialize, Deserializer};
///
/// extern crate foxbox_taxonomy;
/// use foxbox_taxonomy::util::TrivialEnumVisitor;
///
/// enum Foo { A, B, C }
///
/// impl Deserialize for Foo {
///   fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error> where D: Deserializer {
///     deserializer.visit_string(TrivialEnumVisitor::new(|source| {
///       match source {
///         "A" => Ok(Foo::A),
///         "B" => Ok(Foo::B),
///         "C" => Ok(Foo::C),
///          _ => Err(())
///       }
///    }))
///   }
/// }
///
/// # fn main() {}
/// ```
pub struct TrivialEnumVisitor<T> where T: Deserialize {
    parser: Box<Fn(&str) -> Result<T, ()>>
}

impl<T> TrivialEnumVisitor<T> where T: Deserialize {
    pub fn new<F>(parser: F) -> Self
        where F: Fn(&str) -> Result<T, ()> + 'static {
            TrivialEnumVisitor {
                parser: Box::new(parser)
            }
        }
    fn parse<E>(&self, source: &str) -> Result<T, E>
        where E: DeserializationError
    {
        (self.parser)(source)
            .map_err(|()| E::unknown_field(&source.to_owned()))
    }
}

use serde::de::Visitor;
impl<T> Visitor for TrivialEnumVisitor<T> where T: Deserialize {
    type Value = T;
    fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
        where E: DeserializationError,
    {
        self.parse(v)
    }

    fn visit_string<E>(&mut self, v: String) -> Result<T, E>
        where E: DeserializationError,
    {
        self.parse(&v)
    }

    fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<T, E>
        where E: DeserializationError,
    {
        use std::str;
        match str::from_utf8(v) {
            Ok(s) => self.parse(s),
            Err(_) => Err(E::type_mismatch(DeserializationType::String)),
        }
    }

    fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<T, E>
        where E: DeserializationError,
    {
        match String::from_utf8(v) {
            Ok(s) => self.parse(&s),
            Err(_) => Err(DeserializationError::type_mismatch(DeserializationType::String)),
        }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::rc::Rc;
use std::time::Duration;

use futures::{Future};
use futures::future::{result};
use tokio_core::reactor::{Handle, Timeout};

use telegram_bot_raw::{Request, ResponseType};

use connector::{Connector, default_connector};
use errors::Error;
use future::{TelegramFuture, NewTelegramFuture};
use stream::{NewUpdatesStream, UpdatesStream};

/// Main type for sending requests to the Telegram bot API.
#[derive(Clone)]
pub struct Api {
    inner: Rc<ApiInner>,
}

struct ApiInner {
    token: String,
    connector: Box<Connector>,
    handle: Handle,
}

#[derive(Debug)]
pub enum ConnectorConfig {
    Default,
    Specified(Box<Connector>)
}

impl Default for ConnectorConfig {
    fn default() -> Self {
        ConnectorConfig::Default
    }
}

impl ConnectorConfig {
    pub fn new(connector: Box<Connector>) -> Self {
        ConnectorConfig::Specified(connector)
    }

    pub fn take(self, handle: &Handle) -> Result<Box<Connector>, Error> {
        match self {
            ConnectorConfig::Default => default_connector(&handle),
            ConnectorConfig::Specified(connector) => Ok(connector)
        }
    }
}

/// Configuration for an `Api`.
#[derive(Debug)]
pub struct Config {
    token: String,
    connector: ConnectorConfig,
}

impl Config {
    /// Set connector type for an `Api`.
    pub fn connector(self, connector: Box<Connector>) -> Config {
        Config {
            token: self.token,
            connector: ConnectorConfig::new(connector),
        }
    }

    /// Create new `Api` instance.
    pub fn build<H: Borrow<Handle>>(self, handle: H) -> Result<Api, Error> {
        let handle = handle.borrow().clone();
        Ok(Api {
            inner: Rc::new(ApiInner {
                token: self.token,
                connector: self.connector.take(&handle)?,
                handle: handle,
            }),
        })
    }
}

impl Api {
    /// Start construction of the `Api` instance.
    ///
    /// # Examples
    ///
    /// Using default connector.
    ///
    /// ```rust
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// use telegram_bot::Api;
    /// use tokio_core::reactor::Core;
    ///
    /// # fn main() {
    /// let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// let api = Api::configure(telegram_token).build(core.handle());
    /// # }
    /// ```
    ///
    /// Using custom connector.
    ///
    ///
    /// ```rust
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # #[cfg(feature = "hyper_connector")]
    /// # fn main() {
    /// use telegram_bot::Api;
    /// use telegram_bot::connector::hyper;
    /// use tokio_core::reactor::Core;
    ///
    /// let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// let api = Api::configure(telegram_token)
    ///     .connector(hyper::default_connector(&core.handle()))
    ///     .build(core.handle());
    /// # }
    ///
    /// # #[cfg(not(feature = "hyper_connector"))]
    /// # fn main() {}
    /// ```
    pub fn configure<T: AsRef<str>>(token: T) -> Config {
        Config {
            token: token.as_ref().to_string(),
            connector: Default::default(),
        }
    }

    /// Create a stream which produces updates from the Telegram server.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # use telegram_bot::Api;
    /// # use tokio_core::reactor::Core;
    /// # fn main() {
    /// # let core = Core::new().unwrap();
    /// # let api: Api = Api::configure("token").build(core.handle());
    /// use futures::Stream;
    ///
    /// let future = api.stream().for_each(|update| {
    ///     println!("{:?}", update);
    ///     Ok(())
    /// });
    /// # }
    /// ```
    pub fn stream(&self) -> UpdatesStream {
        UpdatesStream::new(self.clone(), self.inner.handle.clone())
    }

    /// Send a request to the Telegram server and do not wait for a response.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # use futures::Future;
    /// # use telegram_bot::{Api, GetMe, ChatId};
    /// # use telegram_bot::prelude::*;
    /// # use tokio_core::reactor::Core;
    /// #
    /// # fn main() {
    /// # let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// # let api = Api::configure(telegram_token).build(core.handle());
    /// # if false {
    /// let chat = ChatId::new(61031);
    /// api.spawn(chat.text("Message"))
    /// # }
    /// # }
    pub fn spawn<Req: Request>(&self, request: Req) {
        self.inner.handle.spawn(self.send(request).then(|_| Ok(())))
    }

    /// Send a request to the Telegram server and wait for a response, timing out after `duration`.
    /// Future will resolve to `None` if timeout fired.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # use futures::Future;
    /// # use telegram_bot::{Api, GetMe};
    /// # use tokio_core::reactor::Core;
    /// #
    /// # fn main() {
    /// # let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// # let api = Api::configure(telegram_token).build(core.handle());
    /// # if false {
    /// use std::time::Duration;
    ///
    /// let future = api.send_timeout(GetMe, Duration::from_secs(5));
    /// future.and_then(|me| Ok(assert!(me.is_some())));
    /// # }
    /// # }
    /// ```
    pub fn send_timeout<Req: Request>(
        &self, request: Req, duration: Duration)
        -> TelegramFuture<Option<<Req::Response as ResponseType>::Type>> {

        let timeout_future = result(Timeout::new(duration, &self.inner.handle))
            .flatten().map_err(From::from).map(|()| None);
        let send_future = self.send(request).map(|resp| Some(resp));

        let future = timeout_future.select(send_future)
            .map(|(item, _next)| item)
            .map_err(|(item, _next)| item);

        TelegramFuture::new(Box::new(future))
    }

    /// Send a request to the Telegram server and wait for a response.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # use futures::Future;
    /// # use telegram_bot::{Api, GetMe};
    /// # use tokio_core::reactor::Core;
    /// #
    /// # fn main() {
    /// # let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// # let api = Api::configure(telegram_token).build(core.handle());
    /// # if false {
    /// let future = api.send(GetMe);
    /// future.and_then(|me| Ok(println!("{:?}", me)));
    /// # }
    /// # }
    /// ```
    pub fn send<Req: Request>(&self, request: Req)
        -> TelegramFuture<<Req::Response as ResponseType>::Type> {

        let request = request.serialize()
            .map_err(From::from);

        let request = result(request);

        let api = self.clone();
        let response = request.and_then(move |request| {
            let ref token = api.inner.token;
            api.inner.connector.request(token, request)
        });

        let future = response.and_then(move |response| {
            Req::Response::deserialize(response).map_err(From::from)
        });

        TelegramFuture::new(Box::new(future))
    }
}
<commit_msg>test: update doctests<commit_after>use std::borrow::Borrow;
use std::rc::Rc;
use std::time::Duration;

use futures::{Future};
use futures::future::{result};
use tokio_core::reactor::{Handle, Timeout};

use telegram_bot_raw::{Request, ResponseType};

use connector::{Connector, default_connector};
use errors::Error;
use future::{TelegramFuture, NewTelegramFuture};
use stream::{NewUpdatesStream, UpdatesStream};

/// Main type for sending requests to the Telegram bot API.
#[derive(Clone)]
pub struct Api {
    inner: Rc<ApiInner>,
}

struct ApiInner {
    token: String,
    connector: Box<Connector>,
    handle: Handle,
}

#[derive(Debug)]
pub enum ConnectorConfig {
    Default,
    Specified(Box<Connector>)
}

impl Default for ConnectorConfig {
    fn default() -> Self {
        ConnectorConfig::Default
    }
}

impl ConnectorConfig {
    pub fn new(connector: Box<Connector>) -> Self {
        ConnectorConfig::Specified(connector)
    }

    pub fn take(self, handle: &Handle) -> Result<Box<Connector>, Error> {
        match self {
            ConnectorConfig::Default => default_connector(&handle),
            ConnectorConfig::Specified(connector) => Ok(connector)
        }
    }
}

/// Configuration for an `Api`.
#[derive(Debug)]
pub struct Config {
    token: String,
    connector: ConnectorConfig,
}

impl Config {
    /// Set connector type for an `Api`.
    pub fn connector(self, connector: Box<Connector>) -> Config {
        Config {
            token: self.token,
            connector: ConnectorConfig::new(connector),
        }
    }

    /// Create new `Api` instance.
    pub fn build<H: Borrow<Handle>>(self, handle: H) -> Result<Api, Error> {
        let handle = handle.borrow().clone();
        Ok(Api {
            inner: Rc::new(ApiInner {
                token: self.token,
                connector: self.connector.take(&handle)?,
                handle: handle,
            }),
        })
    }
}

impl Api {
    /// Start construction of the `Api` instance.
    ///
    /// # Examples
    ///
    /// Using default connector.
    ///
    /// ```rust
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// use telegram_bot::Api;
    /// use tokio_core::reactor::Core;
    ///
    /// # fn main() {
    /// let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// let api = Api::configure(telegram_token).build(core.handle()).unwrap();
    /// # }
    /// ```
    ///
    /// Using custom connector.
    ///
    ///
    /// ```rust
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # #[cfg(feature = "hyper_connector")]
    /// # fn main() {
    /// use telegram_bot::Api;
    /// use telegram_bot::connector::hyper;
    /// use tokio_core::reactor::Core;
    ///
    /// let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// let api = Api::configure(telegram_token)
    ///     .connector(hyper::default_connector(&core.handle()).unwrap())
    ///     .build(core.handle()).unwrap();
    /// # }
    ///
    /// # #[cfg(not(feature = "hyper_connector"))]
    /// # fn main() {}
    /// ```
    pub fn configure<T: AsRef<str>>(token: T) -> Config {
        Config {
            token: token.as_ref().to_string(),
            connector: Default::default(),
        }
    }

    /// Create a stream which produces updates from the Telegram server.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # use telegram_bot::Api;
    /// # use tokio_core::reactor::Core;
    /// # fn main() {
    /// # let core = Core::new().unwrap();
    /// # let api: Api = Api::configure("token").build(core.handle()).unwrap();
    /// use futures::Stream;
    ///
    /// let future = api.stream().for_each(|update| {
    ///     println!("{:?}", update);
    ///     Ok(())
    /// });
    /// # }
    /// ```
    pub fn stream(&self) -> UpdatesStream {
        UpdatesStream::new(self.clone(), self.inner.handle.clone())
    }

    /// Send a request to the Telegram server and do not wait for a response.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # use futures::Future;
    /// # use telegram_bot::{Api, GetMe, ChatId};
    /// # use telegram_bot::prelude::*;
    /// # use tokio_core::reactor::Core;
    /// #
    /// # fn main() {
    /// # let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// # let api = Api::configure(telegram_token).build(core.handle()).unwrap();
    /// # if false {
    /// let chat = ChatId::new(61031);
    /// api.spawn(chat.text("Message"))
    /// # }
    /// # }
    pub fn spawn<Req: Request>(&self, request: Req) {
        self.inner.handle.spawn(self.send(request).then(|_| Ok(())))
    }

    /// Send a request to the Telegram server and wait for a response, timing out after `duration`.
    /// Future will resolve to `None` if timeout fired.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # use futures::Future;
    /// # use telegram_bot::{Api, GetMe};
    /// # use tokio_core::reactor::Core;
    /// #
    /// # fn main() {
    /// # let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// # let api = Api::configure(telegram_token).build(core.handle()).unwrap();
    /// # if false {
    /// use std::time::Duration;
    ///
    /// let future = api.send_timeout(GetMe, Duration::from_secs(5));
    /// future.and_then(|me| Ok(assert!(me.is_some())));
    /// # }
    /// # }
    /// ```
    pub fn send_timeout<Req: Request>(
        &self, request: Req, duration: Duration)
        -> TelegramFuture<Option<<Req::Response as ResponseType>::Type>> {

        let timeout_future = result(Timeout::new(duration, &self.inner.handle))
            .flatten().map_err(From::from).map(|()| None);
        let send_future = self.send(request).map(|resp| Some(resp));

        let future = timeout_future.select(send_future)
            .map(|(item, _next)| item)
            .map_err(|(item, _next)| item);

        TelegramFuture::new(Box::new(future))
    }

    /// Send a request to the Telegram server and wait for a response.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate telegram_bot;
    /// # extern crate tokio_core;
    /// # use futures::Future;
    /// # use telegram_bot::{Api, GetMe};
    /// # use tokio_core::reactor::Core;
    /// #
    /// # fn main() {
    /// # let core = Core::new().unwrap();
    /// # let telegram_token = "token";
    /// # let api = Api::configure(telegram_token).build(core.handle()).unwrap();
    /// # if false {
    /// let future = api.send(GetMe);
    /// future.and_then(|me| Ok(println!("{:?}", me)));
    /// # }
    /// # }
    /// ```
    pub fn send<Req: Request>(&self, request: Req)
        -> TelegramFuture<<Req::Response as ResponseType>::Type> {

        let request = request.serialize()
            .map_err(From::from);

        let request = result(request);

        let api = self.clone();
        let response = request.and_then(move |request| {
            let ref token = api.inner.token;
            api.inner.connector.request(token, request)
        });

        let future = response.and_then(move |response| {
            Req::Response::deserialize(response).map_err(From::from)
        });

        TelegramFuture::new(Box::new(future))
    }
}
<|endoftext|>


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

#![forbid(unsafe_code)]

//! # Serde Reflection (experimental)
//!
//! This crate provides a way to extract IDL-like format descriptions for Rust containers
//! that implement the Serialize and/or Deserialize trait(s) of Serde.
//!
//! # Overview
//!
//! In the following example, we extract the Serde-generated data-format of two containers
//! `Name` and `Person`. We also demonstrate how to handle a custom
//! implementation of `ser::de::Deserialize` that would enforce user-defined invariants
//! for `Name` values.
//!
//! ```rust
//! # use libra_serde_reflection::*;
//! # use serde::{Deserialize, Serialize};
//! #[derive(Serialize, PartialEq, Eq, Debug, Clone)]
//! struct Name(String);
//! // impl<'de> Deserialize<'de> for Name { ... }
//! #
//! # impl<'de> Deserialize<'de> for Name {
//! #     fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
//! #     where
//! #         D: ::serde::Deserializer<'de>,
//! #     {
//! #         // Make sure to wrap our value in a container with the same name
//! #         // as the original type.
//! #         #[derive(Deserialize)]
//! #         #[serde(rename = "Name")]
//! #         struct InternalValue(String);
//! #
//! #         let value = InternalValue::deserialize(deserializer)?.0;
//! #         // Enforce some custom invariant
//! #         if value.len() >= 2 && value.chars().all(char::is_alphabetic) {
//! #             Ok(Name(value))
//! #         } else {
//! #             Err(<D::Error as ::serde::de::Error>::custom(format!(
//! #                 "Invalid name {}",
//! #                 value
//! #             )))
//! #         }
//! #     }
//! # }
//!
//! #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
//! enum Person {
//!     NickName(Name),
//!     FullName { first: Name, last: Name },
//! }
//!
//! # fn main() -> Result<(), Error> {
//! // Start a session to trace formats.
//! let mut tracer = Tracer::new(/* is_human_readable */ false);
//!
//! // For every type (here `Name`), if a user-defined implementation of `Deserialize` exists and
//! // is known to perform custom validation checks, start by tracing the serialization of
//! // a valid value of this type.
//! let bob = Name("Bob".into());
//! tracer.trace_value(&bob)?;
//!
//! // Now, let's trace deserialization for the top-level type `Person`.
//! let (format, values) = tracer.trace_type::<Person>()?;
//! assert_eq!(format, Format::TypeName("Person".into()));
//!
//! // As a byproduct, we have also obtained sample values of type `Person`.
//! // We can see that the user-provided value `bob` was used consistently to pass
//! // validation checks for `Name`.
//! assert_eq!(values[0], Person::NickName(bob.clone()));
//! assert_eq!(values[1], Person::FullName { first: bob.clone(), last: bob.clone() });
//!
//! // We have no more top-level types to trace, so let's stop the tracing session and obtain
//! // a final registry of containers.
//! let registry = tracer.registry()?;
//!
//! // We have successfully extracted a format description of all Serde containers under `Person`.
//! assert_eq!(
//!     registry.get("Name").unwrap(),
//!     &ContainerFormat::NewTypeStruct(Box::new(Format::Str)),
//! );
//! match registry.get("Person").unwrap() {
//!     ContainerFormat::Enum(variants) => assert_eq!(variants.len(), 2),
//!      _ => panic!(),
//! };
//!
//! // Export the registry in YAML.
//! let data = serde_yaml::to_string(&registry).unwrap() + "\n";
//! assert_eq!(&data, r#"---
//! Name:
//!   NEWTYPESTRUCT: STR
//! Person:
//!   ENUM:
//!     0:
//!       NickName:
//!         NEWTYPE:
//!           TYPENAME: Name
//!     1:
//!       FullName:
//!         STRUCT:
//!           - first:
//!               TYPENAME: Name
//!           - last:
//!               TYPENAME: Name
//! "#);
//! # Ok(())
//! # }
//! ```
//!
//! # Tracing Serialization with `trace_value(v)`
//!
//! Tracing the serialization of a Rust value `v` consists of visiting the structural
//! components of `v` in depth and recording Serde formats for all the visited types.
//!
//! ```rust
//! # use libra_serde_reflection::*;
//! # use serde::Serialize;
//! #[derive(Serialize)]
//! struct FullName<'a> {
//!   first: &'a str,
//!   middle: Option<&'a str>,
//!   last: &'a str,
//! }
//!
//! # fn main() -> Result<(), Error> {
//! let mut tracer = Tracer::new(/* is_human_readable */ false);
//! tracer.trace_value(&FullName { first: "", middle: Some(""), last: "" })?;
//! let registry = tracer.registry()?;
//! match registry.get("FullName").unwrap() {
//!     ContainerFormat::Struct(fields) => assert_eq!(fields.len(), 3),
//!     _ => panic!(),
//! };
//! # Ok(())
//! # }
//! ```
//!
//! This approach works well but it can only recover the formats of datatypes for which
//! nontrivial samples have been provided:
//!
//! * In enums, only the variants explicitly covered by user samples will be recorded.
//!
//! * Providing a `None` value or an empty vector `[]` within a sample may result in
//! formats that are partially unknown.
//!
//! ```rust
//! # use libra_serde_reflection::*;
//! # use serde::Serialize;
//! # #[derive(Serialize)]
//! # struct FullName<'a> {
//! #   first: &'a str,
//! #   middle: Option<&'a str>,
//! #   last: &'a str,
//! # }
//! # fn main() -> Result<(), Error> {
//! let mut tracer = Tracer::new(/* is_human_readable */ false);
//! tracer.trace_value(&FullName { first: "", middle: None, last: "" })?;
//! assert_eq!(tracer.registry().unwrap_err(), Error::UnknownFormatInContainer("FullName"));
//! # Ok(())
//! # }
//! ```
//!
//! For this reason, we introduce a complementary set of APIs to trace deserialization of types.
//!
//! # Tracing Deserialization with `trace_type<T>()`
//!
//! Deserialization-tracing APIs take the current tracing state `&mut self` and a type `T`
//! as input.
//!
//! ## Core Algorithm and High-Level API
//!
//! The core algorithm `trace_type_once<T>()`
//! attempts to reconstruct a witness value of type `T` by exploring the graph of all the types
//! occurring in the definition of `T`. At the same time, the algorithm records the
//! formats of all the visited structs and enum variants.
//!
//! For the exploration to be able to terminate, the core algorithm `trace_type_once` explores
//! possible recursion points only once (see definition below).
//! In particular, if `T` is an enum, `trace_type_once` discovers only one variant at a time.
//!
//! For this reason, the high-level API `trace_type<T>()`
//! will repeat calls to `trace_type_once` until all the variants of `T` are known.
//! Variant cases of `T` are explored in sequential order, starting with index `0`.
//!
//! ## Coverage Guarantees
//!
//! Under the assumptions listed below, a single call to `trace_type<T>()` is guaranteed to
//! record the formats of all the types that `T` depends on.
//!
//! (0) Container names must not collide. (TODO: handle this using `std::any::type_name`?)
//!
//! (1) The first variants of mutually recursive enums must be a "base case". That is,
//! defaulting to the first variant for every enum type (along with `None` for option values
//! and `[]` for sequences) must guarantee termination of depth-first traversals of the graph of type
//! declarations.
//!
//! (2) If a type runs custom validation checks during deserialization, sample values must have been provided
//! previously by calling `trace_value`. Besides, the corresponding registered formats
//! must not contain `Unknown` parts.
//!
//! ## Design Considerations
//!
//! Whenever we traverse the graph of type declarations using deserialization callbacks, the type
//! system requires us to return valid Rust values of type `V::Value`, where `V` is the type of
//! a given `visitor`. This contraint limits the way we can stop graph traversal to only a few cases.
//!
//! The first 3 cases are what we have called *possible recursion points* above:
//!
//! * while visiting an `Option<T>` for the second time, we choose to return the value `None` to stop;
//! * while visiting an `Seq<T>` for the second time, we choose to return the empty sequence `[]`;
//! * while visiting an `enum T` for the second time, we choose to return the first variant, i.e.
//! a "base case" by assumption (1) above.
//!
//! In addition to these 3 cases,
//!
//! * while visiting a container (one of the 5 types), if the container's name is mapped to a recorded value,
//! we MAY decide to use it.
//!
//! Currently, we always pick the recorded value for a NewTypeStruct and never do in the other cases.
//! (TODO: decide what to do)

mod de;
mod error;
mod format;
mod ser;
mod trace;
mod value;

pub use error::{Error, Result};
pub use format::{ContainerFormat, Format, Named, VariantFormat};
pub use trace::{Registry, RegistryOwned, Tracer};
pub use value::Value;
<commit_msg>[serde reflection] doc nits<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

//! # Serde Reflection (experimental)
//!
//! This crate provides a way to extract IDL-like format descriptions for Rust containers
//! that implement the Serialize and/or Deserialize trait(s) of Serde.
//!
//! # Overview
//!
//! In the following example, we extract the Serde-generated data-format of two containers
//! `Name` and `Person`. We also demonstrate how to handle a custom
//! implementation of `ser::de::Deserialize` that would enforce user-defined invariants
//! for `Name` values.
//!
//! ```rust
//! # use libra_serde_reflection::*;
//! # use serde::{Deserialize, Serialize};
//! #[derive(Serialize, PartialEq, Eq, Debug, Clone)]
//! struct Name(String);
//! // impl<'de> Deserialize<'de> for Name { ... }
//! #
//! # impl<'de> Deserialize<'de> for Name {
//! #     fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
//! #     where
//! #         D: ::serde::Deserializer<'de>,
//! #     {
//! #         // Make sure to wrap our value in a container with the same name
//! #         // as the original type.
//! #         #[derive(Deserialize)]
//! #         #[serde(rename = "Name")]
//! #         struct InternalValue(String);
//! #
//! #         let value = InternalValue::deserialize(deserializer)?.0;
//! #         // Enforce some custom invariant
//! #         if value.len() >= 2 && value.chars().all(char::is_alphabetic) {
//! #             Ok(Name(value))
//! #         } else {
//! #             Err(<D::Error as ::serde::de::Error>::custom(format!(
//! #                 "Invalid name {}",
//! #                 value
//! #             )))
//! #         }
//! #     }
//! # }
//!
//! #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)]
//! enum Person {
//!     NickName(Name),
//!     FullName { first: Name, last: Name },
//! }
//!
//! # fn main() -> Result<(), Error> {
//! // Start a session to trace formats.
//! let mut tracer = Tracer::new(/* is_human_readable */ false);
//!
//! // For every type (here `Name`), if a user-defined implementation of `Deserialize` exists and
//! // is known to perform custom validation checks, start by tracing the serialization of
//! // a valid value of this type.
//! let bob = Name("Bob".into());
//! tracer.trace_value(&bob)?;
//!
//! // Now, let's trace deserialization for the top-level type `Person`.
//! let (format, values) = tracer.trace_type::<Person>()?;
//! assert_eq!(format, Format::TypeName("Person".into()));
//!
//! // As a byproduct, we have also obtained sample values of type `Person`.
//! // We can see that the user-provided value `bob` was used consistently to pass
//! // validation checks for `Name`.
//! assert_eq!(values[0], Person::NickName(bob.clone()));
//! assert_eq!(values[1], Person::FullName { first: bob.clone(), last: bob.clone() });
//!
//! // We have no more top-level types to trace, so let's stop the tracing session and obtain
//! // a final registry of containers.
//! let registry = tracer.registry()?;
//!
//! // We have successfully extracted a format description of all Serde containers under `Person`.
//! assert_eq!(
//!     registry.get("Name").unwrap(),
//!     &ContainerFormat::NewTypeStruct(Box::new(Format::Str)),
//! );
//! match registry.get("Person").unwrap() {
//!     ContainerFormat::Enum(variants) => assert_eq!(variants.len(), 2),
//!      _ => panic!(),
//! };
//!
//! // Export the registry in YAML.
//! let data = serde_yaml::to_string(&registry).unwrap() + "\n";
//! assert_eq!(&data, r#"---
//! Name:
//!   NEWTYPESTRUCT: STR
//! Person:
//!   ENUM:
//!     0:
//!       NickName:
//!         NEWTYPE:
//!           TYPENAME: Name
//!     1:
//!       FullName:
//!         STRUCT:
//!           - first:
//!               TYPENAME: Name
//!           - last:
//!               TYPENAME: Name
//! "#);
//! # Ok(())
//! # }
//! ```
//!
//! # Tracing Serialization with `trace_value(v)`
//!
//! Tracing the serialization of a Rust value `v` consists of visiting the structural
//! components of `v` in depth and recording Serde formats for all the visited types.
//!
//! ```rust
//! # use libra_serde_reflection::*;
//! # use serde::Serialize;
//! #[derive(Serialize)]
//! struct FullName<'a> {
//!   first: &'a str,
//!   middle: Option<&'a str>,
//!   last: &'a str,
//! }
//!
//! # fn main() -> Result<(), Error> {
//! let mut tracer = Tracer::new(/* is_human_readable */ false);
//! tracer.trace_value(&FullName { first: "", middle: Some(""), last: "" })?;
//! let registry = tracer.registry()?;
//! match registry.get("FullName").unwrap() {
//!     ContainerFormat::Struct(fields) => assert_eq!(fields.len(), 3),
//!     _ => panic!(),
//! };
//! # Ok(())
//! # }
//! ```
//!
//! This approach works well but it can only recover the formats of datatypes for which
//! nontrivial samples have been provided:
//!
//! * In enums, only the variants explicitly covered by user samples will be recorded.
//!
//! * Providing a `None` value or an empty vector `[]` within a sample may result in
//! formats that are partially unknown.
//!
//! ```rust
//! # use libra_serde_reflection::*;
//! # use serde::Serialize;
//! # #[derive(Serialize)]
//! # struct FullName<'a> {
//! #   first: &'a str,
//! #   middle: Option<&'a str>,
//! #   last: &'a str,
//! # }
//! # fn main() -> Result<(), Error> {
//! let mut tracer = Tracer::new(/* is_human_readable */ false);
//! tracer.trace_value(&FullName { first: "", middle: None, last: "" })?;
//! assert_eq!(tracer.registry().unwrap_err(), Error::UnknownFormatInContainer("FullName"));
//! # Ok(())
//! # }
//! ```
//!
//! For this reason, we introduce a complementary set of APIs to trace deserialization of types.
//!
//! # Tracing Deserialization with `trace_type<T>()`
//!
//! Deserialization-tracing APIs take the current tracing state `&mut self` and a type `T`
//! as input.
//!
//! ## Core Algorithm and High-Level API
//!
//! The core algorithm `trace_type_once<T>()`
//! attempts to reconstruct a witness value of type `T` by exploring the graph of all the types
//! occurring in the definition of `T`. At the same time, the algorithm records the
//! formats of all the visited structs and enum variants.
//!
//! For the exploration to be able to terminate, the core algorithm `trace_type_once<T>()` explores
//! each possible recursion point only once (see paragraph below).
//! In particular, if `T` is an enum, `trace_type_once<T>()` discovers only one variant at a time.
//!
//! For this reason, the high-level API `trace_type<T>()`
//! will repeat calls to `trace_type_once<T>()` until all the variants of `T` are known.
//! Variant cases of `T` are explored in sequential order, starting with index `0`.
//!
//! ## Coverage Guarantees
//!
//! Under the assumptions listed below, a single call to `trace_type<T>()` is guaranteed to
//! record the formats of all the types that `T` depends on.
//!
//! (0) Container names must not collide. (TODO: handle this using `std::any::type_name`?)
//!
//! (1) The first variants of mutually recursive enums must be a "base case". That is,
//! defaulting to the first variant for every enum type (along with `None` for option values
//! and `[]` for sequences) must guarantee termination of depth-first traversals of the graph of type
//! declarations.
//!
//! (2) If a type runs custom validation checks during deserialization, sample values must have been provided
//! previously by calling `trace_value`. Besides, the corresponding registered formats
//! must not contain `Unknown` parts.
//!
//! ## Design Considerations
//!
//! Whenever we traverse the graph of type declarations using deserialization callbacks, the type
//! system requires us to return valid Rust values of type `V::Value`, where `V` is the type of
//! a given `visitor`. This contraint limits the way we can stop graph traversal to only a few cases.
//!
//! The first 3 cases are what we have called *possible recursion points* above:
//!
//! * while visiting an `Option<T>` for the second time, we choose to return the value `None` to stop;
//! * while visiting an `Seq<T>` for the second time, we choose to return the empty sequence `[]`;
//! * while visiting an `enum T` for the second time, we choose to return the first variant, i.e.
//! a "base case" by assumption (1) above.
//!
//! In addition to these 3 cases,
//!
//! * while visiting a container, if the container's name is mapped to a recorded value,
//! we MAY decide to use it.
//!
//! Currently, we always pick the recorded value for a NewTypeStruct and never do in the other cases.
//! (TODO: decide what to do)

mod de;
mod error;
mod format;
mod ser;
mod trace;
mod value;

pub use error::{Error, Result};
pub use format::{ContainerFormat, Format, Named, VariantFormat};
pub use trace::{Registry, RegistryOwned, Tracer};
pub use value::Value;
<|endoftext|>


<commit_before>//! Time granularity units used in kekbit.
use std::time::Duration;
use std::time::{SystemTime, UNIX_EPOCH};

///A TickUnit represents a specific time duration but does not maintain time information, it only helps define the time granularity
///required to used in various contexts by all kekbit components which *share a given channel*.
///For each channel it's TickUnit will be spcified at creation and will *never be changed*
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub enum TickUnit {
    ///TickUnit representing one thousandth of a microsecond.
    Nanos,
    ///TickUnit representing one thousandth of a millisecond.
    Micros,
    ///TickUnit representing one thousandth of a second.
    Millis,
    ///TickUnit representing one second.
    Secs,
}

impl TickUnit {
    ///Returns the unique u8 id assigned to every TickUnit. This id it's used for serialization it would never change.
    ///
    /// #Examples
    /// ```
    /// use kekbit_core::tick::TickUnit::*;
    ///
    /// assert_eq!(Nanos.id(), 9);
    /// assert_eq!(Micros.id(), 6);
    /// assert_eq!(Millis.id(), 3);
    /// assert_eq!(Secs.id(), 0);
    /// ```
    #[inline]
    pub fn id(&self) -> u8 {
        match self {
            TickUnit::Nanos => 9,
            TickUnit::Micros => 6,
            TickUnit::Millis => 3,
            TickUnit::Secs => 0,
        }
    }

    /// Returns the tick unit with the given id
    ///
    /// # Arguments
    ///
    /// * `id` - The identifier of the tick unit as u8. In the curent kekbit version it must be **0, 3, 6 or 9**
    ///
    /// # Panics
    ///
    /// If the specified id has no tick unit attached
    ///
    #[inline]
    pub fn from_id(id: u8) -> TickUnit {
        match id {
            9 => TickUnit::Nanos,
            6 => TickUnit::Micros,
            3 => TickUnit::Millis,
            0 => TickUnit::Secs,
            _ => panic!("Unknown time unit id {}", id),
        }
    }
    /// Returns the total number of tick units contained by this `Duration` as a u64.
    /// If the tiemstamp size is longer than 64 bits, it will be truncated to the lower 64 bits
    ///
    /// # Examples
    ///
    /// ```
    /// use std::time::Duration;
    /// use kekbit_core::tick::TickUnit::*;
    ///
    ///let duration = Duration::new(1, 500_000_000); //1 sec and a half
    ///assert_eq!(Nanos.convert(duration), 1_500_000_000);
    ///assert_eq!(Micros.convert(duration), 1_500_000);
    ///assert_eq!(Millis.convert(duration), 1_500);
    ///assert_eq!(Secs.convert(duration), 1);
    /// ```
    #[inline]
    pub fn convert(&self, duration: Duration) -> u64 {
        match self {
            TickUnit::Nanos => duration.as_nanos() as u64,
            TickUnit::Micros => duration.as_micros() as u64,
            TickUnit::Millis => duration.as_millis() as u64,
            TickUnit::Secs => duration.as_secs(),
        }
    }
    ///Returns the difference, measured in the current tick unit, between the current time and midnight, January 1, 1970 UTC.
    ///
    /// # Examples
    ///  ```
    /// use kekbit_core::tick::TickUnit::*;
    ///
    /// println!("{}ms since January 1, 1970 UTC", Millis.nix_time());
    /// ```
    #[inline]
    pub fn nix_time(&self) -> u64 {
        self.convert(SystemTime::now().duration_since(UNIX_EPOCH).unwrap())
    }
}

#[cfg(test)]
mod tests {
    use super::TickUnit::*;
    use super::*;
    use std::time::Duration;
    #[test]
    fn check_ids_symetry() {
        assert_eq!(Nanos.id(), TickUnit::from_id(Nanos.id()).id());
        assert_eq!(Micros.id(), TickUnit::from_id(Micros.id()).id());
        assert_eq!(Millis.id(), TickUnit::from_id(Millis.id()).id());
        assert_eq!(Secs.id(), TickUnit::from_id(Secs.id()).id());
    }

    #[test]
    #[should_panic]
    fn check_wrong_id() {
        TickUnit::from_id(123);
    }

    #[test]
    fn test_coversion() {
        let duration = Duration::new(1, 500_000_000); //1 sec and a half
        assert_eq!(Nanos.convert(duration), 1_500_000_000);
        assert_eq!(Micros.convert(duration), 1_500_000);
        assert_eq!(Millis.convert(duration), 1_500);
        assert_eq!(Secs.convert(duration), 1);
    }

    #[test]
    fn check_ids() {
        assert_eq!(Nanos.id(), 9);
        assert_eq!(Micros.id(), 6);
        assert_eq!(Millis.id(), 3);
        assert_eq!(Secs.id(), 0);
    }

    #[test]
    fn check_nix_time() {
        let t1 = Nanos.nix_time();
        let t2 = Nanos.nix_time();
        assert!(t1 <= t2);
    }
}
<commit_msg>Pass self by value as is only 1 byte in size.<commit_after>//! Time granularity units used in kekbit.
use std::time::Duration;
use std::time::{SystemTime, UNIX_EPOCH};

///A TickUnit represents a specific time duration but does not maintain time information, it only helps define the time granularity
///required to used in various contexts by all kekbit components which *share a given channel*.
///For each channel it's TickUnit will be spcified at creation and will *never be changed*
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub enum TickUnit {
    ///TickUnit representing one thousandth of a microsecond.
    Nanos,
    ///TickUnit representing one thousandth of a millisecond.
    Micros,
    ///TickUnit representing one thousandth of a second.
    Millis,
    ///TickUnit representing one second.
    Secs,
}

impl TickUnit {
    ///Returns the unique u8 id assigned to every TickUnit. This id it's used for serialization it would never change.
    ///
    /// #Examples
    /// ```
    /// use kekbit_core::tick::TickUnit::*;
    ///
    /// assert_eq!(Nanos.id(), 9);
    /// assert_eq!(Micros.id(), 6);
    /// assert_eq!(Millis.id(), 3);
    /// assert_eq!(Secs.id(), 0);
    /// ```
    #[inline]
    pub fn id(self) -> u8 {
        match self {
            TickUnit::Nanos => 9,
            TickUnit::Micros => 6,
            TickUnit::Millis => 3,
            TickUnit::Secs => 0,
        }
    }

    /// Returns the tick unit with the given id
    ///
    /// # Arguments
    ///
    /// * `id` - The identifier of the tick unit as u8. In the curent kekbit version it must be **0, 3, 6 or 9**
    ///
    /// # Panics
    ///
    /// If the specified id has no tick unit attached
    ///
    #[inline]
    pub fn from_id(id: u8) -> TickUnit {
        match id {
            9 => TickUnit::Nanos,
            6 => TickUnit::Micros,
            3 => TickUnit::Millis,
            0 => TickUnit::Secs,
            _ => panic!("Unknown time unit id {}", id),
        }
    }
    /// Returns the total number of tick units contained by this `Duration` as a u64.
    /// If the tiemstamp size is longer than 64 bits, it will be truncated to the lower 64 bits
    ///
    /// # Examples
    ///
    /// ```
    /// use std::time::Duration;
    /// use kekbit_core::tick::TickUnit::*;
    ///
    ///let duration = Duration::new(1, 500_000_000); //1 sec and a half
    ///assert_eq!(Nanos.convert(duration), 1_500_000_000);
    ///assert_eq!(Micros.convert(duration), 1_500_000);
    ///assert_eq!(Millis.convert(duration), 1_500);
    ///assert_eq!(Secs.convert(duration), 1);
    /// ```
    #[inline]
    pub fn convert(self, duration: Duration) -> u64 {
        match self {
            TickUnit::Nanos => duration.as_nanos() as u64,
            TickUnit::Micros => duration.as_micros() as u64,
            TickUnit::Millis => duration.as_millis() as u64,
            TickUnit::Secs => duration.as_secs(),
        }
    }
    ///Returns the difference, measured in the current tick unit, between the current time and midnight, January 1, 1970 UTC.
    ///
    /// # Examples
    ///  ```
    /// use kekbit_core::tick::TickUnit::*;
    ///
    /// println!("{}ms since January 1, 1970 UTC", Millis.nix_time());
    /// ```
    #[inline]
    pub fn nix_time(self) -> u64 {
        self.convert(SystemTime::now().duration_since(UNIX_EPOCH).unwrap())
    }
}

#[cfg(test)]
mod tests {
    use super::TickUnit::*;
    use super::*;
    use std::time::Duration;
    #[test]
    fn check_ids_symetry() {
        assert_eq!(Nanos.id(), TickUnit::from_id(Nanos.id()).id());
        assert_eq!(Micros.id(), TickUnit::from_id(Micros.id()).id());
        assert_eq!(Millis.id(), TickUnit::from_id(Millis.id()).id());
        assert_eq!(Secs.id(), TickUnit::from_id(Secs.id()).id());
    }

    #[test]
    #[should_panic]
    fn check_wrong_id() {
        TickUnit::from_id(123);
    }

    #[test]
    fn test_coversion() {
        let duration = Duration::new(1, 500_000_000); //1 sec and a half
        assert_eq!(Nanos.convert(duration), 1_500_000_000);
        assert_eq!(Micros.convert(duration), 1_500_000);
        assert_eq!(Millis.convert(duration), 1_500);
        assert_eq!(Secs.convert(duration), 1);
    }

    #[test]
    fn check_ids() {
        assert_eq!(Nanos.id(), 9);
        assert_eq!(Micros.id(), 6);
        assert_eq!(Millis.id(), 3);
        assert_eq!(Secs.id(), 0);
    }

    #[test]
    fn check_nix_time() {
        let t1 = Nanos.nix_time();
        let t2 = Nanos.nix_time();
        assert!(t1 <= t2);
    }
}
<|endoftext|>


<commit_before>/// === Sym bindings ===
/// Local symbol.
pub const STB_LOCAL: u8 = 0;
/// Global symbol.
pub const STB_GLOBAL: u8 = 1;
/// Weak symbol.
pub const STB_WEAK: u8 = 2;
/// Number of defined types..
pub const STB_NUM: u8 = 3;
/// Start of OS-specific.
pub const STB_LOOS: u8 = 10;
/// Unique symbol..
pub const STB_GNU_UNIQUE: u8 = 10;
/// End of OS-specific.
pub const STB_HIOS: u8 = 12;
/// Start of processor-specific.
pub const STB_LOPROC: u8 = 13;
/// End of processor-specific.
pub const STB_HIPROC: u8 = 15;

/// === Sym types ===
/// Symbol type is unspecified.
pub const STT_NOTYPE: u8 = 0;
/// Symbol is a data object.
pub const STT_OBJECT: u8 = 1;
/// Symbol is a code object.
pub const STT_FUNC: u8 = 2;
/// Symbol associated with a section.
pub const STT_SECTION: u8 = 3;
/// Symbol's name is file name.
pub const STT_FILE: u8 = 4;
/// Symbol is a common data object.
pub const STT_COMMON: u8 = 5;
/// Symbol is thread-local data object.
pub const STT_TLS: u8 = 6;
/// Number of defined types.
pub const STT_NUM: u8 = 7;
/// Start of OS-specific.
pub const STT_LOOS: u8 = 10;
/// Symbol is indirect code object.
pub const STT_GNU_IFUNC: u8 = 10;
/// End of OS-specific.
pub const STT_HIOS: u8 = 12;
/// Start of processor-specific.
pub const STT_LOPROC: u8 = 13;
/// End of processor-specific.
pub const STT_HIPROC: u8 = 15;

/// Get the ST binding.
///
/// This is the first four bits of the byte.
#[inline]
pub fn st_bind(info: u8) -> u8 {
    info >> 4
}

/// Get the ST type.
///
/// This is the last four bits of the byte.
#[inline]
pub fn st_type(info: u8) -> u8 {
    info & 0xf
}

/// Is this information defining an import?
#[inline]
pub fn is_import(info: u8, value: u64) -> bool {
    let binding = st_bind(info);
    binding == STB_GLOBAL && value == 0
}

/// Convenience function to get the &'static str type from the symbols `st_info`.
pub fn get_type(info: u8) -> &'static str {
    type_to_str(st_type(info))
}

/// Get the string for some binding.
#[inline]
pub fn bind_to_str(typ: u8) -> &'static str {
    match typ {
        STB_LOCAL => "LOCAL",
        STB_GLOBAL => "GLOBAL",
        STB_WEAK => "WEAK",
        STB_NUM => "NUM",
        STB_GNU_UNIQUE => "GNU_UNIQUE",
        _ => "UNKNOWN_STB",
    }
}

/// Get the string for some type.
#[inline]
pub fn type_to_str(typ: u8) -> &'static str {
    match typ {
        STT_NOTYPE => "NOTYPE",
        STT_OBJECT => "OBJECT",
        STT_FUNC => "FUNC",
        STT_SECTION => "SECTION",
        STT_FILE => "FILE",
        STT_COMMON => "COMMON",
        STT_TLS => "TLS",
        STT_NUM => "NUM",
        STT_GNU_IFUNC => "GNU_IFUNC",
        _ => "UNKNOWN_STT",
    }
}

macro_rules! elf_sym_impure_impl {
        ($from_fd_endian:item) => {

            #[cfg(not(feature = "pure"))]
            pub use self::impure::*;

            #[cfg(not(feature = "pure"))]
            mod impure {

                use std::fs::File;
                use std::io::Read;
                use std::io::Seek;
                use std::io::SeekFrom::Start;
                use std::io;
                use std::fmt;
                use std::slice;

                use super::*;

                impl Sym {
                   pub fn is_import(&self) -> bool {
                     let binding = self.st_info >> 4;
                     binding == STB_GLOBAL && self.st_value == 0
                   }
                }

                impl fmt::Debug for Sym {
                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        let bind = st_bind(self.st_info);
                        let typ = st_type(self.st_info);
                        write!(f,
                               "st_name: {} {} {} st_other: {} st_shndx: {} st_value: {:x} st_size: {}",
                               self.st_name,
                               bind_to_str(bind),
                               type_to_str(typ),
                               self.st_other,
                               self.st_shndx,
                               self.st_value,
                               self.st_size)
                    }
                }

                pub unsafe fn from_raw<'a>(symp: *const Sym, count: usize) -> &'a [Sym] {
                    slice::from_raw_parts(symp, count)
                }

                #[cfg(feature = "no_endian_fd")]
                pub fn from_fd<'a>(fd: &mut File, offset: usize, count: usize, _: bool) -> io::Result<Vec<Sym>> {
                    // TODO: AFAIK this shouldn't work, since i pass in a byte size...
                    // FIX THIS, unecessary allocations + unsafety here
                    let mut bytes = vec![0u8; count * SIZEOF_SYM];
                    try!(fd.seek(Start(offset as u64)));
                    try!(fd.read(&mut bytes));
                    let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr() as *mut Sym, count) };
                    let mut syms = Vec::with_capacity(count);
                    syms.extend_from_slice(bytes);
                    syms.dedup();
                    Ok(syms)
                }

                #[cfg(not(feature = "no_endian_fd"))]
                $from_fd_endian

            }
        };
    }
<commit_msg>elf.sym: add is_function method; docs<commit_after>/// === Sym bindings ===
/// Local symbol.
pub const STB_LOCAL: u8 = 0;
/// Global symbol.
pub const STB_GLOBAL: u8 = 1;
/// Weak symbol.
pub const STB_WEAK: u8 = 2;
/// Number of defined types..
pub const STB_NUM: u8 = 3;
/// Start of OS-specific.
pub const STB_LOOS: u8 = 10;
/// Unique symbol..
pub const STB_GNU_UNIQUE: u8 = 10;
/// End of OS-specific.
pub const STB_HIOS: u8 = 12;
/// Start of processor-specific.
pub const STB_LOPROC: u8 = 13;
/// End of processor-specific.
pub const STB_HIPROC: u8 = 15;

/// === Sym types ===
/// Symbol type is unspecified.
pub const STT_NOTYPE: u8 = 0;
/// Symbol is a data object.
pub const STT_OBJECT: u8 = 1;
/// Symbol is a code object.
pub const STT_FUNC: u8 = 2;
/// Symbol associated with a section.
pub const STT_SECTION: u8 = 3;
/// Symbol's name is file name.
pub const STT_FILE: u8 = 4;
/// Symbol is a common data object.
pub const STT_COMMON: u8 = 5;
/// Symbol is thread-local data object.
pub const STT_TLS: u8 = 6;
/// Number of defined types.
pub const STT_NUM: u8 = 7;
/// Start of OS-specific.
pub const STT_LOOS: u8 = 10;
/// Symbol is indirect code object.
pub const STT_GNU_IFUNC: u8 = 10;
/// End of OS-specific.
pub const STT_HIOS: u8 = 12;
/// Start of processor-specific.
pub const STT_LOPROC: u8 = 13;
/// End of processor-specific.
pub const STT_HIPROC: u8 = 15;

/// Get the ST binding.
///
/// This is the first four bits of the byte.
#[inline]
pub fn st_bind(info: u8) -> u8 {
    info >> 4
}

/// Get the ST type.
///
/// This is the last four bits of the byte.
#[inline]
pub fn st_type(info: u8) -> u8 {
    info & 0xf
}

/// Is this information defining an import?
#[inline]
pub fn is_import(info: u8, value: u64) -> bool {
    let binding = st_bind(info);
    binding == STB_GLOBAL && value == 0
}

/// Convenience function to get the &'static str type from the symbols `st_info`.
pub fn get_type(info: u8) -> &'static str {
    type_to_str(st_type(info))
}

/// Get the string for some binding.
#[inline]
pub fn bind_to_str(typ: u8) -> &'static str {
    match typ {
        STB_LOCAL => "LOCAL",
        STB_GLOBAL => "GLOBAL",
        STB_WEAK => "WEAK",
        STB_NUM => "NUM",
        STB_GNU_UNIQUE => "GNU_UNIQUE",
        _ => "UNKNOWN_STB",
    }
}

/// Get the string for some type.
#[inline]
pub fn type_to_str(typ: u8) -> &'static str {
    match typ {
        STT_NOTYPE => "NOTYPE",
        STT_OBJECT => "OBJECT",
        STT_FUNC => "FUNC",
        STT_SECTION => "SECTION",
        STT_FILE => "FILE",
        STT_COMMON => "COMMON",
        STT_TLS => "TLS",
        STT_NUM => "NUM",
        STT_GNU_IFUNC => "GNU_IFUNC",
        _ => "UNKNOWN_STT",
    }
}

macro_rules! elf_sym_impure_impl {
        ($from_fd_endian:item) => {

            #[cfg(not(feature = "pure"))]
            pub use self::impure::*;

            #[cfg(not(feature = "pure"))]
            mod impure {

                use std::fs::File;
                use std::io::Read;
                use std::io::Seek;
                use std::io::SeekFrom::Start;
                use std::io;
                use std::fmt;
                use std::slice;

                use super::*;

                impl Sym {
                   /// Checks whether this `Sym` has `STB_GLOBAL`/`STB_WEAK` binding and a `st_value` of 0
                   pub fn is_import(&self) -> bool {
                     let binding = self.st_info >> 4;
                     (binding == STB_GLOBAL || binding == STB_WEAK) && self.st_value == 0
                   }
                   /// Checks whether this `Sym` has type `STT_FUNC`
                   pub fn is_function(&self) -> bool {
                     st_type(self.st_info) == STT_FUNC
                   }
                }

                impl fmt::Debug for Sym {
                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        let bind = st_bind(self.st_info);
                        let typ = st_type(self.st_info);
                        write!(f,
                               "st_name: {} {} {} st_other: {} st_shndx: {} st_value: {:x} st_size: {}",
                               self.st_name,
                               bind_to_str(bind),
                               type_to_str(typ),
                               self.st_other,
                               self.st_shndx,
                               self.st_value,
                               self.st_size)
                    }
                }

                pub unsafe fn from_raw<'a>(symp: *const Sym, count: usize) -> &'a [Sym] {
                    slice::from_raw_parts(symp, count)
                }

                #[cfg(feature = "no_endian_fd")]
                pub fn from_fd<'a>(fd: &mut File, offset: usize, count: usize, _: bool) -> io::Result<Vec<Sym>> {
                    // TODO: AFAIK this shouldn't work, since i pass in a byte size...
                    // FIX THIS, unecessary allocations + unsafety here
                    let mut bytes = vec![0u8; count * SIZEOF_SYM];
                    try!(fd.seek(Start(offset as u64)));
                    try!(fd.read(&mut bytes));
                    let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr() as *mut Sym, count) };
                    let mut syms = Vec::with_capacity(count);
                    syms.extend_from_slice(bytes);
                    syms.dedup();
                    Ok(syms)
                }

                #[cfg(not(feature = "no_endian_fd"))]
                $from_fd_endian

            }
        };
    }
<|endoftext|>


<commit_before>// Copyright 2015 The Delix Project Authors. See the AUTHORS file at the top level directory.
//
// 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::collections::HashMap;
use std::io;
use std::net::SocketAddr;
use std::result;
use std::sync::{Arc, RwLock, mpsc};
use std::thread;

use metric::{self, Metric};
use node::{ID, request, service};
use transport::direct::Connection;

pub struct ConnectionMap {
    map: Arc<RwLock<HashMap<ID, Connection>>>,
    sender: mpsc::Sender<ID>,
    connections_gauge: Arc<metric::item::Gauge>,
}

pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    AlreadyExists,
    DoesNotExists,
}

impl ConnectionMap {
    pub fn new(metric: Arc<Metric>) -> Self {
        let map = Arc::new(RwLock::new(HashMap::new()));
        let map_clone = map.clone();

        let connections_gauge = Arc::new(metric.gauge("connections"));
        let connections_gauge_clone = connections_gauge.clone();

        let (sender, receiver) = mpsc::channel::<ID>();
        thread::spawn(move || {
            for peer_node_id in receiver {
                map_clone.write().unwrap().remove(&peer_node_id);
                connections_gauge_clone.change(-1);
            }
        });
        ConnectionMap {
            map: map,
            sender: sender,
            connections_gauge: connections_gauge,
        }
    }

    pub fn add(&self, connection: Connection) -> Result<()> {
        let mut map = self.map.write().unwrap();
        if map.contains_key(&connection.peer_node_id()) {
            return Err(Error::AlreadyExists);
        }

        let sender = self.sender.clone();
        connection.set_error_handler(Box::new(move |peer_node_id, error| {
            if error.kind() != io::ErrorKind::ConnectionAborted {
                error!("got connection error: {:?}", error);
            }
            sender.send(peer_node_id).unwrap();
        }));

        map.insert(connection.peer_node_id(), connection);
        self.connections_gauge.change(1);
        Ok(())
    }

    pub fn contains_key(&self, peer_node_id: &ID) -> bool {
        self.map.read().unwrap().contains_key(peer_node_id)
    }

    pub fn select<F, T>(&self, peer_node_id: &ID, f: F) -> Result<T>
        where F: FnOnce(&Connection) -> T
    {
        let map = self.map.read().unwrap();
        match map.get(peer_node_id) {
            Some(ref connection) => Ok(f(connection)),
            None => Err(Error::DoesNotExists),
        }
    }

    pub fn id_public_address_pairs(&self) -> Vec<(ID, SocketAddr)> {
        self.map
            .read()
            .unwrap()
            .iter()
            .map(|(peer_node_id, peer_connection)| {
                (*peer_node_id, peer_connection.peer_public_address())
            })
            .collect()
    }

    pub fn send_add_services(&self, services: &[String]) -> io::Result<()> {
        let mut map = self.map.write().unwrap();
        for (_, connection) in map.iter_mut() {
            try!(connection.send_add_services(services));
        }
        Ok(())
    }

    pub fn send_remove_services(&self, services: &[String]) -> io::Result<()> {
        let mut map = self.map.write().unwrap();
        for (_, connection) in map.iter_mut() {
            try!(connection.send_remove_services(services));
        }
        Ok(())
    }

    pub fn send_request(&self,
                        peer_node_id: &ID,
                        id: u32,
                        name: &str,
                        reader: &mut request::Reader)
                        -> io::Result<()> {
        let map = self.map.read().unwrap();
        let connection = map.get(peer_node_id).unwrap();
        Ok(try!(connection.send_request(id, name, reader)))
    }

    pub fn send_response(&self,
                         peer_node_id: &ID,
                         request_id: u32,
                         service_result: service::Result)
                         -> io::Result<()> {
        let map = self.map.read().unwrap();
        let connection = match map.get(peer_node_id) {
            Some(connection) => connection,
            None => {
                return Err(io::Error::new(io::ErrorKind::ConnectionAborted, "connection aborted"))
            }
        };
        Ok(try!(connection.send_response(request_id, service_result)))
    }

    pub fn shutdown(&self) {
        let map = self.map.read().unwrap();
        for (_, connection) in map.iter() {
            connection.clear_error_handler();
            connection.shutdown();
        }
    }
}

unsafe impl Send for ConnectionMap {}

unsafe impl Sync for ConnectionMap {}

impl Drop for ConnectionMap {
    fn drop(&mut self) {
        self.shutdown();
    }
}
<commit_msg>removed unsafe code from connection map<commit_after>// Copyright 2015 The Delix Project Authors. See the AUTHORS file at the top level directory.
//
// 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::collections::HashMap;
use std::io;
use std::net::SocketAddr;
use std::result;
use std::sync::{Arc, Mutex, RwLock, mpsc};
use std::thread;

use metric::{self, Metric};
use node::{ID, request, service};
use transport::direct::Connection;

pub struct ConnectionMap {
    map: Arc<RwLock<HashMap<ID, Connection>>>,
    tx: Mutex<mpsc::Sender<ID>>,
    connections_gauge: Arc<metric::item::Gauge>,
}

pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    AlreadyExists,
    DoesNotExists,
}

impl ConnectionMap {
    pub fn new(metric: Arc<Metric>) -> Self {
        let map = Arc::new(RwLock::new(HashMap::new()));
        let map_clone = map.clone();

        let connections_gauge = Arc::new(metric.gauge("connections"));
        let connections_gauge_clone = connections_gauge.clone();

        let (tx, rx) = mpsc::channel::<ID>();
        thread::spawn(move || {
            for peer_node_id in rx {
                map_clone.write().unwrap().remove(&peer_node_id);
                connections_gauge_clone.change(-1);
            }
        });
        ConnectionMap {
            map: map,
            tx: Mutex::new(tx),
            connections_gauge: connections_gauge,
        }
    }

    pub fn add(&self, connection: Connection) -> Result<()> {
        let mut map = self.map.write().unwrap();
        if map.contains_key(&connection.peer_node_id()) {
            return Err(Error::AlreadyExists);
        }

        let tx = self.tx.lock().unwrap().clone();
        connection.set_error_handler(Box::new(move |peer_node_id, error| {
            if error.kind() != io::ErrorKind::ConnectionAborted {
                error!("got connection error: {:?}", error);
            }
            tx.send(peer_node_id).unwrap();
        }));

        map.insert(connection.peer_node_id(), connection);
        self.connections_gauge.change(1);
        Ok(())
    }

    pub fn contains_key(&self, peer_node_id: &ID) -> bool {
        self.map.read().unwrap().contains_key(peer_node_id)
    }

    pub fn select<F, T>(&self, peer_node_id: &ID, f: F) -> Result<T>
        where F: FnOnce(&Connection) -> T
    {
        let map = self.map.read().unwrap();
        match map.get(peer_node_id) {
            Some(ref connection) => Ok(f(connection)),
            None => Err(Error::DoesNotExists),
        }
    }

    pub fn id_public_address_pairs(&self) -> Vec<(ID, SocketAddr)> {
        self.map
            .read()
            .unwrap()
            .iter()
            .map(|(peer_node_id, peer_connection)| {
                (*peer_node_id, peer_connection.peer_public_address())
            })
            .collect()
    }

    pub fn send_add_services(&self, services: &[String]) -> io::Result<()> {
        let mut map = self.map.write().unwrap();
        for (_, connection) in map.iter_mut() {
            try!(connection.send_add_services(services));
        }
        Ok(())
    }

    pub fn send_remove_services(&self, services: &[String]) -> io::Result<()> {
        let mut map = self.map.write().unwrap();
        for (_, connection) in map.iter_mut() {
            try!(connection.send_remove_services(services));
        }
        Ok(())
    }

    pub fn send_request(&self,
                        peer_node_id: &ID,
                        id: u32,
                        name: &str,
                        reader: &mut request::Reader)
                        -> io::Result<()> {
        let map = self.map.read().unwrap();
        let connection = map.get(peer_node_id).unwrap();
        Ok(try!(connection.send_request(id, name, reader)))
    }

    pub fn send_response(&self,
                         peer_node_id: &ID,
                         request_id: u32,
                         service_result: service::Result)
                         -> io::Result<()> {
        let map = self.map.read().unwrap();
        let connection = match map.get(peer_node_id) {
            Some(connection) => connection,
            None => {
                return Err(io::Error::new(io::ErrorKind::ConnectionAborted, "connection aborted"))
            }
        };
        Ok(try!(connection.send_response(request_id, service_result)))
    }

    pub fn shutdown(&self) {
        let map = self.map.read().unwrap();
        for (_, connection) in map.iter() {
            connection.clear_error_handler();
            connection.shutdown();
        }
    }
}

// unsafe impl Send for ConnectionMap {}
//
// unsafe impl Sync for ConnectionMap {}

impl Drop for ConnectionMap {
    fn drop(&mut self) {
        self.shutdown();
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2015 Y. T. Chung <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! Encoder

use std::io::{self, Write};
use std::iter::IntoIterator;
use std::{mem, error, fmt};

use byteorder::{self, LittleEndian, WriteBytesExt};

use bson::Bson;

/// Possible errors that can arise during encoding.
#[derive(Debug)]
pub enum EncoderError {
    IoError(io::Error),
}

impl From<io::Error> for EncoderError {
    fn from(err: io::Error) -> EncoderError {
        EncoderError::IoError(err)
    }
}

impl From<byteorder::Error> for EncoderError {
    fn from(err: byteorder::Error) -> EncoderError {
        EncoderError::IoError(From::from(err))
    }
}

impl fmt::Display for EncoderError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &EncoderError::IoError(ref inner) => inner.fmt(fmt)
        }
    }
}

impl error::Error for EncoderError {
    fn description(&self) -> &str {
        match self {
            &EncoderError::IoError(ref inner) => inner.description(),
        }
    }
    fn cause(&self) -> Option<&error::Error> {
        match self {
            &EncoderError::IoError(ref inner) => Some(inner)
        }
    }
}

/// Alias for `Result<T, EncoderError>`.
pub type EncoderResult<T> = Result<T, EncoderError>;

fn write_string<W: Write + ?Sized>(writer: &mut W, s: &str) -> EncoderResult<()> {
    try!(writer.write_i32::<LittleEndian>(s.len() as i32 + 1));
    try!(writer.write_all(s.as_bytes()));
    try!(writer.write_u8(0));
    Ok(())
}

fn write_cstring<W: Write + ?Sized>(writer: &mut W, s: &str) -> EncoderResult<()> {
    try!(writer.write_all(s.as_bytes()));
    try!(writer.write_u8(0));
    Ok(())
}

#[inline]
fn write_i32<W: Write + ?Sized>(writer: &mut W, val: i32) -> EncoderResult<()> {
    writer.write_i32::<LittleEndian>(val).map_err(From::from)
}

#[inline]
fn write_i64<W: Write + ?Sized>(writer: &mut W, val: i64) -> EncoderResult<()> {
    writer.write_i64::<LittleEndian>(val).map_err(From::from)
}

#[inline]
fn write_f64<W: Write + ?Sized>(writer: &mut W, val: f64) -> EncoderResult<()> {
    writer.write_f64::<LittleEndian>(val).map_err(From::from)
}

fn encode_array<W: Write + ?Sized>(writer: &mut W, arr: &[Bson]) -> EncoderResult<()> {
    let mut buf = Vec::new();
    for (key, val) in arr.iter().enumerate() {
        try!(encode_bson(&mut buf, &key.to_string(), val));
    }

    try!(write_i32(writer, (buf.len() + mem::size_of::<i32>() + mem::size_of::<u8>()) as i32));
    try!(writer.write_all(&buf));
    try!(writer.write_u8(0));
    Ok(())
}

/// Attempt to encode a `Document` into a byte stream.
///
/// Can encode any type which is iterable as `(key: &str, value: &Bson)` pairs,
/// which generally means most maps.
pub fn encode_document
    <'a, S: AsRef<str> + 'a, W: Write + ?Sized, D: IntoIterator<Item=(&'a S, &'a Bson)>>
    (writer: &mut W, doc: D) -> EncoderResult<()>
{
    let mut buf = Vec::new();
    for (key, val) in doc.into_iter() {
        try!(encode_bson(&mut buf, key.as_ref(), val));
    }

    try!(write_i32(writer, (buf.len() + mem::size_of::<i32>() + mem::size_of::<u8>()) as i32));
    try!(writer.write_all(&buf));
    try!(writer.write_u8(0));
    Ok(())
}

fn encode_bson<W: Write + ?Sized>(writer: &mut W, key: &str, val: &Bson) -> EncoderResult<()> {
    try!(writer.write_u8(val.element_type() as u8));
    try!(write_cstring(writer, key));

    match val {
        &Bson::FloatingPoint(v) => write_f64(writer, v),
        &Bson::String(ref v) => write_string(writer, &v),
        &Bson::Array(ref v) => encode_array(writer, &v),
        &Bson::Document(ref v) => encode_document(writer, v),
        &Bson::Boolean(v) => writer.write_u8(if v { 0x00 } else { 0x01 }).map_err(From::from),
        &Bson::RegExp(ref pat, ref opt) => {
            try!(write_cstring(writer, pat));
            write_cstring(writer, opt)
        },
        &Bson::JavaScriptCode(ref code) => write_string(writer, &code),
        &Bson::ObjectId(id) => writer.write_all(&id).map_err(From::from),
        &Bson::JavaScriptCodeWithScope(ref code, ref scope) => {
            let mut buf = Vec::new();
            try!(write_string(&mut buf, code));
            try!(encode_document(&mut buf, scope));

            try!(write_i32(writer, buf.len() as i32 + 1));
            writer.write_all(&buf).map_err(From::from)
        },
        &Bson::I32(v) => write_i32(writer, v),
        &Bson::I64(v) => write_i64(writer, v),
        &Bson::TimeStamp(v) => write_i64(writer, v),
        &Bson::Binary(subtype, ref data) => {
            try!(write_i32(writer, data.len() as i32));
            try!(writer.write_u8(From::from(subtype)));
            writer.write_all(data).map_err(From::from)
        },
        &Bson::UtcDatetime(ref v) => write_i64(writer, v.timestamp()),
        &Bson::Null => Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::encode_document;
    use bson::{Document, Bson};

    #[test]
    fn test_encode_floating_point() {
        let src = 1020.123;
        let dst = [18, 0, 0, 0, 1, 107, 101, 121, 0, 68, 139, 108, 231, 251, 224, 143, 64, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::FloatingPoint(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf, &dst);
    }

    #[test]
    fn test_encode_utf8_string() {
        let src = "test你好吗".to_owned();
        let dst = [28, 0, 0, 0, 2, 107, 101, 121, 0, 14, 0, 0, 0, 116, 101, 115, 116, 228, 189, 160, 229, 165, 189, 229, 144, 151, 0, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::String(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf, &dst);
    }

    #[test]
    fn test_encode_array() {
        let src = vec![Bson::FloatingPoint(1.01), Bson::String("xyz".to_owned())];
        let dst = [37, 0, 0, 0, 4, 107, 101, 121, 0, 27, 0, 0, 0, 1, 48, 0, 41, 92, 143, 194, 245, 40, 240, 63, 2, 49, 0, 4, 0, 0, 0, 120, 121, 122, 0, 0, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::Array(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf[..], &dst[..]);
    }
}
<commit_msg>Fix boolean encoding<commit_after>// The MIT License (MIT)

// Copyright (c) 2015 Y. T. Chung <zonyitoo@gmail.com>

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

//! Encoder

use std::io::{self, Write};
use std::iter::IntoIterator;
use std::{mem, error, fmt};

use byteorder::{self, LittleEndian, WriteBytesExt};

use bson::Bson;

/// Possible errors that can arise during encoding.
#[derive(Debug)]
pub enum EncoderError {
    IoError(io::Error),
}

impl From<io::Error> for EncoderError {
    fn from(err: io::Error) -> EncoderError {
        EncoderError::IoError(err)
    }
}

impl From<byteorder::Error> for EncoderError {
    fn from(err: byteorder::Error) -> EncoderError {
        EncoderError::IoError(From::from(err))
    }
}

impl fmt::Display for EncoderError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &EncoderError::IoError(ref inner) => inner.fmt(fmt)
        }
    }
}

impl error::Error for EncoderError {
    fn description(&self) -> &str {
        match self {
            &EncoderError::IoError(ref inner) => inner.description(),
        }
    }
    fn cause(&self) -> Option<&error::Error> {
        match self {
            &EncoderError::IoError(ref inner) => Some(inner)
        }
    }
}

/// Alias for `Result<T, EncoderError>`.
pub type EncoderResult<T> = Result<T, EncoderError>;

fn write_string<W: Write + ?Sized>(writer: &mut W, s: &str) -> EncoderResult<()> {
    try!(writer.write_i32::<LittleEndian>(s.len() as i32 + 1));
    try!(writer.write_all(s.as_bytes()));
    try!(writer.write_u8(0));
    Ok(())
}

fn write_cstring<W: Write + ?Sized>(writer: &mut W, s: &str) -> EncoderResult<()> {
    try!(writer.write_all(s.as_bytes()));
    try!(writer.write_u8(0));
    Ok(())
}

#[inline]
fn write_i32<W: Write + ?Sized>(writer: &mut W, val: i32) -> EncoderResult<()> {
    writer.write_i32::<LittleEndian>(val).map_err(From::from)
}

#[inline]
fn write_i64<W: Write + ?Sized>(writer: &mut W, val: i64) -> EncoderResult<()> {
    writer.write_i64::<LittleEndian>(val).map_err(From::from)
}

#[inline]
fn write_f64<W: Write + ?Sized>(writer: &mut W, val: f64) -> EncoderResult<()> {
    writer.write_f64::<LittleEndian>(val).map_err(From::from)
}

fn encode_array<W: Write + ?Sized>(writer: &mut W, arr: &[Bson]) -> EncoderResult<()> {
    let mut buf = Vec::new();
    for (key, val) in arr.iter().enumerate() {
        try!(encode_bson(&mut buf, &key.to_string(), val));
    }

    try!(write_i32(writer, (buf.len() + mem::size_of::<i32>() + mem::size_of::<u8>()) as i32));
    try!(writer.write_all(&buf));
    try!(writer.write_u8(0));
    Ok(())
}

/// Attempt to encode a `Document` into a byte stream.
///
/// Can encode any type which is iterable as `(key: &str, value: &Bson)` pairs,
/// which generally means most maps.
pub fn encode_document
    <'a, S: AsRef<str> + 'a, W: Write + ?Sized, D: IntoIterator<Item=(&'a S, &'a Bson)>>
    (writer: &mut W, doc: D) -> EncoderResult<()>
{
    let mut buf = Vec::new();
    for (key, val) in doc.into_iter() {
        try!(encode_bson(&mut buf, key.as_ref(), val));
    }

    try!(write_i32(writer, (buf.len() + mem::size_of::<i32>() + mem::size_of::<u8>()) as i32));
    try!(writer.write_all(&buf));
    try!(writer.write_u8(0));
    Ok(())
}

fn encode_bson<W: Write + ?Sized>(writer: &mut W, key: &str, val: &Bson) -> EncoderResult<()> {
    try!(writer.write_u8(val.element_type() as u8));
    try!(write_cstring(writer, key));

    match val {
        &Bson::FloatingPoint(v) => write_f64(writer, v),
        &Bson::String(ref v) => write_string(writer, &v),
        &Bson::Array(ref v) => encode_array(writer, &v),
        &Bson::Document(ref v) => encode_document(writer, v),
        &Bson::Boolean(v) => writer.write_u8(if v { 0x01 } else { 0x00 }).map_err(From::from),
        &Bson::RegExp(ref pat, ref opt) => {
            try!(write_cstring(writer, pat));
            write_cstring(writer, opt)
        },
        &Bson::JavaScriptCode(ref code) => write_string(writer, &code),
        &Bson::ObjectId(id) => writer.write_all(&id).map_err(From::from),
        &Bson::JavaScriptCodeWithScope(ref code, ref scope) => {
            let mut buf = Vec::new();
            try!(write_string(&mut buf, code));
            try!(encode_document(&mut buf, scope));

            try!(write_i32(writer, buf.len() as i32 + 1));
            writer.write_all(&buf).map_err(From::from)
        },
        &Bson::I32(v) => write_i32(writer, v),
        &Bson::I64(v) => write_i64(writer, v),
        &Bson::TimeStamp(v) => write_i64(writer, v),
        &Bson::Binary(subtype, ref data) => {
            try!(write_i32(writer, data.len() as i32));
            try!(writer.write_u8(From::from(subtype)));
            writer.write_all(data).map_err(From::from)
        },
        &Bson::UtcDatetime(ref v) => write_i64(writer, v.timestamp()),
        &Bson::Null => Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::encode_document;
    use bson::{Document, Bson};

    #[test]
    fn test_encode_floating_point() {
        let src = 1020.123;
        let dst = [18, 0, 0, 0, 1, 107, 101, 121, 0, 68, 139, 108, 231, 251, 224, 143, 64, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::FloatingPoint(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf, &dst);
    }

    #[test]
    fn test_encode_utf8_string() {
        let src = "test你好吗".to_owned();
        let dst = [28, 0, 0, 0, 2, 107, 101, 121, 0, 14, 0, 0, 0, 116, 101, 115, 116, 228, 189, 160, 229, 165, 189, 229, 144, 151, 0, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::String(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf, &dst);
    }

    #[test]
    fn test_encode_array() {
        let src = vec![Bson::FloatingPoint(1.01), Bson::String("xyz".to_owned())];
        let dst = [37, 0, 0, 0, 4, 107, 101, 121, 0, 27, 0, 0, 0, 1, 48, 0, 41, 92, 143, 194, 245, 40, 240, 63, 2, 49, 0, 4, 0, 0, 0, 120, 121, 122, 0, 0, 0];

        let mut doc = Document::new();
        doc.insert("key".to_owned(), Bson::Array(src));

        let mut buf = Vec::new();
        encode_document(&mut buf, &doc).unwrap();

        assert_eq!(&buf[..], &dst[..]);
    }
}
<|endoftext|>