<commit_before>mod apicall {
    pub struct APICallInfo {
        kind: APICallType,
        service: service::Service,
        app: app::App,
        user: Option<user::User>,
    }

    pub enum APICallType {
        Authorize,
        AuthRep,
        Report
    }

    impl APICallType {
        pub fn method(&self) -> String {
            match self {
                Authorize => "GET".to_owned(),
                _ => "POST".to_owned()
            }
        }
    }

    impl APICallInfo {
        pub fn new(kind: APICallType, service: service::Service, app: app::App, user: Option<user::User>) -> Self {
            Self { kind, service, app, user }
        }
    }

    pub trait ToParams {
        fn to_params(&self) -> String;
    }

    mod service {
        pub struct Service {
            service_id: String,
            creds: Credentials,
        }

        impl super::ToParams for Service {
            fn to_params(&self) -> String {
                let mut param = "service_id=".to_owned();
                param.push_str(self.service_id.as_str());
                param.push_str(self.creds.to_params().as_str());
                param
            }
        }

        pub enum Credentials {
            ProviderKey(String),
            ServiceToken(String),
        }

        impl super::ToParams for Credentials {
            fn to_params(&self) -> String {
                let (field, value) = match *self {
                    Credentials::ProviderKey(ref key) => ("provider_key=", key),
                    Credentials::ServiceToken(ref token) => ("service_token=", token)
                };
                let mut param = field.to_owned();
                param.push_str(value.as_str());
                param
            }
        }
    }

    mod app {
        pub enum App {
            AppId(String, Option<String>),
            UserKey(String),
            OAuthToken(String)
        }
    }

    mod user {
        pub enum User {
            UserId(String),
            OAuthToken(String)
        }
    }

    pub struct Request {
        method: String,
        path: String,
        body: Option<String>
    }

    pub trait ToRequest {
        fn to_request(&self) -> Request;
    }

    impl ToRequest for APICallInfo {
        fn to_request(&self) -> Request {
            Request {
                method: self.kind.method(),
                path: "/".to_owned(),
                body: None
            }
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>lib: make modules and structs public<commit_after>pub mod apicall {
    pub struct APICallInfo {
        kind: APICallType,
        service: service::Service,
        app: app::App,
        user: Option<user::User>,
    }

    pub enum APICallType {
        Authorize,
        AuthRep,
        Report
    }

    impl APICallType {
        pub fn method(&self) -> String {
            match self {
                Authorize => "GET".to_owned(),
                _ => "POST".to_owned()
            }
        }
    }

    impl APICallInfo {
        pub fn new(kind: APICallType, service: service::Service, app: app::App, user: Option<user::User>) -> Self {
            Self { kind, service, app, user }
        }
    }

    pub trait ToParams {
        fn to_params(&self) -> String;
    }

    pub mod service {
        pub struct Service {
            service_id: String,
            creds: Credentials,
        }

        impl super::ToParams for Service {
            fn to_params(&self) -> String {
                let mut param = "service_id=".to_owned();
                param.push_str(self.service_id.as_str());
                param.push_str(self.creds.to_params().as_str());
                param
            }
        }

        pub enum Credentials {
            ProviderKey(String),
            ServiceToken(String),
        }

        impl super::ToParams for Credentials {
            fn to_params(&self) -> String {
                let (field, value) = match *self {
                    Credentials::ProviderKey(ref key) => ("provider_key=", key),
                    Credentials::ServiceToken(ref token) => ("service_token=", token)
                };
                let mut param = field.to_owned();
                param.push_str(value.as_str());
                param
            }
        }
    }

    pub mod app {
        pub enum App {
            AppId(String, Option<String>),
            UserKey(String),
            OAuthToken(String)
        }
    }

    pub mod user {
        pub enum User {
            UserId(String),
            OAuthToken(String)
        }
    }

    pub struct Request {
        method: String,
        path: String,
        body: Option<String>
    }

    pub trait ToRequest {
        fn to_request(&self) -> Request;
    }

    impl ToRequest for APICallInfo {
        fn to_request(&self) -> Request {
            Request {
                method: self.kind.method(),
                path: "/".to_owned(),
                body: None
            }
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


<commit_before>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
pub mod metadata;
pub mod frame;
pub mod subframe;
pub mod stream;

pub use metadata::{metadata_parser, Metadata};
pub use frame::{frame_parser, Frame};
pub use subframe::{subframe_parser, Subframe};
pub use stream::{stream_parser, Stream};
<commit_msg>Add top level code sample for FLAC decoding<commit_after>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.
//!
//! # Examples
//!
//! Basic decoding from a file.
//!
//! ```
//! match flac::Stream::from_file("path/to/file.flac") {
//!   Ok(mut stream) => {
//!     // Copy of `StreamInfo` to help convert to a different audio format.
//!     let info = stream.info();
//!
//!     for sample in stream.iter() {
//!       // Iterate over each decoded sample
//!     }
//!   }
//!   Err(error)     => println!("{}", error),
//! }
//! ```

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
pub mod metadata;
pub mod frame;
pub mod subframe;
pub mod stream;

pub use metadata::{metadata_parser, Metadata};
pub use frame::{frame_parser, Frame};
pub use subframe::{subframe_parser, Subframe};
pub use stream::{stream_parser, Stream};
<|endoftext|>


<commit_before>//! `MetaFactory` is used to build efficient object creation trees at
//! runtime. This is potentialy useful if the configuration of this
//! tree occurs in different libraries.
//!
//! In other words, it allows us to separate __what__ is created from
//! __how__ it is created.
//!
//! ```
//! use metafactory::new_metafactory;
//! use metafactory::factory::ToFactory;
//!
//! fn main() {
//!     // build meta-info for constructor from cloneable source.
//!     let mf = new_metafactory(5i);
//!
//!     // inspect the metafactory
//!     assert!(mf.get_type().is::<int>());
//!
//!     // create a factory that can be used as argument for other factory
//!     let boxany = mf.new_factory(Vec::new());
//!
//!     // conveniently donwcast factory to callable instance
//!     let factory = boxany.to_factory::<int>().unwrap();
//!
//!     // factory can be cloned
//!     let factory2 = factory.clone();
//!
//!     // both clones invoke the same construction path and return the same value
//!     assert_eq!(factory.get(), factory2.get());
//! }
//! ```

extern crate typedef;

use std::any::{ Any };
use typedef::{ TypeDef };

pub mod factory;
pub mod error;
pub mod from_clone;
pub mod from_closure;

/// Implements reflection and initiation of any abstract object constructor.
///
/// ## Information about constructor
///
/// The first goal of this trait is being able to inspect the construction
/// mechanism at the runtime.
///
/// `MetaFactory` contains information about the constructor source: the
/// return type and argument types. It also contains a method `new_factory`
/// that can create a function to invoke this source and get the values.
///
/// ## Factory initiation
///
/// The second goal is to avoid donwcasting construction arguments on every
/// `Factory` invocation.
///
/// There are separate traits for `MetaFactory` and "real" `Factory`.
/// `MetaFactory` is used to build a real `Factory` by passing all the
/// required constructor arguments as factories under `Vec<Box<Any>>`.
///
/// Internaly, all parent `Factory`s will be downcasted to correct types
/// and stored inside returned `Factory`'s scope, so that all of them
/// can be invoked with a simple `get()` call.
///
/// ## Simple value as constructor
///
/// This library allows to use many sources as "constructors", the simplest
/// of which is a cloneable value. In this example we will use such value to
/// create a new constructor metadata, check if argument and return types are
/// correct, and then create an actual getter for the value:
///
/// ```
/// use metafactory::{ new_metafactory };
/// use metafactory::factory::{ ToFactory };
///
/// let metafactory = new_metafactory(5i);
/// assert!(metafactory.get_type().is::<int>());
/// assert!(metafactory.get_arg_types().len() == 0); // clonable int has no arguments
///
/// let factory = metafactory
///     .new_factory(
///         Vec::new() // No arguments in this case.
///     )
///     .to_factory::<int>()
///     .unwrap();
///
/// assert_eq!(factory.get(), 5i);
/// ```
#[unstable]
pub trait MetaFactory {
    #[unstable]
    fn get_type(&self) -> TypeDef;
    #[unstable]
    fn get_arg_types(&self) -> Vec<TypeDef>;
    #[unstable]
    fn new_factory(&self, arg_getters: Vec<Box<Any>>) -> Box<Any>;
}

/// Trait for values convertable to `MetaFactory`.
///
/// This trait is implemented for values that can be used as
/// sources for object creation.
#[unstable]
pub trait ToMetaFactory {
    /// Creates a `MetaFactory` that has information about object
    /// constructor: produced object type, argument types, and
    /// a method to get this getter.
    #[unstable]
    fn to_metafactory<'a>(self) -> Box<MetaFactory + 'a>;
}

/// Create a new `MetaFactory` for any compatible value source.
///
/// Compatible value type must have `ToMetaFactory` implementation.
/// Supported sources are in submodules, look at "clone" for simpliest example.
pub fn new_metafactory<'r, T: ToMetaFactory>(any: T) -> Box<MetaFactory + 'r> {
    any.to_metafactory()
}
<commit_msg>Add lambda example to doc.<commit_after>//! `MetaFactory` is used to build efficient object creation trees at
//! runtime. This is potentialy useful if the configuration of this
//! tree occurs in different libraries.
//!
//! In other words, it allows us to separate __what__ is created from
//! __how__ it is created.
//!
//! ```
//! use metafactory::new_metafactory;
//! use metafactory::factory::ToFactory;
//!
//! fn main() {
//!     // build argument-factory from cloneable source.
//!     let meta_arg1 = new_metafactory(5i);
//!
//!     // build argument-factory from lambda.
//!     let meta_arg2 = new_metafactory(|| 5i32);
//!
//!     // it knows the cloneable source returns int
//!     assert!(meta_arg1.get_type().is::<int>());
//!     // it knows the lambda source returns i32
//!     assert!(meta_arg2.get_type().is::<i32>());
//!
//!     // create a factory that can be used as argument for other factory
//!     let boxany = meta_arg1.new_factory(Vec::new());
//!
//!     // conveniently downcast factory to callable instance
//!     let factory = boxany.to_factory::<int>().unwrap();
//!
//!     // factory can be cloned
//!     let factory2 = factory.clone();
//!
//!     // both clones invoke the same construction path and return the same value
//!     assert_eq!(factory.get(), factory2.get());
//! }
//! ```

extern crate typedef;

use std::any::{ Any };
use typedef::{ TypeDef };

pub mod factory;
pub mod error;
pub mod from_clone;
pub mod from_closure;

/// Implements reflection and initiation of any abstract object constructor.
///
/// ## Information about constructor
///
/// The first goal of this trait is being able to inspect the construction
/// mechanism at the runtime.
///
/// `MetaFactory` contains information about the constructor source: the
/// return type and argument types. It also contains a method `new_factory`
/// that can create a function to invoke this source and get the values.
///
/// ## Factory initiation
///
/// The second goal is to avoid donwcasting construction arguments on every
/// `Factory` invocation.
///
/// There are separate traits for `MetaFactory` and "real" `Factory`.
/// `MetaFactory` is used to build a real `Factory` by passing all the
/// required constructor arguments as factories under `Vec<Box<Any>>`.
///
/// Internaly, all parent `Factory`s will be downcasted to correct types
/// and stored inside returned `Factory`'s scope, so that all of them
/// can be invoked with a simple `get()` call.
///
/// ## Simple value as constructor
///
/// This library allows to use many sources as "constructors", the simplest
/// of which is a cloneable value. In this example we will use such value to
/// create a new constructor metadata, check if argument and return types are
/// correct, and then create an actual getter for the value:
///
/// ```
/// use metafactory::{ new_metafactory };
/// use metafactory::factory::{ ToFactory };
///
/// let metafactory = new_metafactory(5i);
/// assert!(metafactory.get_type().is::<int>());
/// assert!(metafactory.get_arg_types().len() == 0); // clonable int has no arguments
///
/// let factory = metafactory
///     .new_factory(
///         Vec::new() // No arguments in this case.
///     )
///     .to_factory::<int>()
///     .unwrap();
///
/// assert_eq!(factory.get(), 5i);
/// ```
#[unstable]
pub trait MetaFactory {
    #[unstable]
    fn get_type(&self) -> TypeDef;
    #[unstable]
    fn get_arg_types(&self) -> Vec<TypeDef>;
    #[unstable]
    fn new_factory(&self, arg_getters: Vec<Box<Any>>) -> Box<Any>;
}

/// Trait for values convertable to `MetaFactory`.
///
/// This trait is implemented for values that can be used as
/// sources for object creation.
#[unstable]
pub trait ToMetaFactory {
    /// Creates a `MetaFactory` that has information about object
    /// constructor: produced object type, argument types, and
    /// a method to get this getter.
    #[unstable]
    fn to_metafactory<'a>(self) -> Box<MetaFactory + 'a>;
}

/// Create a new `MetaFactory` for any compatible value source.
///
/// Compatible value type must have `ToMetaFactory` implementation.
/// Supported sources are in submodules, look at "clone" for simpliest example.
pub fn new_metafactory<'r, T: ToMetaFactory>(any: T) -> Box<MetaFactory + 'r> {
    any.to_metafactory()
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate oven;
extern crate cookie;

use iron::prelude::*;
use iron::middleware;
use oven::prelude::*;

pub struct LoginManager {
    signing_key: Vec<u8>
}

impl LoginManager {
    pub fn new(signing_key: Vec<u8>) -> LoginManager {
        LoginManager { signing_key: signing_key }
    }
}

impl middleware::AroundMiddleware for LoginManager {
    fn around(self, handler: Box<middleware::Handler>) -> Box<middleware::Handler> {
        let mut ch = Chain::new(handler);
        let key = self.signing_key;

        ch.link(oven::new(key.clone()));

        Box::new(ch)
    }
}

pub trait User: Send + Sync + Sized {
    fn from_username(request: &mut Request, username: &str) -> Option<Self>;
    fn get_username(&self) -> &str;

    fn from_request(request: &mut Request) -> Option<Self> {
        let value = match request.get_cookie("logged_in_user") {
            Some(x) => x.value.clone(),
            None => return None
        };
        Self::from_username(request, &value[..])
    }

    fn log_in_on(&self, response: &mut Response) {
        response.set_cookie(cookie::Cookie::new("logged_in_user".to_owned(), self.get_username().to_owned()));
    }

    fn log_out_of(&self, response: &mut Response) {
        response.set_cookie(cookie::Cookie::new("logged_in_user".to_owned(), self.get_username().to_owned()));
    }

    fn log_in(self) -> LoginModifier<Self> { LoginModifier { user: self } }
    fn log_out(self) -> LogoutModifier<Self> { LogoutModifier { user: self } }
}

pub struct LoginModifier<U: User> { user: U }
impl<U: User> iron::modifier::Modifier<Response> for LoginModifier<U> {
    fn modify(self, response: &mut Response) { self.user.log_in_on(response) }
}

pub struct LogoutModifier<U: User> { user: U }
impl<U: User> iron::modifier::Modifier<Response> for LogoutModifier<U> {
    fn modify(self, response: &mut Response) { self.user.log_out_of(response) }
}
<commit_msg>Properly implement log_out<commit_after>extern crate iron;
extern crate oven;
extern crate cookie;

use iron::prelude::*;
use iron::middleware;
use oven::prelude::*;

pub struct LoginManager {
    signing_key: Vec<u8>
}

impl LoginManager {
    pub fn new(signing_key: Vec<u8>) -> LoginManager {
        LoginManager { signing_key: signing_key }
    }
}

impl middleware::AroundMiddleware for LoginManager {
    fn around(self, handler: Box<middleware::Handler>) -> Box<middleware::Handler> {
        let mut ch = Chain::new(handler);
        let key = self.signing_key;

        ch.link(oven::new(key.clone()));

        Box::new(ch)
    }
}

pub trait User: Send + Sync + Sized {
    fn from_username(request: &mut Request, username: &str) -> Option<Self>;
    fn get_username(&self) -> &str;

    fn from_request(request: &mut Request) -> Option<Self> {
        let value = match request.get_cookie("logged_in_user") {
            Some(x) => x.value.clone(),
            None => return None
        };
        Self::from_username(request, &value[..])
    }

    fn log_in_on(&self, response: &mut Response) {
        response.set_cookie(cookie::Cookie::new("logged_in_user".to_owned(), self.get_username().to_owned()));
    }

    fn log_in(self) -> LoginModifier<Self> { LoginModifier { user: self } }
}

pub struct LoginModifier<U: User> { user: U }
impl<U: User> iron::modifier::Modifier<Response> for LoginModifier<U> {
    fn modify(self, response: &mut Response) { self.user.log_in_on(response) }
}

pub fn log_out_of(response: &mut Response) {
    response.get_mut::<oven::ResponseCookies>().unwrap().remove("logged_in_user");
}

pub struct LogoutModifier;
impl iron::modifier::Modifier<Response> for LogoutModifier {
    fn modify(self, response: &mut Response) { log_out_of(response) }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Aaron Loucks <aloucks+github@cofront.net>
//
// 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.

use std::slice::Iter;
use std::hash::Hash;
use std::hash::Hasher;
use std::fmt::{self, Debug};
use std::ops::Index;

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Entity(u64);

const INVALID_ID: u64 = std::u64::MAX;
const INVALID_INDEX: usize = std::u32::MAX as usize;

impl Default for Entity {
    #[inline(always)]
    fn default() -> Entity {
        Entity(INVALID_ID)
    }
}

impl Debug for Entity {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Entity({{id: {}, key: {}, gen: {}}})", self.0, self.key(), self.gen())
    }
}

impl Hash for Entity {
    #[inline(always)]
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write_u64(self.0)
    }
}

impl Entity {
    #[inline(always)]
    fn from_key_and_gen(key: u32, gen: u32) -> Entity {
        Entity(((key as u64) << 32) | (gen as u64))
    }

    #[inline(always)]
    pub fn id(&self) -> u64 {
        self.0
    }

    #[inline(always)]
    pub fn key(&self) -> u32 {
        (self.0 >> 32) as u32
    }

    #[inline(always)]
    pub fn gen(&self) -> u32 {
        (self.0 & 0xFFFFFFFF) as u32
    }
}

#[derive(Debug, Clone)]
pub struct EntityPool {
    entities: Vec<Entity>,
    entities_free: Vec<Entity>,
    entity_index: Vec<usize>, // entity_index[entity.key] => index; entities[index as usize]
    next_entity_key: u32,
}

impl Default for EntityPool {
    #[inline(always)]
    fn default() -> EntityPool {
        EntityPool::new()
    }
}

impl EntityPool {

    /// Creates a new, empty `EntityPool`.
    ///
    /// The `EntityPool` will not allocate until entities are created.
    ///
    pub fn new() -> EntityPool {
        EntityPool::with_capacity(0, 0)
    }

    /// Creates a new, empty `EntityPool` with the specified capacities.
    ///
    /// The `EntityPool` will able to create `create_capacity` and return `return_capacity`
    /// entities without reallocating. If either capacity is 0, their respective storage
    /// vectors will not allocate.
    pub fn with_capacity(create_capacity: usize, return_capacity: usize) -> EntityPool {
        EntityPool {
            entities: Vec::with_capacity(create_capacity),
            entities_free: Vec::with_capacity(return_capacity),
            entity_index: Vec::with_capacity(create_capacity),
            next_entity_key: 0
        }
    }

    /// Creates a unique entity.
    ///
    /// Returns the `Entity` and it's current `index`. The index is only guaranteed to remain
    /// valid until the next call to `return_entity`.
    pub fn create_entity(&mut self) -> (usize, Entity) {
        let (key, gen) = match self.entities_free.pop() {
            Some(entity) => {
                (entity.key(), entity.gen().wrapping_add(1))
            },
            None => {
                let key = self.next_entity_key;
                self.next_entity_key = key + 1;
                (key, 0)
            }
        };
        let entity = Entity::from_key_and_gen(key, gen);
        let index = self.entities.len();
        self.entities.push(entity);
        if key as usize != self.entity_index.len() {
            self.entity_index[key as usize] = index;
        }
        else {
            debug_assert_eq!(key as usize, self.entity_index.len());
            self.entity_index.push(index);
        }
        (index, entity)
    }

    /// Release ownership of the `entity`, allowing for it to be recycled. A recycled entity will
    /// have it's internal generation incremented, yielding a new, unique entity.
    ///
    /// Entities are stored in contiguous memory. When an entity is returned, the last entity is
    /// swaped into the returned entity's slot; thus indexes retrieved prior to returning an
    /// entity are potentially invalidated.
    ///
    /// # Panics
    ///
    /// Returning an entity more than once, or an entity created from another pool, results in
    /// undefined behavior.
    ///
    /// # Examples
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// let (_, e1) = pool.create_entity();
    /// pool.return_entity(e1);
    /// let (_, e2) = pool.create_entity();
    /// assert!(e1 != e2);
    /// ```
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// let (i1, e1) = pool.create_entity();
    /// let (i2, e2) = pool.create_entity();
    /// let (i3, e3) = pool.create_entity();
    /// assert_eq!(0, i1);
    /// assert_eq!(1, i2);
    /// assert_eq!(2, i3);
    /// assert_eq!(0, pool.index_of(e1));
    /// assert_eq!(1, pool.index_of(e2));
    /// assert_eq!(2, pool.index_of(e3));
    /// pool.return_entity(e2);
    /// assert_eq!(0, pool.index_of(e1));
    /// assert_eq!(1, pool.index_of(e3));
    /// ```
    pub fn return_entity(&mut self, entity: Entity) {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize];
        debug_assert_eq!(entity.gen(), self.entities[index].gen());
        self.entities_free.push(entity);
        self.entities.swap_remove(index);
        self.entity_index[key as usize] = INVALID_INDEX;
        match self.entities.get(index) {
            Some(e) => self.entity_index[e.key() as usize] = index,
            None    => {}
        };
    }

    /// Returns the current `index` of the given `entity`, which is only guaranteed to remain
    /// valid until the next call to `return_entity`.
    ///
    /// # Panics
    ///
    /// Querying the status of an entity from another pool results in undefined behavior.
    #[inline(always)]
    pub fn index_of(&self, entity: Entity) -> usize {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize] as usize;
        debug_assert_eq!(entity.gen(), self.entities[index].gen());
        index
    }

    /// Returns the current `entity` at the given `index`.
    ///
    /// # Panics
    ///
    /// Panics if the index is greater or equal to the number of live entities in this pool.
    #[inline(always)]
    pub fn entity_at(&self, index: usize) -> Entity {
        self.entities[index]
    }

    /// Returns `true` if this entity has not been returned.
    ///
    /// # Panics
    ///
    /// Querying the status of an entity from another pool results in undefined behavior.
    pub fn is_alive(&self, entity: Entity) -> bool {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize];
        if index != INVALID_INDEX {
            let other = self.entities[index];
            key == other.key() && entity.gen() == other.gen()
        }
        else {
            false
        }
    }

    /// Returns an iterator to the live entities. The `Enumerate` of the returned iterator will
    /// yield each `entity` and its current `index`.
    ///
    /// # Examples
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// pool.create_entity();
    /// pool.create_entity();
    /// pool.create_entity();
    /// for (index, entity) in pool.iter().enumerate() {
    ///     assert_eq!(index, pool.index_of(*entity));
    ///     assert_eq!(*entity, pool.entity_at(index));
    /// }
    /// ```
    #[inline(always)]
    pub fn iter(&self) -> Iter<Entity> {
        self.entities.iter()
    }

    /// Resets the `EnitityPool` to its initial state, without releasing allocated capacity.
    ///
    /// All entities created prior to resetting are no longer considered members of this pool.
    pub fn reset(&mut self) {
        self.entities.clear();
        self.entities_free.clear();
        self.entity_index.clear();
        self.next_entity_key = 0;
    }

    /// Reserves capacity for at least `additional` more entities to be created without
    /// reallocation. The pool may reserve more space to avoid frequesnt reallocations.
    pub fn reserve(&mut self, additional: usize) {
        self.entities.reserve(additional);
        self.entity_index.reserve(additional);
    }

    /// Reserves capacity for at least `additional` more entities to be returned without
    /// reallocation. The pool may reserve more space to avoid frequesnt reallocations.
    pub fn reserve_returned(&mut self, additional: usize) {
        self.entities_free.reserve(additional);
    }

    /// Shrinks the capacity of this pool as much as possible.
    pub fn shrink_to_fit(&mut self) {
        self.entities.shrink_to_fit();
        self.entities_free.shrink_to_fit();
        self.entity_index.shrink_to_fit();
    }

    /// Returns the number of live entities in this pool.
    #[inline(always)]
    pub fn len(&self) -> usize {
        debug_assert_eq!(self.entities.len(), self.entity_index.len());
        self.entities.len()
    }

    /// Returns the number of returned entities in this pool that are ready to be recycled.
    #[inline(always)]
    pub fn len_returned(&self) -> usize {
        self.entities_free.len()
    }

    /// Returns the number of entities that this pool can create without reallocation.
    #[inline(always)]
    pub fn capacity(&self) -> usize {
        debug_assert_eq!(self.entities.capacity(), self.entity_index.capacity());
        self.entities.capacity()
    }

    /// Returns the number of entities that can be returned without reallocation.
    #[inline(always)]
    pub fn capacity_returned(&self) -> usize {
        self.entities_free.capacity()
    }
}

impl Index<usize> for EntityPool {
    type Output = Entity;
    /// Returns the `entity` at the given `index`.
    #[inline(always)]
    fn index(&self, index: usize) -> &Entity {
        &self.entities[index]
    }
}

impl Index<Entity> for EntityPool {
    type Output = usize;
    /// Returns the index of the given `entity`.
    #[inline(always)]
    fn index(&self, entity: Entity) -> &usize {
        &self.entity_index[entity.key() as usize]
    }
}

impl<'a> Index<&'a Entity> for EntityPool {
    type Output = usize;
    /// Returns the index of the given `entity`.
    #[inline(always)]
    fn index(&self, entity: &Entity) -> &usize {
        &self.entity_index[entity.key() as usize]
    }
}

impl<'a> Index<&'a usize> for EntityPool {
    type Output = Entity;
    /// Returns the `entity` at the given `index`.
    #[inline(always)]
    fn index(&self, index: &usize) -> &Entity {
        &self.entities[*index]
    }
}

#[test]
fn it_works() {
    let mut pool = EntityPool::new();
    let mut entities = Vec::<Entity>::new();
    for i in 0..5 {
        let (index, e) = pool.create_entity();
        assert_eq!(i, index);
        assert_eq!(e, pool.entity_at(index));
        assert_eq!(e, pool[i]);
        assert_eq!(index, pool.index_of(e));
        assert_eq!(index, pool[e]);
        assert!(!entities.contains(&e));
        assert!(pool.is_alive(e));
        entities.push(e);
    }
    let mut alive = 5;
    for e in entities.iter() {
        pool.return_entity(*e);
        assert!(!pool.is_alive(*e));
        alive -= 1;
        let mut expected_alive = 0;
        for (i_alive, e_alive) in pool.iter().enumerate() {
            assert!(pool.is_alive(*e_alive));
            assert_eq!(i_alive, pool.index_of(*e_alive));
            assert_eq!(i_alive, pool[*e_alive]);
            assert_eq!(i_alive, pool[e_alive]);
            assert_eq!(*e_alive, pool.entity_at(i_alive));
            assert_eq!(*e_alive, pool[i_alive]);
            assert_eq!(*e_alive, pool[&i_alive]);
            expected_alive += 1;
        }
        assert_eq!(expected_alive, alive);
    }
    for i in 0..5 {
        let (index, e) = pool.create_entity();
        assert_eq!(i, index);
        assert_eq!(e, pool.entity_at(index));
        assert_eq!(e, pool[i]);
        assert_eq!(index, pool.index_of(e));
        assert_eq!(index, pool[e]);
        assert!(!entities.contains(&e));
        assert!(pool.is_alive(e));
        entities.push(e);
    }
    let mut count = 0;
    for (index, e) in pool.iter().enumerate() {
        assert_eq!(index, pool.index_of(*e));
        assert_eq!(index, pool[e]);
        assert_eq!(*e, pool.entity_at(index));
        assert_eq!(*e, pool[index]);
        assert!(pool.is_alive(*e));
        count += 1;
    }
    assert_eq!(5, count);
}
<commit_msg>Adding addtional debug asserts<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Aaron Loucks <aloucks+github@cofront.net>
//
// 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.

use std::slice::Iter;
use std::hash::Hash;
use std::hash::Hasher;
use std::fmt::{self, Debug};
use std::ops::Index;

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Entity(u64);

const INVALID_ID: u64 = std::u64::MAX;
const INVALID_INDEX: usize = std::u32::MAX as usize;

impl Default for Entity {
    #[inline(always)]
    fn default() -> Entity {
        Entity(INVALID_ID)
    }
}

impl Debug for Entity {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Entity({{id: {}, key: {}, gen: {}}})", self.0, self.key(), self.gen())
    }
}

impl Hash for Entity {
    #[inline(always)]
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        state.write_u64(self.0)
    }
}

impl Entity {
    #[inline(always)]
    fn from_key_and_gen(key: u32, gen: u32) -> Entity {
        Entity(((key as u64) << 32) | (gen as u64))
    }

    #[inline(always)]
    pub fn id(&self) -> u64 {
        self.0
    }

    #[inline(always)]
    pub fn key(&self) -> u32 {
        (self.0 >> 32) as u32
    }

    #[inline(always)]
    pub fn gen(&self) -> u32 {
        (self.0 & 0xFFFFFFFF) as u32
    }
}

#[derive(Debug, Clone)]
pub struct EntityPool {
    entities: Vec<Entity>,
    entities_free: Vec<Entity>,
    entity_index: Vec<usize>, // entity_index[entity.key] => index; entities[index as usize]
    next_entity_key: u32,
}

impl Default for EntityPool {
    #[inline(always)]
    fn default() -> EntityPool {
        EntityPool::new()
    }
}

impl EntityPool {

    /// Creates a new, empty `EntityPool`.
    ///
    /// The `EntityPool` will not allocate until entities are created.
    ///
    pub fn new() -> EntityPool {
        EntityPool::with_capacity(0, 0)
    }

    /// Creates a new, empty `EntityPool` with the specified capacities.
    ///
    /// The `EntityPool` will able to create `create_capacity` and return `return_capacity`
    /// entities without reallocating. If either capacity is 0, their respective storage
    /// vectors will not allocate.
    pub fn with_capacity(create_capacity: usize, return_capacity: usize) -> EntityPool {
        EntityPool {
            entities: Vec::with_capacity(create_capacity),
            entities_free: Vec::with_capacity(return_capacity),
            entity_index: Vec::with_capacity(create_capacity),
            next_entity_key: 0
        }
    }

    /// Creates a unique entity.
    ///
    /// Returns the `Entity` and it's current `index`. The index is only guaranteed to remain
    /// valid until the next call to `return_entity`.
    pub fn create_entity(&mut self) -> (usize, Entity) {
        let (key, gen) = match self.entities_free.pop() {
            Some(entity) => {
                (entity.key(), entity.gen().wrapping_add(1))
            },
            None => {
                let key = self.next_entity_key;
                self.next_entity_key = key + 1;
                (key, 0)
            }
        };
        let entity = Entity::from_key_and_gen(key, gen);
        let index = self.entities.len();
        self.entities.push(entity);
        if key as usize != self.entity_index.len() {
            self.entity_index[key as usize] = index;
        }
        else {
            debug_assert_eq!(key as usize, self.entity_index.len());
            self.entity_index.push(index);
        }
        (index, entity)
    }

    /// Release ownership of the `entity`, allowing for it to be recycled. A recycled entity will
    /// have it's internal generation incremented, yielding a new, unique entity.
    ///
    /// Entities are stored in contiguous memory. When an entity is returned, the last entity is
    /// swaped into the returned entity's slot; thus indexes retrieved prior to returning an
    /// entity are potentially invalidated.
    ///
    /// # Panics
    ///
    /// Returning an entity more than once, or an entity created from another pool, results in
    /// undefined behavior.
    ///
    /// # Examples
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// let (_, e1) = pool.create_entity();
    /// pool.return_entity(e1);
    /// let (_, e2) = pool.create_entity();
    /// assert!(e1 != e2);
    /// ```
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// let (i1, e1) = pool.create_entity();
    /// let (i2, e2) = pool.create_entity();
    /// let (i3, e3) = pool.create_entity();
    /// assert_eq!(0, i1);
    /// assert_eq!(1, i2);
    /// assert_eq!(2, i3);
    /// assert_eq!(0, pool.index_of(e1));
    /// assert_eq!(1, pool.index_of(e2));
    /// assert_eq!(2, pool.index_of(e3));
    /// pool.return_entity(e2);
    /// assert_eq!(0, pool.index_of(e1));
    /// assert_eq!(1, pool.index_of(e3));
    /// ```
    pub fn return_entity(&mut self, entity: Entity) {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize];
        debug_assert!(index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                      entity));
        debug_assert_eq!(entity.gen(), self.entities[index].gen());
        self.entities_free.push(entity);
        self.entities.swap_remove(index);
        self.entity_index[key as usize] = INVALID_INDEX;
        match self.entities.get(index) {
            Some(e) => self.entity_index[e.key() as usize] = index,
            None    => {}
        };
    }

    /// Returns the current `index` of the given `entity`, which is only guaranteed to remain
    /// valid until the next call to `return_entity`.
    ///
    /// # Panics
    ///
    /// Querying the status of an entity from another pool results in undefined behavior.
    #[inline(always)]
    pub fn index_of(&self, entity: Entity) -> usize {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize] as usize;
        debug_assert!(index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                      entity));
        debug_assert_eq!(entity.gen(), self.entities[index].gen());
        index
    }

    /// Returns the current `entity` at the given `index`.
    ///
    /// # Panics
    ///
    /// Panics if the index is greater or equal to the number of live entities in this pool.
    #[inline(always)]
    pub fn entity_at(&self, index: usize) -> Entity {
        self.entities[index]
    }

    /// Returns `true` if this entity has not been returned.
    ///
    /// # Panics
    ///
    /// Querying the status of an entity from another pool results in undefined behavior.
    pub fn is_alive(&self, entity: Entity) -> bool {
        debug_assert!(entity != Entity::default());
        let key = entity.key();
        let index = self.entity_index[key as usize];
        if index != INVALID_INDEX {
            let other = self.entities[index];
            key == other.key() && entity.gen() == other.gen()
        }
        else {
            false
        }
    }

    /// Returns an iterator to the live entities. The `Enumerate` of the returned iterator will
    /// yield each `entity` and its current `index`.
    ///
    /// # Examples
    ///
    /// ```
    /// use entitypool::EntityPool;
    ///
    /// let mut pool = EntityPool::new();
    /// pool.create_entity();
    /// pool.create_entity();
    /// pool.create_entity();
    /// for (index, entity) in pool.iter().enumerate() {
    ///     assert_eq!(index, pool.index_of(*entity));
    ///     assert_eq!(*entity, pool.entity_at(index));
    /// }
    /// ```
    #[inline(always)]
    pub fn iter(&self) -> Iter<Entity> {
        self.entities.iter()
    }

    /// Resets the `EnitityPool` to its initial state, without releasing allocated capacity.
    ///
    /// All entities created prior to resetting are no longer considered members of this pool.
    pub fn reset(&mut self) {
        self.entities.clear();
        self.entities_free.clear();
        self.entity_index.clear();
        self.next_entity_key = 0;
    }

    /// Reserves capacity for at least `additional` more entities to be created without
    /// reallocation. The pool may reserve more space to avoid frequesnt reallocations.
    pub fn reserve(&mut self, additional: usize) {
        self.entities.reserve(additional);
        self.entity_index.reserve(additional);
    }

    /// Reserves capacity for at least `additional` more entities to be returned without
    /// reallocation. The pool may reserve more space to avoid frequesnt reallocations.
    pub fn reserve_returned(&mut self, additional: usize) {
        self.entities_free.reserve(additional);
    }

    /// Shrinks the capacity of this pool as much as possible.
    pub fn shrink_to_fit(&mut self) {
        self.entities.shrink_to_fit();
        self.entities_free.shrink_to_fit();
        self.entity_index.shrink_to_fit();
    }

    /// Returns the number of live entities in this pool.
    #[inline(always)]
    pub fn len(&self) -> usize {
        debug_assert_eq!(self.entities.len(), self.entity_index.len());
        self.entities.len()
    }

    /// Returns the number of returned entities in this pool that are ready to be recycled.
    #[inline(always)]
    pub fn len_returned(&self) -> usize {
        self.entities_free.len()
    }

    /// Returns the number of entities that this pool can create without reallocation.
    #[inline(always)]
    pub fn capacity(&self) -> usize {
        debug_assert_eq!(self.entities.capacity(), self.entity_index.capacity());
        self.entities.capacity()
    }

    /// Returns the number of entities that can be returned without reallocation.
    #[inline(always)]
    pub fn capacity_returned(&self) -> usize {
        self.entities_free.capacity()
    }
}

impl Index<usize> for EntityPool {
    type Output = Entity;
    /// Returns the `entity` at the given `index`.
    #[inline(always)]
    fn index(&self, index: usize) -> &Entity {
        &self.entities[index]
    }
}

impl Index<Entity> for EntityPool {
    type Output = usize;
    /// Returns the index of the given `entity`.
    #[inline(always)]
    fn index(&self, entity: Entity) -> &usize {
        let index = &self.entity_index[entity.key() as usize];
        debug_assert!(*index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                       entity));
        index
    }
}

impl<'a> Index<&'a Entity> for EntityPool {
    type Output = usize;
    /// Returns the index of the given `entity`.
    #[inline(always)]
    fn index(&self, entity: &Entity) -> &usize {
        let index = &self.entity_index[entity.key() as usize];
        debug_assert!(*index != INVALID_INDEX, format!("Invalid or previously freed entity: {:?}",
                                                       entity));
        index
    }
}

impl<'a> Index<&'a usize> for EntityPool {
    type Output = Entity;
    /// Returns the `entity` at the given `index`.
    #[inline(always)]
    fn index(&self, index: &usize) -> &Entity {
        &self.entities[*index]
    }
}

#[test]
fn it_works() {
    let mut pool = EntityPool::new();
    let mut entities = Vec::<Entity>::new();
    for i in 0..5 {
        let (index, e) = pool.create_entity();
        assert_eq!(i, index);
        assert_eq!(e, pool.entity_at(index));
        assert_eq!(e, pool[i]);
        assert_eq!(index, pool.index_of(e));
        assert_eq!(index, pool[e]);
        assert!(!entities.contains(&e));
        assert!(pool.is_alive(e));
        entities.push(e);
    }
    let mut alive = 5;
    for e in entities.iter() {
        pool.return_entity(*e);
        assert!(!pool.is_alive(*e));
        alive -= 1;
        let mut expected_alive = 0;
        for (i_alive, e_alive) in pool.iter().enumerate() {
            assert!(pool.is_alive(*e_alive));
            assert_eq!(i_alive, pool.index_of(*e_alive));
            assert_eq!(i_alive, pool[*e_alive]);
            assert_eq!(i_alive, pool[e_alive]);
            assert_eq!(*e_alive, pool.entity_at(i_alive));
            assert_eq!(*e_alive, pool[i_alive]);
            assert_eq!(*e_alive, pool[&i_alive]);
            expected_alive += 1;
        }
        assert_eq!(expected_alive, alive);
    }
    for i in 0..5 {
        let (index, e) = pool.create_entity();
        assert_eq!(i, index);
        assert_eq!(e, pool.entity_at(index));
        assert_eq!(e, pool[i]);
        assert_eq!(index, pool.index_of(e));
        assert_eq!(index, pool[e]);
        assert!(!entities.contains(&e));
        assert!(pool.is_alive(e));
        entities.push(e);
    }
    let mut count = 0;
    for (index, e) in pool.iter().enumerate() {
        assert_eq!(index, pool.index_of(*e));
        assert_eq!(index, pool[e]);
        assert_eq!(*e, pool.entity_at(index));
        assert_eq!(*e, pool[index]);
        assert!(pool.is_alive(*e));
        count += 1;
    }
    assert_eq!(5, count);
}
<|endoftext|>


<commit_before>extern crate libc;
use std::ffi::CString;
use std::mem::size_of;

extern crate rpgffi as pg;

macro_rules! log {
    ($msg:expr) => {
        elog(file!(), line!(), "log()", $msg)
    }
}

// Implementation of initialization and callbacks.

pub unsafe extern "C" fn init(cb: *mut pg::OutputPluginCallbacks) {
    (*cb).startup_cb = Some(startup);
    (*cb).begin_cb = Some(begin);
    (*cb).change_cb = Some(change);
    (*cb).commit_cb = Some(commit);
    (*cb).shutdown_cb = Some(shutdown);
}

unsafe extern "C" fn startup(ctx: *mut pg::Struct_LogicalDecodingContext,
                             options: *mut pg::OutputPluginOptions,
                             _is_init: pg::_bool) {
    use pg::Enum_OutputPluginOutputType::*;
    let last_relid = pg::palloc0(size_of::<pg::Oid>() as u64);
    (*ctx).output_plugin_private = last_relid;
    (*options).output_type = OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
}

unsafe extern "C" fn begin(ctx: *mut pg::Struct_LogicalDecodingContext,
                           txn: *mut pg::ReorderBufferTXN) {
    let s = CString::new("{ \"begin\": %u }").unwrap();
    pg::OutputPluginPrepareWrite(ctx, CTRUE);
    pg::appendStringInfo((*ctx).out, s.as_ptr(), (*txn).xid);
    pg::OutputPluginWrite(ctx, CTRUE);
}

unsafe extern "C" fn change(ctx: *mut pg::Struct_LogicalDecodingContext,
                            _txn: *mut pg::ReorderBufferTXN,
                            relation: pg::Relation,
                            change: *mut pg::ReorderBufferChange) {
    let relid = (*relation).rd_id;
    let last_relid: *mut pg::Oid =
        (*ctx).output_plugin_private as *mut pg::Oid;
    if *last_relid != relid {
        pg::OutputPluginPrepareWrite(ctx, CFALSE);
        append_schema(relation, (*ctx).out);
        pg::OutputPluginWrite(ctx, CFALSE);
        *last_relid = relid;
    }
    pg::OutputPluginPrepareWrite(ctx, CTRUE);
    append_change(relation, change, (*ctx).out);
    pg::OutputPluginWrite(ctx, CTRUE);
}

unsafe extern "C" fn commit(ctx: *mut pg::Struct_LogicalDecodingContext,
                            txn: *mut pg::ReorderBufferTXN,
                            _lsn: pg::XLogRecPtr) {
    let s = CString::new("{ \"commit\": %u, \"t\": \"%s\" }").unwrap();
    let t = pg::timestamptz_to_str((*txn).commit_time);
    pg::OutputPluginPrepareWrite(ctx, CTRUE);
    pg::appendStringInfo((*ctx).out, s.as_ptr(), (*txn).xid, t);
    pg::OutputPluginWrite(ctx, CTRUE);
    let last_relid: *mut pg::Oid =
        (*ctx).output_plugin_private as *mut pg::Oid;
    *last_relid = 0;
}

unsafe extern "C" fn shutdown(ctx: *mut pg::Struct_LogicalDecodingContext) {
    pg::pfree((*ctx).output_plugin_private);
}

trait PGAppend<T> {
    unsafe fn add_str(self, T);
    unsafe fn add_json(self, T);
}

impl<'a> PGAppend<&'a str> for pg::StringInfo {
    unsafe fn add_str(self, t: &'a str) {
        pg::appendStringInfoString(self, CString::new(t).unwrap().as_ptr());
    }
    unsafe fn add_json(self, t: &'a str) {
        pg::escape_json(self, CString::new(t).unwrap().as_ptr());
    }
}

impl PGAppend<*mut i8> for pg::StringInfo {
    unsafe fn add_str(self, t: *mut i8) {
        pg::appendStringInfoString(self, t);
    }
    unsafe fn add_json(self, t: *mut i8) {
        pg::escape_json(self, t);
    }
}

unsafe fn append_change(relation: pg::Relation,
                        change: *mut pg::ReorderBufferChange,
                        out: pg::StringInfo) {
    use pg::Enum_ReorderBufferChangeType::*;
    let relid = (*relation).rd_id;
    let name = pg::get_rel_name(relid);
    let ns = pg::get_namespace_name(pg::get_rel_namespace(relid));
    let qualified_name = pg::quote_qualified_identifier(ns, name);
    let tuple_desc = (*relation).rd_att;
    let tuples = (*change).data.tp();
    let tuple_new = (*tuples).newtuple;
    let tuple_old = (*tuples).oldtuple;
    let token = match (*change).action {
        REORDER_BUFFER_CHANGE_INSERT => "insert",
        REORDER_BUFFER_CHANGE_UPDATE => "update",
        REORDER_BUFFER_CHANGE_DELETE => "delete",
        _ => panic!("Unrecognized change action!"),
    };
    out.add_str("{ ");
    out.add_json(token);
    out.add_str(": ");
    append_tuple_buf_as_json(tuple_new, tuple_desc, out);
    if !tuple_old.is_null() {
        out.add_str(", \"@\": ");
        append_tuple_buf_as_json(tuple_old, tuple_desc, out);
    }
    out.add_str(", ");
    out.add_json("table");
    out.add_str(": ");
    out.add_json(qualified_name);
    out.add_str(" }");
}

unsafe fn append_tuple_buf_as_json(data: *mut pg::ReorderBufferTupleBuf,
                                   desc: pg::TupleDesc,
                                   out: pg::StringInfo) {
    if !data.is_null() {
        let heap_tuple = &mut (*data).tuple;
        let n = (*desc).natts as usize;
        let attrs = (*desc).attrs;

        // Pull out every single field to check for stale TOAST.
        let mut datums: Vec<pg::Datum> = Vec::new();
        let mut nulls: Vec<pg::_bool> = Vec::new();
        datums.resize(n, 0);
        nulls.resize(n, CFALSE);
        pg::heap_deform_tuple(heap_tuple,
                              desc,
                              datums.as_mut_ptr(),
                              nulls.as_mut_ptr());

        let mut skip: Vec<pg::Form_pg_attribute> = Vec::with_capacity(n);

        for i in 0..n {
            let datum: pg::Datum = datums[i];
            if datum == 0 {
                continue;
            }
            let attr = *attrs.offset(i as isize);
            let ty = (*attr).atttypid;
            if is_stale_toast(datum, ty) && (*attr).attisdropped == CFALSE {
                skip.push(attr);
            }
        }

        // Mark as dropped to trick row_to_json().
        for attr in &mut skip {
            (**attr).attisdropped = CTRUE;
        }

        let datum = pg::heap_copy_tuple_as_datum(heap_tuple, desc);
        let empty_oid: pg::Oid = 0;
        let json =
            pg::DirectFunctionCall1Coll(Some(row_to_json), empty_oid, datum);

        // Set back to true because who knows how else these attrs, which are
        // part of the passed in tuple description, are being used.
        for attr in &mut skip {
            (**attr).attisdropped = CFALSE;
        }

        let ptr = json as *const pg::Struct_varlena;
        let text = pg::text_to_cstring(ptr);
        pg::appendStringInfoString(out, text);
    } else {
        out.add_str("{}");
    }
}

unsafe fn append_schema(relation: pg::Relation, out: pg::StringInfo) {
    let relid = (*relation).rd_id;
    let tupdesc = (*relation).rd_att;
    let name = pg::get_rel_name(relid);
    let ns = pg::get_namespace_name(pg::get_rel_namespace(relid));
    let qualified_name = pg::quote_qualified_identifier(ns, name);
    out.add_str("{ ");
    out.add_json("schema");
    out.add_str(": ");
    out.add_str("[");
    let mut first: bool = true;
    for i in 0..(*tupdesc).natts {
        let attr = *(*tupdesc).attrs.offset(i as isize);
        let num = (*attr).attnum;
        if (*attr).attisdropped == 1 || num <= 0 {
            continue;
        }
        let col = pg::get_attname(relid, num);
        let typ = pg::format_type_be(pg::get_atttype(relid, num));
        if !first {
            out.add_str(",");
        } else {
            first = false;
        }
        out.add_str("{");
        out.add_json(col);
        out.add_str(":");
        out.add_json(typ);
        out.add_str("}");
    }
    out.add_str("]");
    out.add_str(", ");
    out.add_json("table");
    out.add_str(": ");
    out.add_json(qualified_name);
    out.add_str(" }");
}

extern "C" fn row_to_json(fcinfo: pg::FunctionCallInfo) -> pg::Datum {
    // We wrap the unsafe call to make it safe, so that it can be passed as
    // a function pointer to DirectFunctionCall1Coll(). This is a spurious
    // artifact of the generated binding.
    unsafe { pg::row_to_json(fcinfo) }
}

/** This is a simulation of `VARATT_IS_EXTERNAL_ONDISK`.

```c
#define VARATT_IS_EXTERNAL_ONDISK(PTR) \
  (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_ONDISK)

    #define VARATT_IS_EXTERNAL(PTR)             VARATT_IS_1B_E(PTR)

        #define VARATT_IS_1B_E(PTR) \
            ((((varattrib_1b *) (PTR))->va_header) == 0x01)

    #define VARTAG_EXTERNAL(PTR)                VARTAG_1B_E(PTR)

        #define VARTAG_1B_E(PTR) \
            (((varattrib_1b_e *) (PTR))->va_tag)
```
*/
unsafe fn is_stale_toast(datum: pg::Datum, type_id: pg::Oid) -> bool {
    use pg::Enum_vartag_external::VARTAG_ONDISK;
    let mut ignored: pg::Oid = 0;
    let mut is_variable_length: pg::_bool = CFALSE;
    pg::getTypeOutputInfo(type_id, &mut ignored, &mut is_variable_length);
    if is_variable_length == CTRUE {
        // Cast to varlena metadata type.
        let v = datum as *const pg::varattrib_1b_e;
        (*v).va_header == 0x01 && (*v).va_tag == (VARTAG_ONDISK as u8)
    } else {
        false
    }
}

// Symbols Postgres needs to find.

#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern "C" fn _PG_init() {}

#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern fn
    _PG_output_plugin_init(cb: *mut pg::OutputPluginCallbacks) {
    init(cb);
}

// Miscellaneous.

const CTRUE: pg::_bool = 1;
const CFALSE: pg::_bool = 0;

pub unsafe fn elog(file: &str, line: u32, function: &str, msg: &str) {
    let level = 15;         // The LOG level of logging is normally server-only
    pg::elog_start(CString::new(file).unwrap().as_ptr(),
                   line as ::std::os::raw::c_int,
                   CString::new(function).unwrap().as_ptr());
    pg::elog_finish(level,
                    CString::new("%s").unwrap().as_ptr(),
                    CString::new(msg).unwrap().as_ptr());
}
<commit_msg>Test for dropped attributes before TOAST test<commit_after>extern crate libc;
use std::ffi::CString;
use std::mem::size_of;

extern crate rpgffi as pg;

macro_rules! log {
    ($msg:expr) => {
        elog(file!(), line!(), "log()", $msg)
    }
}

// Implementation of initialization and callbacks.

pub unsafe extern "C" fn init(cb: *mut pg::OutputPluginCallbacks) {
    (*cb).startup_cb = Some(startup);
    (*cb).begin_cb = Some(begin);
    (*cb).change_cb = Some(change);
    (*cb).commit_cb = Some(commit);
    (*cb).shutdown_cb = Some(shutdown);
}

unsafe extern "C" fn startup(ctx: *mut pg::Struct_LogicalDecodingContext,
                             options: *mut pg::OutputPluginOptions,
                             _is_init: pg::_bool) {
    use pg::Enum_OutputPluginOutputType::*;
    let last_relid = pg::palloc0(size_of::<pg::Oid>() as u64);
    (*ctx).output_plugin_private = last_relid;
    (*options).output_type = OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
}

unsafe extern "C" fn begin(ctx: *mut pg::Struct_LogicalDecodingContext,
                           txn: *mut pg::ReorderBufferTXN) {
    let s = CString::new("{ \"begin\": %u }").unwrap();
    pg::OutputPluginPrepareWrite(ctx, CTRUE);
    pg::appendStringInfo((*ctx).out, s.as_ptr(), (*txn).xid);
    pg::OutputPluginWrite(ctx, CTRUE);
}

unsafe extern "C" fn change(ctx: *mut pg::Struct_LogicalDecodingContext,
                            _txn: *mut pg::ReorderBufferTXN,
                            relation: pg::Relation,
                            change: *mut pg::ReorderBufferChange) {
    let relid = (*relation).rd_id;
    let last_relid: *mut pg::Oid =
        (*ctx).output_plugin_private as *mut pg::Oid;
    if *last_relid != relid {
        pg::OutputPluginPrepareWrite(ctx, CFALSE);
        append_schema(relation, (*ctx).out);
        pg::OutputPluginWrite(ctx, CFALSE);
        *last_relid = relid;
    }
    pg::OutputPluginPrepareWrite(ctx, CTRUE);
    append_change(relation, change, (*ctx).out);
    pg::OutputPluginWrite(ctx, CTRUE);
}

unsafe extern "C" fn commit(ctx: *mut pg::Struct_LogicalDecodingContext,
                            txn: *mut pg::ReorderBufferTXN,
                            _lsn: pg::XLogRecPtr) {
    let s = CString::new("{ \"commit\": %u, \"t\": \"%s\" }").unwrap();
    let t = pg::timestamptz_to_str((*txn).commit_time);
    pg::OutputPluginPrepareWrite(ctx, CTRUE);
    pg::appendStringInfo((*ctx).out, s.as_ptr(), (*txn).xid, t);
    pg::OutputPluginWrite(ctx, CTRUE);
    let last_relid: *mut pg::Oid =
        (*ctx).output_plugin_private as *mut pg::Oid;
    *last_relid = 0;
}

unsafe extern "C" fn shutdown(ctx: *mut pg::Struct_LogicalDecodingContext) {
    pg::pfree((*ctx).output_plugin_private);
}

trait PGAppend<T> {
    unsafe fn add_str(self, T);
    unsafe fn add_json(self, T);
}

impl<'a> PGAppend<&'a str> for pg::StringInfo {
    unsafe fn add_str(self, t: &'a str) {
        pg::appendStringInfoString(self, CString::new(t).unwrap().as_ptr());
    }
    unsafe fn add_json(self, t: &'a str) {
        pg::escape_json(self, CString::new(t).unwrap().as_ptr());
    }
}

impl PGAppend<*mut i8> for pg::StringInfo {
    unsafe fn add_str(self, t: *mut i8) {
        pg::appendStringInfoString(self, t);
    }
    unsafe fn add_json(self, t: *mut i8) {
        pg::escape_json(self, t);
    }
}

unsafe fn append_change(relation: pg::Relation,
                        change: *mut pg::ReorderBufferChange,
                        out: pg::StringInfo) {
    use pg::Enum_ReorderBufferChangeType::*;
    let relid = (*relation).rd_id;
    let name = pg::get_rel_name(relid);
    let ns = pg::get_namespace_name(pg::get_rel_namespace(relid));
    let qualified_name = pg::quote_qualified_identifier(ns, name);
    let tuple_desc = (*relation).rd_att;
    let tuples = (*change).data.tp();
    let tuple_new = (*tuples).newtuple;
    let tuple_old = (*tuples).oldtuple;
    let token = match (*change).action {
        REORDER_BUFFER_CHANGE_INSERT => "insert",
        REORDER_BUFFER_CHANGE_UPDATE => "update",
        REORDER_BUFFER_CHANGE_DELETE => "delete",
        _ => panic!("Unrecognized change action!"),
    };
    out.add_str("{ ");
    out.add_json(token);
    out.add_str(": ");
    append_tuple_buf_as_json(tuple_new, tuple_desc, out);
    if !tuple_old.is_null() {
        out.add_str(", \"@\": ");
        append_tuple_buf_as_json(tuple_old, tuple_desc, out);
    }
    out.add_str(", ");
    out.add_json("table");
    out.add_str(": ");
    out.add_json(qualified_name);
    out.add_str(" }");
}

unsafe fn append_tuple_buf_as_json(data: *mut pg::ReorderBufferTupleBuf,
                                   desc: pg::TupleDesc,
                                   out: pg::StringInfo) {
    if !data.is_null() {
        let heap_tuple = &mut (*data).tuple;
        let n = (*desc).natts as usize;
        let attrs = (*desc).attrs;

        // Pull out every single field to check for stale TOAST.
        let mut datums: Vec<pg::Datum> = Vec::new();
        let mut nulls: Vec<pg::_bool> = Vec::new();
        datums.resize(n, 0);
        nulls.resize(n, CFALSE);
        pg::heap_deform_tuple(heap_tuple,
                              desc,
                              datums.as_mut_ptr(),
                              nulls.as_mut_ptr());

        let mut skip: Vec<pg::Form_pg_attribute> = Vec::with_capacity(n);

        for i in 0..n {
            let datum: pg::Datum = datums[i];
            if datum == 0 {
                continue;
            }
            let attr = *attrs.offset(i as isize);
            let ty = (*attr).atttypid;
            if (*attr).attisdropped == CFALSE && is_stale_toast(datum, ty) {
                skip.push(attr);
            }
        }

        // Mark as dropped to trick row_to_json().
        for attr in &mut skip {
            (**attr).attisdropped = CTRUE;
        }

        let datum = pg::heap_copy_tuple_as_datum(heap_tuple, desc);
        let empty_oid: pg::Oid = 0;
        let json =
            pg::DirectFunctionCall1Coll(Some(row_to_json), empty_oid, datum);

        // Set back to true because who knows how else these attrs, which are
        // part of the passed in tuple description, are being used.
        for attr in &mut skip {
            (**attr).attisdropped = CFALSE;
        }

        let ptr = json as *const pg::Struct_varlena;
        let text = pg::text_to_cstring(ptr);
        pg::appendStringInfoString(out, text);
    } else {
        out.add_str("{}");
    }
}

unsafe fn append_schema(relation: pg::Relation, out: pg::StringInfo) {
    let relid = (*relation).rd_id;
    let tupdesc = (*relation).rd_att;
    let name = pg::get_rel_name(relid);
    let ns = pg::get_namespace_name(pg::get_rel_namespace(relid));
    let qualified_name = pg::quote_qualified_identifier(ns, name);
    out.add_str("{ ");
    out.add_json("schema");
    out.add_str(": ");
    out.add_str("[");
    let mut first: bool = true;
    for i in 0..(*tupdesc).natts {
        let attr = *(*tupdesc).attrs.offset(i as isize);
        let num = (*attr).attnum;
        if (*attr).attisdropped == 1 || num <= 0 {
            continue;
        }
        let col = pg::get_attname(relid, num);
        let typ = pg::format_type_be(pg::get_atttype(relid, num));
        if !first {
            out.add_str(",");
        } else {
            first = false;
        }
        out.add_str("{");
        out.add_json(col);
        out.add_str(":");
        out.add_json(typ);
        out.add_str("}");
    }
    out.add_str("]");
    out.add_str(", ");
    out.add_json("table");
    out.add_str(": ");
    out.add_json(qualified_name);
    out.add_str(" }");
}

extern "C" fn row_to_json(fcinfo: pg::FunctionCallInfo) -> pg::Datum {
    // We wrap the unsafe call to make it safe, so that it can be passed as
    // a function pointer to DirectFunctionCall1Coll(). This is a spurious
    // artifact of the generated binding.
    unsafe { pg::row_to_json(fcinfo) }
}

/** This is a simulation of `VARATT_IS_EXTERNAL_ONDISK`.

```c
#define VARATT_IS_EXTERNAL_ONDISK(PTR) \
  (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_ONDISK)

    #define VARATT_IS_EXTERNAL(PTR)             VARATT_IS_1B_E(PTR)

        #define VARATT_IS_1B_E(PTR) \
            ((((varattrib_1b *) (PTR))->va_header) == 0x01)

    #define VARTAG_EXTERNAL(PTR)                VARTAG_1B_E(PTR)

        #define VARTAG_1B_E(PTR) \
            (((varattrib_1b_e *) (PTR))->va_tag)
```
*/
unsafe fn is_stale_toast(datum: pg::Datum, type_id: pg::Oid) -> bool {
    use pg::Enum_vartag_external::VARTAG_ONDISK;
    let mut ignored: pg::Oid = 0;
    let mut is_variable_length: pg::_bool = CFALSE;
    pg::getTypeOutputInfo(type_id, &mut ignored, &mut is_variable_length);
    if is_variable_length == CTRUE {
        // Cast to varlena metadata type.
        let v = datum as *const pg::varattrib_1b_e;
        (*v).va_header == 0x01 && (*v).va_tag == (VARTAG_ONDISK as u8)
    } else {
        false
    }
}

// Symbols Postgres needs to find.

#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern "C" fn _PG_init() {}

#[allow(non_snake_case)]
#[no_mangle]
pub unsafe extern fn
    _PG_output_plugin_init(cb: *mut pg::OutputPluginCallbacks) {
    init(cb);
}

// Miscellaneous.

const CTRUE: pg::_bool = 1;
const CFALSE: pg::_bool = 0;

pub unsafe fn elog(file: &str, line: u32, function: &str, msg: &str) {
    let level = 15;         // The LOG level of logging is normally server-only
    pg::elog_start(CString::new(file).unwrap().as_ptr(),
                   line as ::std::os::raw::c_int,
                   CString::new(function).unwrap().as_ptr());
    pg::elog_finish(level,
                    CString::new("%s").unwrap().as_ptr(),
                    CString::new(msg).unwrap().as_ptr());
}
<|endoftext|>


<commit_before>#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]

extern crate semver;
extern crate url;

use std::io::{Acceptor, BufferedReader, IoResult, Listener, RefReader, RefWriter};
use std::io::net::ip;
use std::io::net::tcp;
use std::io::util::LimitReader;
use std::sync;
use std::comm::{Handle, Select};

pub use common::Header;
pub use common::Method;
pub use common::StatusCode;
pub use response::Response;

mod client;
mod common;
mod response;

/// The main class of this library.
/// Create a new server using `Server::new()`.
pub struct Server {
    connections_receiver: Receiver<IoResult<client::ClientConnection>>,
    requests_receiver: sync::Mutex<Vec<Receiver<Request>>>,
}

/// Represents an HTTP request made by a client.
pub struct Request {
    read_socket: LimitReader<BufferedReader<tcp::TcpStream>>,
    write_socket: tcp::TcpStream,
    method: Method,
    path: url::Path,
    http_version: semver::Version,
    headers: Vec<Header>,
    body_length: uint,
}

pub struct ResponseWriter {
    writer: tcp::TcpStream
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server that listens on the specified address.
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the TcpAcceptor
        let server = try!(tcp::TcpListener::bind(
            format!("{}", addr.ip).as_slice(), addr.port).listen());

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx, rx) = channel();
        spawn(proc() {
            let mut server = server;

            loop {
                let val = server.accept().map(|sock| client::ClientConnection::new(sock));

                match tx.send_opt(val) {
                    Err(_) => break,
                    _ => ()
                }
            }
        });

        // result
        Ok(Server {
            connections_receiver: rx,
            requests_receiver: sync::Mutex::new(Vec::new()),
        })
    }

    /// Returns the number of clients currently connected to the server.
    pub fn get_num_connections(&self) -> uint {
        self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> Request {
        loop {
            let (connec, rq, errord) = self.recv_impl();

            // removing closed connections
            {
                let mut errord = errord;
                errord.sort_by(|a, b| b.cmp(a));
                let mut locked_receivers = self.requests_receiver.lock();
                for id in errord.move_iter() {
                    locked_receivers.remove(id);
                }
            }

            // adding the connection, if any
            match connec {
                None => (),
                Some(c) => self.add_client(c)
            };

            // returning the request, if any
            match rq {
                Some(rq) => return rq,
                None => ()
            };
        }
    }

    /// Returns either a new client or a request, plus a list of connections that are
    ///   no longer valid
    fn recv_impl(&self) -> (Option<client::ClientConnection>, Option<Request>, Vec<uint>) {
        let mut locked_receivers = self.requests_receiver.lock();

        let select = Select::new();

        // add the handle for a new connection to the select
        let mut connections_handle = select.handle(&self.connections_receiver);
        unsafe { connections_handle.add() };

        // add all the existing connections
        let mut rq_handles = Vec::new();
        for rc in locked_receivers.iter() {
            rq_handles.push(select.handle(rc));
        }
        for h in rq_handles.mut_iter() { unsafe { h.add() } }

        // getting the result
        loop {
            let handle_id = select.wait();

            // checking for connections_handle
            if handle_id == connections_handle.id() {
                match connections_handle.recv_opt() {
                    Ok(Ok(connec)) => {
                        for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                        unsafe { connections_handle.remove() };
                        return (Some(connec), None, Vec::new());
                    },
                    _ => {
                        println!("The server socket crashed");
                        continue
                    }
                }
            }

            // checking the clients
            let mut result = None;
            let mut errord = Vec::new();

            for (id, h) in rq_handles.mut_iter().enumerate() {
                if handle_id == h.id() {
                    match h.recv_opt() {
                        Ok(rq) => { result = Some(rq); break },
                        Err(_) => { errord.push(id); }
                    }
                }
            }

            if result.is_some() {
                for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                unsafe { connections_handle.remove() };

                return (None, result, errord)

            } else if errord.len() >= 1 {
                for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                unsafe { connections_handle.remove() };

                return (None, None, errord)
            }
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> Option<Request> {
        self.process_new_clients();

        {
            let mut locked_receivers = self.requests_receiver.lock();
            for rx in locked_receivers.iter() {
                let attempt = rx.try_recv();
                if attempt.is_ok() {       // TODO: remove the channel if it is closed
                    return Some(attempt.unwrap());
                }
            }
        }

        None
    }

    /// Does not block.
    fn process_new_clients(&self) {
        let mut new_clients = Vec::new();

        // we add all the elements available on connections_receiver to new_clients
        loop {
            match self.connections_receiver.try_recv() {
                Ok(client) => new_clients.push(client),
                Err(_) => break
            }
        }

        // for each new client, spawning a task that will
        // continuously try to read a Request
        for client in new_clients.move_iter().filter_map(|c| c.ok()) {
            self.add_client(client)
        }
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: client::ClientConnection) {
        let (tx, rx) = channel();
        spawn(proc() {
            let mut client = client;
            // TODO: when the channel is being closed, immediatly notify the task
            client.advance(|rq| tx.send_opt(rq).is_ok());
        });
        self.requests_receiver.lock().push(rx);
    }
}

impl Request {
    /// Returns the method requested by the client (eg. GET, POST, etc.)
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the length of the body in bytes.
    pub fn get_body_length(&self) -> uint {
        self.body_length
    }

    /// Allows to read the body of the request.
    pub fn as_reader<'a>(&'a mut self)
        -> RefReader<'a, LimitReader<BufferedReader<tcp::TcpStream>>>
    {
        fn as_reader_impl<'a, R: Reader>(elem: &'a mut R) -> RefReader<'a, R> {
            elem.by_ref()
        }
        as_reader_impl(&mut self.read_socket)
    }

    /// Turns the Request into a writer.
    /// The writer has a raw access to the stream to the user.
    /// This function is useful for things like CGI.
    pub fn into_writer(self) -> ResponseWriter {
        Request::finish_reading(self.read_socket);

        ResponseWriter { writer: self.write_socket }
    }

    /// Sends a response to this request.
    pub fn respond<R: Reader>(self, response: Response<R>) {
        Request::finish_reading(self.read_socket);

        match response.raw_print(self.write_socket) {
            Ok(_) => (),
            Err(err) => println!("error while sending answer: {}", err)     // TODO: handle better?
        }
    }

    /// Consumes the rest of the request's body in the TcpStream.
    fn finish_reading(reader: LimitReader<BufferedReader<tcp::TcpStream>>) {
        let remaining_to_read = reader.limit();
        let underlying = reader.unwrap().consume(remaining_to_read);
    }
}

impl Writer for ResponseWriter {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.writer.write(buf)
    }

    #[inline]
    fn flush(&mut self) -> IoResult<()> {
        self.writer.flush()
    }

    #[inline]
    fn write_fmt(&mut self, fmt: &::std::fmt::Arguments) -> IoResult<()> {
        self.writer.write_fmt(fmt)
    }

    #[inline]
    fn write_str(&mut self, s: &str) -> IoResult<()> {
        self.writer.write_str(s)
    }

    #[inline]
    fn write_line(&mut self, s: &str) -> IoResult<()> {
        self.writer.write_line(s)
    }

    #[inline]
    fn write_char(&mut self, c: char) -> IoResult<()> {
        self.writer.write_char(c)
    }

    #[inline]
    fn write_int(&mut self, n: int) -> IoResult<()> {
        self.writer.write_int(n)
    }

    #[inline]
    fn write_uint(&mut self, n: uint) -> IoResult<()> {
        self.writer.write_uint(n)
    }

    #[inline]
    fn write_le_uint(&mut self, n: uint) -> IoResult<()> {
        self.writer.write_le_uint(n)
    }

    #[inline]
    fn write_le_int(&mut self, n: int) -> IoResult<()> {
        self.writer.write_le_int(n)
    }

    #[inline]
    fn write_be_uint(&mut self, n: uint) -> IoResult<()> {
        self.writer.write_be_uint(n)
    }

    #[inline]
    fn write_be_int(&mut self, n: int) -> IoResult<()> {
        self.writer.write_be_int(n)
    }

    #[inline]
    fn write_be_u64(&mut self, n: u64) -> IoResult<()> {
        self.writer.write_be_u64(n)
    }

    #[inline]
    fn write_be_u32(&mut self, n: u32) -> IoResult<()> {
        self.writer.write_be_u32(n)
    }

    #[inline]
    fn write_be_u16(&mut self, n: u16) -> IoResult<()> {
        self.writer.write_be_u16(n)
    }

    #[inline]
    fn write_be_i64(&mut self, n: i64) -> IoResult<()> {
        self.writer.write_be_i64(n)
    }

    #[inline]
    fn write_be_i32(&mut self, n: i32) -> IoResult<()> {
        self.writer.write_be_i32(n)
    }

    #[inline]
    fn write_be_i16(&mut self, n: i16) -> IoResult<()> {
        self.writer.write_be_i16(n)
    }

    #[inline]
    fn write_be_f64(&mut self, f: f64) -> IoResult<()> {
        self.writer.write_be_f64(f)
    }

    #[inline]
    fn write_be_f32(&mut self, f: f32) -> IoResult<()> {
        self.writer.write_be_f32(f)
    }

    #[inline]
    fn write_le_u64(&mut self, n: u64) -> IoResult<()> {
        self.writer.write_le_u64(n)
    }

    #[inline]
    fn write_le_u32(&mut self, n: u32) -> IoResult<()> {
        self.writer.write_le_u32(n)
    }

    #[inline]
    fn write_le_u16(&mut self, n: u16) -> IoResult<()> {
        self.writer.write_le_u16(n)
    }

    #[inline]
    fn write_le_i64(&mut self, n: i64) -> IoResult<()> {
        self.writer.write_le_i64(n)
    }

    #[inline]
    fn write_le_i32(&mut self, n: i32) -> IoResult<()> {
        self.writer.write_le_i32(n)
    }

    #[inline]
    fn write_le_i16(&mut self, n: i16) -> IoResult<()> {
        self.writer.write_le_i16(n)
    }

    #[inline]
    fn write_le_f64(&mut self, f: f64) -> IoResult<()> {
        self.writer.write_le_f64(f)
    }

    #[inline]
    fn write_le_f32(&mut self, f: f32) -> IoResult<()> {
        self.writer.write_le_f32(f)
    }

    #[inline]
    fn write_u8(&mut self, n: u8) -> IoResult<()> {
        self.writer.write_u8(n)
    }

    #[inline]
    fn write_i8(&mut self, n: i8) -> IoResult<()> {
        self.writer.write_i8(n)
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {})",
            self.method, self.path)).fmt(formatter)
    }
}
<commit_msg>Cleaner implementation of recv()<commit_after>#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]

extern crate semver;
extern crate url;

use std::io::{Acceptor, BufferedReader, IoResult, Listener, RefReader, RefWriter};
use std::io::net::ip;
use std::io::net::tcp;
use std::io::util::LimitReader;
use std::sync;
use std::comm::{Handle, Select};
use client::ClientConnection;

pub use common::Header;
pub use common::Method;
pub use common::StatusCode;
pub use response::Response;

mod client;
mod common;
mod response;

/// The main class of this library.
/// Create a new server using `Server::new()`.
pub struct Server {
    connections_receiver: Receiver<IoResult<ClientConnection>>,
    requests_receiver: sync::Mutex<Vec<Receiver<Request>>>,
}

/// Represents an HTTP request made by a client.
pub struct Request {
    read_socket: LimitReader<BufferedReader<tcp::TcpStream>>,
    write_socket: tcp::TcpStream,
    method: Method,
    path: url::Path,
    http_version: semver::Version,
    headers: Vec<Header>,
    body_length: uint,
}

pub struct ResponseWriter {
    writer: tcp::TcpStream
}

enum ServerRecvEvent {
    NewRequest(Request),
    NewClient(ClientConnection),
    ReceiverErrord(uint),
    ServerSocketCrashed
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server that listens on the specified address.
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the TcpAcceptor
        let server = try!(tcp::TcpListener::bind(
            format!("{}", addr.ip).as_slice(), addr.port).listen());

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx, rx) = channel();
        spawn(proc() {
            let mut server = server;

            loop {
                let val = server.accept().map(|sock| ClientConnection::new(sock));

                match tx.send_opt(val) {
                    Err(_) => break,
                    _ => ()
                }
            }
        });

        // result
        Ok(Server {
            connections_receiver: rx,
            requests_receiver: sync::Mutex::new(Vec::new()),
        })
    }

    /// Returns the number of clients currently connected to the server.
    pub fn get_num_connections(&self) -> uint {
        self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> Request {
        loop {
            match self.recv_impl() {
                NewClient(client) => self.add_client(client),
                NewRequest(rq) => return rq,
                ReceiverErrord(id) => { self.requests_receiver.lock().remove(id); },
                _ => println!("The server socket crashed")
            }
        }
    }

    /// Returns either a new client or a request, plus a list of connections that are
    ///   no longer valid
    fn recv_impl(&self) -> ServerRecvEvent {
        let mut locked_receivers = self.requests_receiver.lock();

        let select = Select::new();

        // add the handle for a new connection to the select
        let mut connections_handle = select.handle(&self.connections_receiver);
        unsafe { connections_handle.add() };

        // add all the existing connections
        let mut rq_handles = Vec::new();
        for rc in locked_receivers.iter() {
            rq_handles.push(select.handle(rc));
        }
        for h in rq_handles.mut_iter() { unsafe { h.add() } }

        // getting the result
        loop {
            let handle_id = select.wait();

            // checking for connections_handle
            if handle_id == connections_handle.id() {
                match connections_handle.recv_opt() {
                    Ok(Ok(connec)) => {
                        for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                        unsafe { connections_handle.remove() };
                        return NewClient(connec);
                    },
                    _ => {
                        for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                        unsafe { connections_handle.remove() };
                        return ServerSocketCrashed
                    }
                }
            }

            // checking the clients
            let mut result = None;
            for (id, h) in rq_handles.mut_iter().enumerate() {
                if handle_id == h.id() {
                    match h.recv_opt() {
                        Ok(rq) => result = Some(NewRequest(rq)),
                        Err(_) => result = Some(ReceiverErrord(id))
                    }
                    break
                }
            };

            match result {
                None => continue,
                Some(r) => {
                    for h in rq_handles.mut_iter() { unsafe { h.remove() } };
                    unsafe { connections_handle.remove() };
                    return r;
                }
            }
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> Option<Request> {
        self.process_new_clients();

        {
            let mut locked_receivers = self.requests_receiver.lock();
            for rx in locked_receivers.iter() {
                let attempt = rx.try_recv();
                if attempt.is_ok() {       // TODO: remove the channel if it is closed
                    return Some(attempt.unwrap());
                }
            }
        }

        None
    }

    /// Does not block.
    fn process_new_clients(&self) {
        let mut new_clients = Vec::new();

        // we add all the elements available on connections_receiver to new_clients
        loop {
            match self.connections_receiver.try_recv() {
                Ok(client) => new_clients.push(client),
                Err(_) => break
            }
        }

        // for each new client, spawning a task that will
        // continuously try to read a Request
        for client in new_clients.move_iter().filter_map(|c| c.ok()) {
            self.add_client(client)
        }
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: ClientConnection) {
        let (tx, rx) = channel();
        spawn(proc() {
            let mut client = client;
            // TODO: when the channel is being closed, immediatly notify the task
            client.advance(|rq| tx.send_opt(rq).is_ok());
        });
        self.requests_receiver.lock().push(rx);
    }
}

impl Request {
    /// Returns the method requested by the client (eg. GET, POST, etc.)
    pub fn get_method<'a>(&'a self) -> &'a Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    pub fn get_url<'a>(&'a self) -> &'a url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    pub fn get_headers<'a>(&'a self) -> &'a [Header] {
        self.headers.as_slice()
    }

    /// Returns the length of the body in bytes.
    pub fn get_body_length(&self) -> uint {
        self.body_length
    }

    /// Allows to read the body of the request.
    pub fn as_reader<'a>(&'a mut self)
        -> RefReader<'a, LimitReader<BufferedReader<tcp::TcpStream>>>
    {
        fn as_reader_impl<'a, R: Reader>(elem: &'a mut R) -> RefReader<'a, R> {
            elem.by_ref()
        }
        as_reader_impl(&mut self.read_socket)
    }

    /// Turns the Request into a writer.
    /// The writer has a raw access to the stream to the user.
    /// This function is useful for things like CGI.
    pub fn into_writer(self) -> ResponseWriter {
        Request::finish_reading(self.read_socket);

        ResponseWriter { writer: self.write_socket }
    }

    /// Sends a response to this request.
    pub fn respond<R: Reader>(self, response: Response<R>) {
        Request::finish_reading(self.read_socket);

        match response.raw_print(self.write_socket) {
            Ok(_) => (),
            Err(err) => println!("error while sending answer: {}", err)     // TODO: handle better?
        }
    }

    /// Consumes the rest of the request's body in the TcpStream.
    fn finish_reading(reader: LimitReader<BufferedReader<tcp::TcpStream>>) {
        let remaining_to_read = reader.limit();
        let underlying = reader.unwrap().consume(remaining_to_read);
    }
}

impl Writer for ResponseWriter {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.writer.write(buf)
    }

    #[inline]
    fn flush(&mut self) -> IoResult<()> {
        self.writer.flush()
    }

    #[inline]
    fn write_fmt(&mut self, fmt: &::std::fmt::Arguments) -> IoResult<()> {
        self.writer.write_fmt(fmt)
    }

    #[inline]
    fn write_str(&mut self, s: &str) -> IoResult<()> {
        self.writer.write_str(s)
    }

    #[inline]
    fn write_line(&mut self, s: &str) -> IoResult<()> {
        self.writer.write_line(s)
    }

    #[inline]
    fn write_char(&mut self, c: char) -> IoResult<()> {
        self.writer.write_char(c)
    }

    #[inline]
    fn write_int(&mut self, n: int) -> IoResult<()> {
        self.writer.write_int(n)
    }

    #[inline]
    fn write_uint(&mut self, n: uint) -> IoResult<()> {
        self.writer.write_uint(n)
    }

    #[inline]
    fn write_le_uint(&mut self, n: uint) -> IoResult<()> {
        self.writer.write_le_uint(n)
    }

    #[inline]
    fn write_le_int(&mut self, n: int) -> IoResult<()> {
        self.writer.write_le_int(n)
    }

    #[inline]
    fn write_be_uint(&mut self, n: uint) -> IoResult<()> {
        self.writer.write_be_uint(n)
    }

    #[inline]
    fn write_be_int(&mut self, n: int) -> IoResult<()> {
        self.writer.write_be_int(n)
    }

    #[inline]
    fn write_be_u64(&mut self, n: u64) -> IoResult<()> {
        self.writer.write_be_u64(n)
    }

    #[inline]
    fn write_be_u32(&mut self, n: u32) -> IoResult<()> {
        self.writer.write_be_u32(n)
    }

    #[inline]
    fn write_be_u16(&mut self, n: u16) -> IoResult<()> {
        self.writer.write_be_u16(n)
    }

    #[inline]
    fn write_be_i64(&mut self, n: i64) -> IoResult<()> {
        self.writer.write_be_i64(n)
    }

    #[inline]
    fn write_be_i32(&mut self, n: i32) -> IoResult<()> {
        self.writer.write_be_i32(n)
    }

    #[inline]
    fn write_be_i16(&mut self, n: i16) -> IoResult<()> {
        self.writer.write_be_i16(n)
    }

    #[inline]
    fn write_be_f64(&mut self, f: f64) -> IoResult<()> {
        self.writer.write_be_f64(f)
    }

    #[inline]
    fn write_be_f32(&mut self, f: f32) -> IoResult<()> {
        self.writer.write_be_f32(f)
    }

    #[inline]
    fn write_le_u64(&mut self, n: u64) -> IoResult<()> {
        self.writer.write_le_u64(n)
    }

    #[inline]
    fn write_le_u32(&mut self, n: u32) -> IoResult<()> {
        self.writer.write_le_u32(n)
    }

    #[inline]
    fn write_le_u16(&mut self, n: u16) -> IoResult<()> {
        self.writer.write_le_u16(n)
    }

    #[inline]
    fn write_le_i64(&mut self, n: i64) -> IoResult<()> {
        self.writer.write_le_i64(n)
    }

    #[inline]
    fn write_le_i32(&mut self, n: i32) -> IoResult<()> {
        self.writer.write_le_i32(n)
    }

    #[inline]
    fn write_le_i16(&mut self, n: i16) -> IoResult<()> {
        self.writer.write_le_i16(n)
    }

    #[inline]
    fn write_le_f64(&mut self, f: f64) -> IoResult<()> {
        self.writer.write_le_f64(f)
    }

    #[inline]
    fn write_le_f32(&mut self, f: f32) -> IoResult<()> {
        self.writer.write_le_f32(f)
    }

    #[inline]
    fn write_u8(&mut self, n: u8) -> IoResult<()> {
        self.writer.write_u8(n)
    }

    #[inline]
    fn write_i8(&mut self, n: i8) -> IoResult<()> {
        self.writer.write_i8(n)
    }
}

impl std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut std::fmt::Formatter)
        -> Result<(), std::fmt::FormatError>
    {
        (format!("Request({} {})",
            self.method, self.path)).fmt(formatter)
    }
}
<|endoftext|>