<commit_before>/**
Create an input object

Input objects are used as data carriers for complex input values to
fields and mutations. Unlike the other helper macros,
`graphql_input_object!` actually *creates* the struct you define. It
does not add anything to the struct definition itself - what you type
is what will be generated:

```rust
# #[macro_use] extern crate juniper;

graphql_input_object!(
    description: "Coordinates for the user"

    struct Coordinates {
        longitude: f64 as "The X coordinate, from -180 to +180",
        latitude: f64 as "The Y coordinate, from -90 to +90",
    }
);

# fn main() { }
```

This macro creates the struct as specified and implements
`FromInputValue` to automatically parse values provided from variables
and arguments.

If you want to expose the struct under a different name than the Rust
type, you can write `struct Coordinates as "MyCoordinates" { ...`.

*/
#[macro_export]
macro_rules! graphql_input_object {
    // Calls $val.$func($arg) if $arg is not None
    ( @maybe_apply, None, $func:ident, $val:expr ) => { $val };
    ( @maybe_apply, $arg:tt, $func:ident, $val:expr ) => { $val.$func($arg) };

    // Calls $val.description($descr) when $descr is not empty
    ( @apply_description, , $val:expr ) => { $val };
    ( @apply_description, $descr:tt , $val:expr ) => { $val.description($descr) };

    // Generate the FromInputValue::from method body, provided a
    // HashMap<&str, &InputValue> in $var
    (
        @generate_from_input_value,
        $name:tt, $var:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        Some($name {
            $( $field_name: {
                let n: String = $crate::to_camel_case(stringify!($field_name));
                let v: Option<&&$crate::InputValue> = $var.get(&n[..]);

                println!("Found variable for {:?}: {:?} in {:?}", n, v, $var);

                match v {
                    $( Some(&&InputValue::Null) | None if true => $default, )*
                        Some(v) => $crate::FromInputValue::from(v).unwrap(),
                        _ => $crate::FromInputValue::from(&$crate::InputValue::null()).unwrap()
                }
            } ),*
        })
    };

    // Generate the struct declaration, including (Rust) meta attributes
    (
        @generate_struct_fields,
        ( $($meta:tt)* ), ( $($pubmod:tt)* ), $name:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        $($meta)* $($pubmod)* struct $name {
            $( $field_name: $field_type, )*
        }
    };

    // Generate single field meta for field with default value
    (
        @generate_single_meta_field,
        $reg:tt,
        ( $field_name:ident = $default:tt : $field_type:ty $(as $descr:tt)* )
    ) => {
        graphql_input_object!(
            @apply_description,
            $($descr)*,
            $reg.arg_with_default::<$field_type>(
                &$crate::to_camel_case(stringify!($field_name)),
                &$default))
    };

    // Generate single field meta for field without default value
    (
        @generate_single_meta_field,
        $reg:tt,
        ( $field_name:ident : $field_type:ty $(as $descr:tt)* )
    ) => {
        graphql_input_object!(
            @apply_description,
            $($descr)*,
            $reg.arg::<$field_type>(
                &$crate::to_camel_case(stringify!($field_name))))
    };

    // Generate the input field meta list, i.e. &[Argument] for
    (
        @generate_meta_fields,
        $reg:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        &[
            $(
                graphql_input_object!(
                    @generate_single_meta_field,
                    $reg,
                    ( $field_name $(= $default)* : $field_type $(as $descr)* )
                )
            ),*
        ]
    };

    // #[...] struct $name { ... }
    // struct $name { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* struct $name:ident { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $(#[$meta])* ), ( ), $name, (stringify!($name)), ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] pub struct $name { ... }
    // pub struct $name { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* pub struct $name:ident { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $(#[$meta])* ), ( pub ), $name, (stringify!($name)), ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] struct $name as "GraphQLName" { ... }
    // struct $name as "GraphQLName" { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $($meta)* ), ( ), $name, $outname, ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] pub struct $name as "GraphQLName" { ... }
    // pub struct $name as "GraphQLName" { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* pub struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $($meta)* ), ( pub ), $name, $outname, ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // description: <description>
    (
        @parse,
        ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $_ignore:tt ),
        description: $descr:tt $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( $meta, $pubmod, $name, $outname, $fields, $descr ),
            $($rest)*
        );
    };

    // No more data to parse, generate the struct and impls
    (
        @parse,
        ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $descr:tt ),
    ) => {
        graphql_input_object!(@generate_struct_fields, $meta, $pubmod, $name, $fields);

        impl $crate::FromInputValue for $name {
            fn from(value: &$crate::InputValue) -> Option<$name> {
                if let Some(obj) = value.to_object_value() {
                    graphql_input_object!(@generate_from_input_value, $name, obj, $fields)
                }
                else {
                   None
                }
            }
        }

        impl $crate::GraphQLType for $name {
            type Context = ();

            fn name() -> Option<&'static str> {
                Some($outname)
            }

            fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> {
                let fields = graphql_input_object!(@generate_meta_fields, registry, $fields);
                graphql_input_object!(
                    @maybe_apply, $descr, description,
                    registry.build_input_object_type::<$name>(fields)).into_meta()
            }
        }
    };

    // Entry point: parse calls starting with a struct declaration
    ( $(#[$meta:meta])* struct $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            $(#[$meta])* struct $($items)*
        );
    };

    // Entry point: parse calls starting with a public struct declaration
    ( $(#[$meta:meta])* pub struct $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            $(#[$meta])* pub struct $($items)*
        );
    };

    // Entry point: parse calls starting with the description
    ( description: $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            description: $($items)*
        );
    };
}
<commit_msg>Document input object default values<commit_after>/**
Create an input object

Input objects are used as data carriers for complex input values to
fields and mutations. Unlike the other helper macros,
`graphql_input_object!` actually *creates* the struct you define. It
does not add anything to the struct definition itself - what you type
is what will be generated:

```rust
# #[macro_use] extern crate juniper;
#
graphql_input_object!(
    description: "Coordinates for the user"

    struct Coordinates {
        longitude: f64 as "The X coordinate, from -180 to +180",
        latitude: f64 as "The Y coordinate, from -90 to +90",
    }
);

# fn main() { }
```

This macro creates the struct as specified and implements
`FromInputValue` to automatically parse values provided from variables
and arguments.

If you want to expose the struct under a different name than the Rust
type, you can write `struct Coordinates as "MyCoordinates" { ...`.

You can specify *default values* for input object fields; the syntax
is similar to argument default values:

```rust
# #[macro_use] extern crate juniper;
#
graphql_input_object!(
    struct SampleObject {
        foo = 123: i64 as "A sample field, defaults to 123 if omitted"
    }
);

# fn main() { }
```

*/
#[macro_export]
macro_rules! graphql_input_object {
    // Calls $val.$func($arg) if $arg is not None
    ( @maybe_apply, None, $func:ident, $val:expr ) => { $val };
    ( @maybe_apply, $arg:tt, $func:ident, $val:expr ) => { $val.$func($arg) };

    // Calls $val.description($descr) when $descr is not empty
    ( @apply_description, , $val:expr ) => { $val };
    ( @apply_description, $descr:tt , $val:expr ) => { $val.description($descr) };

    // Generate the FromInputValue::from method body, provided a
    // HashMap<&str, &InputValue> in $var
    (
        @generate_from_input_value,
        $name:tt, $var:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        Some($name {
            $( $field_name: {
                let n: String = $crate::to_camel_case(stringify!($field_name));
                let v: Option<&&$crate::InputValue> = $var.get(&n[..]);

                println!("Found variable for {:?}: {:?} in {:?}", n, v, $var);

                match v {
                    $( Some(&&InputValue::Null) | None if true => $default, )*
                        Some(v) => $crate::FromInputValue::from(v).unwrap(),
                        _ => $crate::FromInputValue::from(&$crate::InputValue::null()).unwrap()
                }
            } ),*
        })
    };

    // Generate the struct declaration, including (Rust) meta attributes
    (
        @generate_struct_fields,
        ( $($meta:tt)* ), ( $($pubmod:tt)* ), $name:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        $($meta)* $($pubmod)* struct $name {
            $( $field_name: $field_type, )*
        }
    };

    // Generate single field meta for field with default value
    (
        @generate_single_meta_field,
        $reg:tt,
        ( $field_name:ident = $default:tt : $field_type:ty $(as $descr:tt)* )
    ) => {
        graphql_input_object!(
            @apply_description,
            $($descr)*,
            $reg.arg_with_default::<$field_type>(
                &$crate::to_camel_case(stringify!($field_name)),
                &$default))
    };

    // Generate single field meta for field without default value
    (
        @generate_single_meta_field,
        $reg:tt,
        ( $field_name:ident : $field_type:ty $(as $descr:tt)* )
    ) => {
        graphql_input_object!(
            @apply_description,
            $($descr)*,
            $reg.arg::<$field_type>(
                &$crate::to_camel_case(stringify!($field_name))))
    };

    // Generate the input field meta list, i.e. &[Argument] for
    (
        @generate_meta_fields,
        $reg:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        &[
            $(
                graphql_input_object!(
                    @generate_single_meta_field,
                    $reg,
                    ( $field_name $(= $default)* : $field_type $(as $descr)* )
                )
            ),*
        ]
    };

    // #[...] struct $name { ... }
    // struct $name { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* struct $name:ident { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $(#[$meta])* ), ( ), $name, (stringify!($name)), ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] pub struct $name { ... }
    // pub struct $name { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* pub struct $name:ident { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $(#[$meta])* ), ( pub ), $name, (stringify!($name)), ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] struct $name as "GraphQLName" { ... }
    // struct $name as "GraphQLName" { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $($meta)* ), ( ), $name, $outname, ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] pub struct $name as "GraphQLName" { ... }
    // pub struct $name as "GraphQLName" { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* pub struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $($meta)* ), ( pub ), $name, $outname, ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // description: <description>
    (
        @parse,
        ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $_ignore:tt ),
        description: $descr:tt $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( $meta, $pubmod, $name, $outname, $fields, $descr ),
            $($rest)*
        );
    };

    // No more data to parse, generate the struct and impls
    (
        @parse,
        ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $descr:tt ),
    ) => {
        graphql_input_object!(@generate_struct_fields, $meta, $pubmod, $name, $fields);

        impl $crate::FromInputValue for $name {
            fn from(value: &$crate::InputValue) -> Option<$name> {
                if let Some(obj) = value.to_object_value() {
                    graphql_input_object!(@generate_from_input_value, $name, obj, $fields)
                }
                else {
                   None
                }
            }
        }

        impl $crate::GraphQLType for $name {
            type Context = ();

            fn name() -> Option<&'static str> {
                Some($outname)
            }

            fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> {
                let fields = graphql_input_object!(@generate_meta_fields, registry, $fields);
                graphql_input_object!(
                    @maybe_apply, $descr, description,
                    registry.build_input_object_type::<$name>(fields)).into_meta()
            }
        }
    };

    // Entry point: parse calls starting with a struct declaration
    ( $(#[$meta:meta])* struct $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            $(#[$meta])* struct $($items)*
        );
    };

    // Entry point: parse calls starting with a public struct declaration
    ( $(#[$meta:meta])* pub struct $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            $(#[$meta])* pub struct $($items)*
        );
    };

    // Entry point: parse calls starting with the description
    ( description: $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            description: $($items)*
        );
    };
}
<|endoftext|>


<commit_before>use builder::Builder;
use pool::Pool;
use sender::Sender;
use shutdown::Shutdown;

use futures::Future;

/// Work-stealing based thread pool for executing futures.
///
/// If a `ThreadPool` instance is dropped without explicitly being shutdown,
/// `shutdown_now` is called implicitly, forcing all tasks that have not yet
/// completed to be dropped.
///
/// Create `ThreadPool` instances using `Builder`.
#[derive(Debug)]
pub struct ThreadPool {
    pub(crate) inner: Option<Sender>,
}

impl ThreadPool {
    /// Create a new `ThreadPool` with default values.
    ///
    /// Use [`Builder`] for creating a configured thread pool.
    ///
    /// [`Builder`]: struct.Builder.html
    pub fn new() -> ThreadPool {
        Builder::new().build()
    }

    /// Spawn a future onto the thread pool.
    ///
    /// This function takes ownership of the future and randomly assigns it to a
    /// worker thread. The thread will then start executing the future.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate tokio_threadpool;
    /// # extern crate futures;
    /// # use tokio_threadpool::ThreadPool;
    /// use futures::future::{Future, lazy};
    ///
    /// # pub fn main() {
    /// // Create a thread pool with default configuration values
    /// let thread_pool = ThreadPool::new();
    ///
    /// thread_pool.spawn(lazy(|| {
    ///     println!("called from a worker thread");
    ///     Ok(())
    /// }));
    ///
    /// // Gracefully shutdown the threadpool
    /// thread_pool.shutdown().wait().unwrap();
    /// # }
    /// ```
    ///
    /// # Panics
    ///
    /// This function panics if the spawn fails. Use [`Sender::spawn`] for a
    /// version that returns a `Result` instead of panicking.
    pub fn spawn<F>(&self, future: F)
    where F: Future<Item = (), Error = ()> + Send + 'static,
    {
        self.sender().spawn(future).unwrap();
    }

    /// Return a reference to the sender handle
    ///
    /// The handle is used to spawn futures onto the thread pool. It also
    /// implements the `Executor` trait.
    pub fn sender(&self) -> &Sender {
        self.inner.as_ref().unwrap()
    }

    /// Return a mutable reference to the sender handle
    pub fn sender_mut(&mut self) -> &mut Sender {
        self.inner.as_mut().unwrap()
    }

    /// Shutdown the pool once it becomes idle.
    ///
    /// Idle is defined as the completion of all futures that have been spawned
    /// onto the thread pool. There may still be outstanding handles when the
    /// thread pool reaches an idle state.
    ///
    /// Once the idle state is reached, calling `spawn` on any outstanding
    /// handle will result in an error. All worker threads are signaled and will
    /// shutdown. The returned future completes once all worker threads have
    /// completed the shutdown process.
    pub fn shutdown_on_idle(mut self) -> Shutdown {
        self.inner().shutdown(false, false);
        Shutdown { inner: self.inner.take().unwrap() }
    }

    /// Shutdown the pool
    ///
    /// This prevents the thread pool from accepting new tasks but will allow
    /// any existing tasks to complete.
    ///
    /// Calling `spawn` on any outstanding handle will result in an error. All
    /// worker threads are signaled and will shutdown. The returned future
    /// completes once all worker threads have completed the shutdown process.
    pub fn shutdown(mut self) -> Shutdown {
        self.inner().shutdown(true, false);
        Shutdown { inner: self.inner.take().unwrap() }
    }

    /// Shutdown the pool immediately
    ///
    /// This will prevent the thread pool from accepting new tasks **and**
    /// abort any tasks that are currently running on the thread pool.
    ///
    /// Calling `spawn` on any outstanding handle will result in an error. All
    /// worker threads are signaled and will shutdown. The returned future
    /// completes once all worker threads have completed the shutdown process.
    pub fn shutdown_now(mut self) -> Shutdown {
        self.inner().shutdown(true, true);
        Shutdown { inner: self.inner.take().unwrap() }
    }

    fn inner(&self) -> &Pool {
        &*self.inner.as_ref().unwrap().inner
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        if let Some(sender) = self.inner.take() {
            sender.inner.shutdown(true, true);
            let shutdown = Shutdown { inner: sender };
            let _ = shutdown.wait();
        }
    }
}
<commit_msg>Add ThreadPool::spawn_handle (#602)<commit_after>use builder::Builder;
use pool::Pool;
use sender::Sender;
use shutdown::Shutdown;

use futures::{Future, Poll};
use futures::sync::oneshot;

/// Work-stealing based thread pool for executing futures.
///
/// If a `ThreadPool` instance is dropped without explicitly being shutdown,
/// `shutdown_now` is called implicitly, forcing all tasks that have not yet
/// completed to be dropped.
///
/// Create `ThreadPool` instances using `Builder`.
#[derive(Debug)]
pub struct ThreadPool {
    pub(crate) inner: Option<Sender>,
}

impl ThreadPool {
    /// Create a new `ThreadPool` with default values.
    ///
    /// Use [`Builder`] for creating a configured thread pool.
    ///
    /// [`Builder`]: struct.Builder.html
    pub fn new() -> ThreadPool {
        Builder::new().build()
    }

    /// Spawn a future onto the thread pool.
    ///
    /// This function takes ownership of the future and randomly assigns it to a
    /// worker thread. The thread will then start executing the future.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate tokio_threadpool;
    /// # extern crate futures;
    /// # use tokio_threadpool::ThreadPool;
    /// use futures::future::{Future, lazy};
    ///
    /// # pub fn main() {
    /// // Create a thread pool with default configuration values
    /// let thread_pool = ThreadPool::new();
    ///
    /// thread_pool.spawn(lazy(|| {
    ///     println!("called from a worker thread");
    ///     Ok(())
    /// }));
    ///
    /// // Gracefully shutdown the threadpool
    /// thread_pool.shutdown().wait().unwrap();
    /// # }
    /// ```
    ///
    /// # Panics
    ///
    /// This function panics if the spawn fails. Use [`Sender::spawn`] for a
    /// version that returns a `Result` instead of panicking.
    pub fn spawn<F>(&self, future: F)
    where F: Future<Item = (), Error = ()> + Send + 'static,
    {
        self.sender().spawn(future).unwrap();
    }

    /// Spawn a future on to the thread pool, return a future representing
    /// the produced value.
    ///
    /// The SpawnHandle returned is a future that is a proxy for future itself.
    /// When future completes on this thread pool then the SpawnHandle will itself
    /// be resolved.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate tokio_threadpool;
    /// # extern crate futures;
    /// # use tokio_threadpool::ThreadPool;
    /// use futures::future::{Future, lazy};
    ///
    /// # pub fn main() {
    /// // Create a thread pool with default configuration values
    /// let thread_pool = ThreadPool::new();
    ///
    /// let handle = thread_pool.spawn_handle(lazy(|| Ok::<_, ()>(42)));
    ///
    /// let value = handle.wait().unwrap();
    /// assert_eq!(value, 42);
    ///
    /// // Gracefully shutdown the threadpool
    /// thread_pool.shutdown().wait().unwrap();
    /// # }
    /// ```
    ///
    /// # Panics
    ///
    /// This function panics if the spawn fails.
    pub fn spawn_handle<F>(&self, future: F) -> SpawnHandle<F::Item, F::Error>
    where
        F: Future + Send + 'static,
        F::Item: Send + 'static,
        F::Error: Send + 'static,
    {
        SpawnHandle(oneshot::spawn(future, self.sender()))
    }

    /// Return a reference to the sender handle
    ///
    /// The handle is used to spawn futures onto the thread pool. It also
    /// implements the `Executor` trait.
    pub fn sender(&self) -> &Sender {
        self.inner.as_ref().unwrap()
    }

    /// Return a mutable reference to the sender handle
    pub fn sender_mut(&mut self) -> &mut Sender {
        self.inner.as_mut().unwrap()
    }

    /// Shutdown the pool once it becomes idle.
    ///
    /// Idle is defined as the completion of all futures that have been spawned
    /// onto the thread pool. There may still be outstanding handles when the
    /// thread pool reaches an idle state.
    ///
    /// Once the idle state is reached, calling `spawn` on any outstanding
    /// handle will result in an error. All worker threads are signaled and will
    /// shutdown. The returned future completes once all worker threads have
    /// completed the shutdown process.
    pub fn shutdown_on_idle(mut self) -> Shutdown {
        self.inner().shutdown(false, false);
        Shutdown { inner: self.inner.take().unwrap() }
    }

    /// Shutdown the pool
    ///
    /// This prevents the thread pool from accepting new tasks but will allow
    /// any existing tasks to complete.
    ///
    /// Calling `spawn` on any outstanding handle will result in an error. All
    /// worker threads are signaled and will shutdown. The returned future
    /// completes once all worker threads have completed the shutdown process.
    pub fn shutdown(mut self) -> Shutdown {
        self.inner().shutdown(true, false);
        Shutdown { inner: self.inner.take().unwrap() }
    }

    /// Shutdown the pool immediately
    ///
    /// This will prevent the thread pool from accepting new tasks **and**
    /// abort any tasks that are currently running on the thread pool.
    ///
    /// Calling `spawn` on any outstanding handle will result in an error. All
    /// worker threads are signaled and will shutdown. The returned future
    /// completes once all worker threads have completed the shutdown process.
    pub fn shutdown_now(mut self) -> Shutdown {
        self.inner().shutdown(true, true);
        Shutdown { inner: self.inner.take().unwrap() }
    }

    fn inner(&self) -> &Pool {
        &*self.inner.as_ref().unwrap().inner
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        if let Some(sender) = self.inner.take() {
            sender.inner.shutdown(true, true);
            let shutdown = Shutdown { inner: sender };
            let _ = shutdown.wait();
        }
    }
}

/// Handle returned from ThreadPool::spawn_handle.
///
/// This handle is a future representing the completion of a different future
/// spawned on to the thread pool. Created through the ThreadPool::spawn_handle
/// function this handle will resolve when the future provided resolves on the
/// thread pool.
#[derive(Debug)]
pub struct SpawnHandle<T, E>(oneshot::SpawnHandle<T, E>);

impl<T, E> Future for SpawnHandle<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<T, E> {
        self.0.poll()
    }
}<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::u16;
use std::fmt;
use std::default::Default;

use super::{Frame, FrameBuilder};

bitflags! {
    flags OpCode: u8 {
        const CONTINUATION  = 0b0000_0000,
        const TEXT          = 0b0000_0001,
        const BINARY        = 0b0000_0010,
        const CLOSE         = 0b0000_1000,
        const PING          = 0b0000_1001,
        const PONG          = 0b0000_1010
    }
}

#[derive(Clone, PartialEq, Eq)]
pub enum FrameType {
    Control,
    Data
}

#[derive(Clone, PartialEq, Eq)]
pub enum OpType {
    Continuation,
    Text,
    Binary,
    Close,
    Ping,
    Pong
}

#[derive(Clone)]
struct Header {
    op_code: OpCode,
    mask: bool,
    payload_len: u64,
    masking_key: [u8; 4]
}

#[derive(Clone)]
struct Payload {
    data: Vec<u8>
}

#[derive(Clone)]
pub struct WebSocketFrame {
    frame_type: FrameType,
    header: Header,
    payload: Payload
}

#[derive(Clone)]
pub struct WebSocketFrameBuilder;
impl FrameBuilder for WebSocketFrameBuilder {
    fn from_bytes(buf: &mut Vec<u8>) -> Option<Box<Frame>> {
        if buf.len() < 5 {
            trace!("Buffer length is less than 5, not worth trying...");
            return None;
        }

        trace!("from_bytes buf.len(): {}", buf.len());
        trace!("buf[0]: {:#b}    // FIN and OpType", buf[0]);
        trace!("buf[1]: {:#b}    // Mask and Payload Len", buf[1]);

        let mut frame: WebSocketFrame = Default::default();

        // OpCode and FrameType
        let fin_cleared = buf[0] & 0b0000_1111;
        match OpCode::from_bits(fin_cleared) {
            Some(op_code) => {
                if op_code.contains(CONTINUATION) {
                    frame.frame_type = FrameType::Data;
                    frame.header.op_code = CONTINUATION;
                } else if op_code.contains(TEXT) {
                    frame.frame_type = FrameType::Data;
                    frame.header.op_code = TEXT;
                } else if op_code.contains(BINARY) {
                    frame.frame_type = FrameType::Data;
                    frame.header.op_code = BINARY;
                } else if op_code.contains(CLOSE) {
                    frame.frame_type = FrameType::Control;
                    frame.header.op_code = CLOSE;
                } else if op_code.contains(PING) {
                    frame.frame_type = FrameType::Control;
                    frame.header.op_code = PING;
                } else if op_code.contains(PONG) {
                    frame.frame_type = FrameType::Control;
                    frame.header.op_code = PONG;
                } else {
                    error!("Could not match within bitflags: {:#b}", buf[0]);
                    return None;
                }
            }
            None => {
                error!("Invalid OpCode bits: {:#b}", buf[0]);
                return None;
            }
        }

        trace!("Frame info:   Type: {} | OpType: {}", frame.frame_type, frame.op_type());

        // Payload masked (If from client, must always be true)
        let mask_bit = 0b1000_0000 & buf[1];
        frame.header.mask = mask_bit > 0;

        trace!("Frame masked: {}", frame.header.mask);

        // Payload data length
        let mut next_offset: usize = 3;
        let payload_len = 0b0111_1111 & buf[2];
        if payload_len <= 125 {
            frame.header.payload_len = payload_len as u64;
        } else if payload_len == 126 {
            let mut len = (buf[3] as u16) << 8;
            len |= buf[4] as u16;
            frame.header.payload_len = len as u64;
            next_offset = 5;
        } else {
            // We don't want to cause a panic
            if buf.len() < 10 {
                trace!("Not enough payload to continue reading payload length");
                return None;
            }

            let mut len = (buf[3] as u64) << 56;
            len |= (buf[3] as u64) << 48;
            len |= (buf[4] as u64) << 40;
            len |= (buf[5] as u64) << 32;
            len |= (buf[6] as u64) << 24;
            len |= (buf[7] as u64) << 16;
            len |= (buf[8] as u64) << 8;
            len |= buf[9] as u64;
            frame.header.payload_len = len;
            next_offset = 10;
        }

        trace!("Payload length: {}", frame.header.payload_len);

        // Optional masking key
        if frame.header.mask {
            if buf.len() <= next_offset + 4 {
                trace!("Payload masked, not enough in buffer to read masking key");
                return None;
            }
            frame.header.masking_key[0] = buf[next_offset];
            frame.header.masking_key[1] = buf[next_offset + 1];
            frame.header.masking_key[2] = buf[next_offset + 2];
            frame.header.masking_key[3] = buf[next_offset + 3];
            next_offset += 4;
        }

        if buf.len() < next_offset + frame.header.payload_len as usize {
            trace!("Not enough in buffer to read payload");
            return None;
        }

        // Payload data
        let len = frame.header.payload_len as usize;
        frame.payload.data.extend_from_slice(&buf[next_offset..len]);

        trace!("Read complete");

        return Some(Box::new(frame));
    }
}

impl WebSocketFrame {
    pub fn new(buf: &[u8], frame_type: FrameType, op_type: OpType) -> WebSocketFrame {
        WebSocketFrame {
            frame_type: frame_type,
            header: Header {
                op_code: match op_type {
                    OpType::Continuation => CONTINUATION,
                    OpType::Text => TEXT,
                    OpType::Binary => BINARY,
                    OpType::Close => CLOSE,
                    OpType::Ping => PING,
                    OpType::Pong => PONG,
                },
                mask: false,
                payload_len: buf.len() as u64,
                masking_key: [0u8; 4]
            },
            payload: Payload {
                data: buf.to_vec()
            }
        }
    }

    pub fn op_type(&self) -> OpType {
        match self.header.op_code {
            CONTINUATION => OpType::Continuation,
            TEXT => OpType::Text,
            BINARY => OpType::Binary,
            CLOSE => OpType::Close,
            PING => OpType::Ping,
            PONG => OpType::Pong,
            _ => unreachable!()
        }
    }

    pub fn frame_type(&self) -> FrameType {
        self.frame_type.clone()
    }

    pub fn is_masked(&self) -> bool {
        self.header.mask
    }

    pub fn payload_unmasked(&self) -> Vec<u8> {
        let len = self.payload.data.len();
        let mut buf = Vec::<u8>::with_capacity(len);
        for x in 0..len {
            buf.push(self.payload.data[x] ^ self.header.masking_key[x % 4]);
        }

        buf
    }
}

impl Frame for WebSocketFrame {
    fn payload(&self) -> Vec<u8> {
        if self.header.mask {
            self.payload_unmasked()
        } else {
            self.payload.data.clone()
        }
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut buf = Vec::<u8>::with_capacity(self.len_as_vec());

        // OpCode
        buf.push(self.header.op_code.bits());

        // Mask and Payload len
        let mask_bit: u8 = if self.header.mask {
            0b1000_000
        } else {
            0b0000_000
        };
        let next_7_bits: u8 = if self.header.payload_len <= 125 {
            self.header.payload_len as u8
        } else if self.header.payload_len <= u16::MAX as u64 {
            126u8
        } else {
            127u8
        };
        let next_byte: u8 = mask_bit & next_7_bits;
        buf.push(next_byte);

        // Optional payload len
        if next_byte == 126 {
            buf.push(((self.header.payload_len as u16) >> 8) as u8);
            buf.push(self.header.payload_len as u8);
        } else if next_byte == 127 {
            buf.push((self.header.payload_len >> 56) as u8);
            buf.push((self.header.payload_len >> 48) as u8);
            buf.push((self.header.payload_len >> 40) as u8);
            buf.push((self.header.payload_len >> 32) as u8);
            buf.push((self.header.payload_len >> 24) as u8);
            buf.push((self.header.payload_len >> 16) as u8);
            buf.push((self.header.payload_len >> 8) as u8);
            buf.push(self.header.payload_len as u8);
        }

        // Optional masking key
        if self.header.mask {
            buf.push(self.header.masking_key[0]);
            buf.push(self.header.masking_key[1]);
            buf.push(self.header.masking_key[2]);
            buf.push(self.header.masking_key[3]);
        }

        // Payload data
        buf.extend_from_slice(&self.payload.data[..]);

        buf
    }

    fn len_as_vec(&self) -> usize {
        let mut len = 0usize;

        // OpCode
        len += 1;

        // Mask and paylaod length
        len += 1;

        // Extended Payload length
        if self.header.payload_len > 125 && self.header.payload_len < u16::MAX as u64 {
            len += 2;
        } else if self.header.payload_len > u16::MAX as u64 {
            len += 8;
        }

        // Optional masking key
        if self.header.mask {
            len += 4;
        }

        // Payload data
        len += self.header.payload_len as usize;

        len
    }

    fn as_mut_raw_erased(&self) -> *mut () {
        let dup = Box::new(self.clone());
        return Box::into_raw(dup) as *mut _ as *mut ();
    }
}

impl Default for WebSocketFrame {
    fn default() -> WebSocketFrame {
        WebSocketFrame {
            frame_type: FrameType::Control,
            header: Header {
                op_code: CONTINUATION,
                mask: false,
                payload_len: 0u64,
                masking_key: [0u8; 4]
            },
            payload: Payload {
                data: Vec::<u8>::new()
            }
        }
    }
}

impl fmt::Debug for FrameType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FrameType::Control => write!(f, "FrameType::Control"),
            FrameType::Data => write!(f, "FrameType::Data")
        }
    }
}

impl fmt::Display for FrameType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FrameType::Control => write!(f, "FrameType::Control"),
            FrameType::Data => write!(f, "FrameType::Data")
        }
    }
}

impl fmt::Debug for OpType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            OpType::Continuation => write!(f, "OpType::Continuation"),
            OpType::Text => write!(f, "OpType::Text"),
            OpType::Binary => write!(f, "OpType::Binary"),
            OpType::Close => write!(f, "OpType::Close"),
            OpType::Ping => write!(f, "OpType::Ping"),
            OpType::Pong => write!(f, "OpType::Pong"),
        }
    }
}

impl fmt::Display for OpType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            OpType::Continuation => write!(f, "OpType::Continuation"),
            OpType::Text => write!(f, "OpType::Text"),
            OpType::Binary => write!(f, "OpType::Binary"),
            OpType::Close => write!(f, "OpType::Close"),
            OpType::Ping => write!(f, "OpType::Ping"),
            OpType::Pong => write!(f, "OpType::Pong"),
        }
    }
}
<commit_msg>More websocket logging<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::u16;
use std::fmt;
use std::default::Default;

use super::{Frame, FrameBuilder};

bitflags! {
    flags OpCode: u8 {
        const CONTINUATION  = 0b0000_0000,
        const TEXT          = 0b0000_0001,
        const BINARY        = 0b0000_0010,
        const CLOSE         = 0b0000_1000,
        const PING          = 0b0000_1001,
        const PONG          = 0b0000_1010
    }
}

#[derive(Clone, PartialEq, Eq)]
pub enum FrameType {
    Control,
    Data
}

#[derive(Clone, PartialEq, Eq)]
pub enum OpType {
    Continuation,
    Text,
    Binary,
    Close,
    Ping,
    Pong
}

#[derive(Clone)]
struct Header {
    op_code: OpCode,
    mask: bool,
    payload_len: u64,
    masking_key: [u8; 4]
}

#[derive(Clone)]
struct Payload {
    data: Vec<u8>
}

#[derive(Clone)]
pub struct WebSocketFrame {
    frame_type: FrameType,
    header: Header,
    payload: Payload
}

#[derive(Clone)]
pub struct WebSocketFrameBuilder;
impl FrameBuilder for WebSocketFrameBuilder {
    fn from_bytes(buf: &mut Vec<u8>) -> Option<Box<Frame>> {
        if buf.len() < 5 {
            trace!("Buffer length is less than 5, not worth trying...");
            return None;
        }

        trace!("from_bytes buf.len(): {}", buf.len());
        trace!("buf[0]: {:#b}    // FIN and OpType", buf[0]);
        trace!("buf[1]: {:#b}    // Mask and Payload Len", buf[1]);

        let mut frame: WebSocketFrame = Default::default();

        // OpCode and FrameType
        let fin_cleared = buf[0] & 0b0000_1111;
        match OpCode::from_bits(fin_cleared) {
            Some(op_code) => {
                if op_code.contains(CONTINUATION) {
                    trace!("op_code.contains(CONTINUATION)");
                    frame.frame_type = FrameType::Data;
                    frame.header.op_code = CONTINUATION;
                } else if op_code.contains(TEXT) {
                    trace!("op_code.contains(TEXT)");
                    frame.frame_type = FrameType::Data;
                    frame.header.op_code = TEXT;
                } else if op_code.contains(BINARY) {
                    trace!("op_code.contains(BINARY)");
                    frame.frame_type = FrameType::Data;
                    frame.header.op_code = BINARY;
                } else if op_code.contains(CLOSE) {
                    trace!("op_code.contains(CLOSE)");
                    frame.frame_type = FrameType::Control;
                    frame.header.op_code = CLOSE;
                } else if op_code.contains(PING) {
                    trace!("op_code.contains(PING)");
                    frame.frame_type = FrameType::Control;
                    frame.header.op_code = PING;
                } else if op_code.contains(PONG) {
                    trace!("op_code.contains(PONG)");
                    frame.frame_type = FrameType::Control;
                    frame.header.op_code = PONG;
                } else {
                    error!("Could not match within bitflags: {:#b}", buf[0]);
                    return None;
                }
            }
            None => {
                error!("Invalid OpCode bits: {:#b}", buf[0]);
                return None;
            }
        }

        trace!("Frame info:   Type: {} | OpType: {}", frame.frame_type, frame.op_type());

        // Payload masked (If from client, must always be true)
        let mask_bit = 0b1000_0000 & buf[1];
        frame.header.mask = mask_bit > 0;

        trace!("Frame masked: {}", frame.header.mask);

        // Payload data length
        let mut next_offset: usize = 3;
        let payload_len = 0b0111_1111 & buf[2];
        if payload_len <= 125 {
            frame.header.payload_len = payload_len as u64;
        } else if payload_len == 126 {
            let mut len = (buf[3] as u16) << 8;
            len |= buf[4] as u16;
            frame.header.payload_len = len as u64;
            next_offset = 5;
        } else {
            // We don't want to cause a panic
            if buf.len() < 10 {
                trace!("Not enough payload to continue reading payload length");
                return None;
            }

            let mut len = (buf[3] as u64) << 56;
            len |= (buf[3] as u64) << 48;
            len |= (buf[4] as u64) << 40;
            len |= (buf[5] as u64) << 32;
            len |= (buf[6] as u64) << 24;
            len |= (buf[7] as u64) << 16;
            len |= (buf[8] as u64) << 8;
            len |= buf[9] as u64;
            frame.header.payload_len = len;
            next_offset = 10;
        }

        trace!("Payload length: {}", frame.header.payload_len);

        // Optional masking key
        if frame.header.mask {
            if buf.len() <= next_offset + 4 {
                trace!("Payload masked, not enough in buffer to read masking key");
                return None;
            }
            frame.header.masking_key[0] = buf[next_offset];
            frame.header.masking_key[1] = buf[next_offset + 1];
            frame.header.masking_key[2] = buf[next_offset + 2];
            frame.header.masking_key[3] = buf[next_offset + 3];
            next_offset += 4;
        }

        if buf.len() < next_offset + frame.header.payload_len as usize {
            trace!("Not enough in buffer to read payload");
            return None;
        }

        // Payload data
        let len = frame.header.payload_len as usize;
        frame.payload.data.extend_from_slice(&buf[next_offset..len]);

        trace!("Read complete");

        return Some(Box::new(frame));
    }
}

impl WebSocketFrame {
    pub fn new(buf: &[u8], frame_type: FrameType, op_type: OpType) -> WebSocketFrame {
        WebSocketFrame {
            frame_type: frame_type,
            header: Header {
                op_code: match op_type {
                    OpType::Continuation => CONTINUATION,
                    OpType::Text => TEXT,
                    OpType::Binary => BINARY,
                    OpType::Close => CLOSE,
                    OpType::Ping => PING,
                    OpType::Pong => PONG,
                },
                mask: false,
                payload_len: buf.len() as u64,
                masking_key: [0u8; 4]
            },
            payload: Payload {
                data: buf.to_vec()
            }
        }
    }

    pub fn op_type(&self) -> OpType {
        match self.header.op_code {
            CONTINUATION => OpType::Continuation,
            TEXT => OpType::Text,
            BINARY => OpType::Binary,
            CLOSE => OpType::Close,
            PING => OpType::Ping,
            PONG => OpType::Pong,
            _ => unreachable!()
        }
    }

    pub fn frame_type(&self) -> FrameType {
        self.frame_type.clone()
    }

    pub fn is_masked(&self) -> bool {
        self.header.mask
    }

    pub fn payload_unmasked(&self) -> Vec<u8> {
        let len = self.payload.data.len();
        let mut buf = Vec::<u8>::with_capacity(len);
        for x in 0..len {
            buf.push(self.payload.data[x] ^ self.header.masking_key[x % 4]);
        }

        buf
    }
}

impl Frame for WebSocketFrame {
    fn payload(&self) -> Vec<u8> {
        if self.header.mask {
            self.payload_unmasked()
        } else {
            self.payload.data.clone()
        }
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut buf = Vec::<u8>::with_capacity(self.len_as_vec());

        // OpCode
        buf.push(self.header.op_code.bits());

        // Mask and Payload len
        let mask_bit: u8 = if self.header.mask {
            0b1000_000
        } else {
            0b0000_000
        };
        let next_7_bits: u8 = if self.header.payload_len <= 125 {
            self.header.payload_len as u8
        } else if self.header.payload_len <= u16::MAX as u64 {
            126u8
        } else {
            127u8
        };
        let next_byte: u8 = mask_bit & next_7_bits;
        buf.push(next_byte);

        // Optional payload len
        if next_byte == 126 {
            buf.push(((self.header.payload_len as u16) >> 8) as u8);
            buf.push(self.header.payload_len as u8);
        } else if next_byte == 127 {
            buf.push((self.header.payload_len >> 56) as u8);
            buf.push((self.header.payload_len >> 48) as u8);
            buf.push((self.header.payload_len >> 40) as u8);
            buf.push((self.header.payload_len >> 32) as u8);
            buf.push((self.header.payload_len >> 24) as u8);
            buf.push((self.header.payload_len >> 16) as u8);
            buf.push((self.header.payload_len >> 8) as u8);
            buf.push(self.header.payload_len as u8);
        }

        // Optional masking key
        if self.header.mask {
            buf.push(self.header.masking_key[0]);
            buf.push(self.header.masking_key[1]);
            buf.push(self.header.masking_key[2]);
            buf.push(self.header.masking_key[3]);
        }

        // Payload data
        buf.extend_from_slice(&self.payload.data[..]);

        buf
    }

    fn len_as_vec(&self) -> usize {
        let mut len = 0usize;

        // OpCode
        len += 1;

        // Mask and paylaod length
        len += 1;

        // Extended Payload length
        if self.header.payload_len > 125 && self.header.payload_len < u16::MAX as u64 {
            len += 2;
        } else if self.header.payload_len > u16::MAX as u64 {
            len += 8;
        }

        // Optional masking key
        if self.header.mask {
            len += 4;
        }

        // Payload data
        len += self.header.payload_len as usize;

        len
    }

    fn as_mut_raw_erased(&self) -> *mut () {
        let dup = Box::new(self.clone());
        return Box::into_raw(dup) as *mut _ as *mut ();
    }
}

impl Default for WebSocketFrame {
    fn default() -> WebSocketFrame {
        WebSocketFrame {
            frame_type: FrameType::Control,
            header: Header {
                op_code: CONTINUATION,
                mask: false,
                payload_len: 0u64,
                masking_key: [0u8; 4]
            },
            payload: Payload {
                data: Vec::<u8>::new()
            }
        }
    }
}

impl fmt::Debug for FrameType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FrameType::Control => write!(f, "FrameType::Control"),
            FrameType::Data => write!(f, "FrameType::Data")
        }
    }
}

impl fmt::Display for FrameType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FrameType::Control => write!(f, "FrameType::Control"),
            FrameType::Data => write!(f, "FrameType::Data")
        }
    }
}

impl fmt::Debug for OpType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            OpType::Continuation => write!(f, "OpType::Continuation"),
            OpType::Text => write!(f, "OpType::Text"),
            OpType::Binary => write!(f, "OpType::Binary"),
            OpType::Close => write!(f, "OpType::Close"),
            OpType::Ping => write!(f, "OpType::Ping"),
            OpType::Pong => write!(f, "OpType::Pong"),
        }
    }
}

impl fmt::Display for OpType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            OpType::Continuation => write!(f, "OpType::Continuation"),
            OpType::Text => write!(f, "OpType::Text"),
            OpType::Binary => write!(f, "OpType::Binary"),
            OpType::Close => write!(f, "OpType::Close"),
            OpType::Ping => write!(f, "OpType::Ping"),
            OpType::Pong => write!(f, "OpType::Pong"),
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate std;
extern crate sync;

use super::liblua;
use { Lua, Pushable, CopyReadable };

extern fn wrapper1(lua: *mut liblua::lua_State) -> libc::c_int {
    // TODO: in the future the value to load will not be the upvalue itself, but the value pointed by the upvalue
    let wrapper2raw = unsafe { liblua::lua_touserdata(lua, liblua::lua_upvalueindex(2)) };
    let wrapper2: fn(*mut liblua::lua_State)->libc::c_int = unsafe { std::mem::transmute(wrapper2raw) };
    wrapper2(lua)
}

fn wrapper2<T: AnyCallable>(lua: *mut liblua::lua_State) -> libc::c_int {
    let dataRaw = unsafe { liblua::lua_touserdata(lua, liblua::lua_upvalueindex(1)) };
    let data: &T = unsafe { std::mem::transmute(&dataRaw) };

    data.load_args_and_call(lua)
}

trait AnyCallable {
    fn load_args_and_call(&self, lua: *mut liblua::lua_State)
        -> libc::c_int;
}

trait Callable<Args: CopyReadable, Ret: Pushable> {
    fn do_call(&self, args: Args) -> Ret;
}

impl<Args: CopyReadable, Ret: Pushable, T: Callable<Args, Ret>> AnyCallable for T {
    fn load_args_and_call(&self, lua: *mut liblua::lua_State)
        -> libc::c_int
    {
        let mut tmpLua = Lua{lua:lua};      // this is actually pretty dangerous (even if we forget it at the end) because in case of unwinding lua_close will be called

        let argumentsCount = unsafe { liblua::lua_gettop(lua) } as uint;

        let args = match CopyReadable::read_from_lua(&mut tmpLua, -argumentsCount as libc::c_int) {      // TODO: what if the user has the wrong params?
            None => {
                let errMsg = format!("unable to read parameters");
                errMsg.push_to_lua(&mut tmpLua);
                unsafe { liblua::lua_error(lua); }
                unreachable!()
            },
            Some(a) => a
        };

        let retValue = self.do_call(args);
        let nb = retValue.push_to_lua(&mut tmpLua);

        unsafe { std::mem::forget(tmpLua) };   // do not call lua_close on this temporary context

        nb as libc::c_int
    }
}

macro_rules! pushable_function(
    ($b:block | $($ty:ident),*) => (
        impl<Ret: Pushable $(, $ty : CopyReadable+Clone)*> Pushable for fn($($ty),*)->Ret {
            fn push_to_lua(&self, lua: &mut Lua) -> uint {
                // pushing the function pointer as a lightuserdata
                unsafe { liblua::lua_pushlightuserdata(lua.lua, std::mem::transmute(*self)) };

                // pushing wrapper2 as a lightuserdata
                let wrapper2 = wrapper2::<fn($($ty),*)->Ret>;
                unsafe { liblua::lua_pushlightuserdata(lua.lua, std::mem::transmute(wrapper2)) };

                // pushing wrapper1 as a closure
                unsafe { liblua::lua_pushcclosure(lua.lua, std::mem::transmute(wrapper1), 2) };

                1
            }
        }

        impl<Ret: Pushable $(, $ty : CopyReadable+Clone)*> Callable<($($ty),*),Ret> for fn($($ty),*)->Ret {
            fn do_call(&self, args: ($($ty),*))
                -> Ret
            {
                $b
            }
        }
    );
)

pushable_function!({ (*self)() } | )
pushable_function!({ (*self)(args) } | Arg1 )
pushable_function!({ (*self)(args.ref0().clone(), args.ref1().clone()) } | Arg1, Arg2 )
pushable_function!({ (*self)(args.ref0().clone(), args.ref1().clone(), args.ref2().clone()) } | Arg1, Arg2, Arg3 )
pushable_function!({ (*self)(args.ref0().clone(), args.ref1().clone(), args.ref2().clone(), args.ref3().clone()) } | Arg1, Arg2, Arg3, Arg4 )
pushable_function!({ (*self)(args.ref0().clone(), args.ref1().clone(), args.ref2().clone(), args.ref3().clone(), args.ref4().clone()) } | Arg1, Arg2, Arg3, Arg4, Arg5 )
// TODO: finish

#[cfg(test)]
mod tests {
    #[test]
    fn simple_function() {
        let mut lua = super::super::Lua::new();

        fn ret5() -> int { 5 };
        lua.set("ret5", ret5).unwrap();

        let val: int = lua.execute("return ret5()").unwrap();
        assert_eq!(val, 5);
    }

    #[test]
    fn one_argument() {
        let mut lua = super::super::Lua::new();

        fn plus_one(val: int) -> int { val + 1 };
        lua.set("plus_one", plus_one).unwrap();

        let val: int = lua.execute("return plus_one(3)").unwrap();
        assert_eq!(val, 4);
    }

    #[test]
    fn two_arguments() {
        let mut lua = super::super::Lua::new();

        fn add(val1: int, val2: int) -> int { val1 + val2 };
        lua.set("add", add).unwrap();

        let val: int = lua.execute("return add(3, 7)").unwrap();
        assert_eq!(val, 10);
    }
}
<commit_msg>Add test for wrong parameters types for functions<commit_after>extern crate libc;
extern crate std;
extern crate sync;

use super::liblua;
use { Lua, Pushable, CopyReadable };

extern fn wrapper1(lua: *mut liblua::lua_State) -> libc::c_int {
    // TODO: in the future the value to load will not be the upvalue itself, but the value pointed by the upvalue
    let wrapper2raw = unsafe { liblua::lua_touserdata(lua, liblua::lua_upvalueindex(2)) };
    let wrapper2: fn(*mut liblua::lua_State)->libc::c_int = unsafe { std::mem::transmute(wrapper2raw) };
    wrapper2(lua)
}

fn wrapper2<T: AnyCallable>(lua: *mut liblua::lua_State) -> libc::c_int {
    let dataRaw = unsafe { liblua::lua_touserdata(lua, liblua::lua_upvalueindex(1)) };
    let data: &T = unsafe { std::mem::transmute(&dataRaw) };

    data.load_args_and_call(lua)
}

trait AnyCallable {
    fn load_args_and_call(&self, lua: *mut liblua::lua_State)
        -> libc::c_int;
}

trait Callable<Args: CopyReadable, Ret: Pushable> {
    fn do_call(&self, args: Args) -> Ret;
}

impl<Args: CopyReadable, Ret: Pushable, T: Callable<Args, Ret>> AnyCallable for T {
    fn load_args_and_call(&self, lua: *mut liblua::lua_State)
        -> libc::c_int
    {
        let mut tmpLua = Lua{lua:lua};      // this is actually pretty dangerous (even if we forget it at the end) because in case of unwinding lua_close will be called

        let argumentsCount = unsafe { liblua::lua_gettop(lua) } as uint;

        let args = match CopyReadable::read_from_lua(&mut tmpLua, -argumentsCount as libc::c_int) {      // TODO: what if the user has the wrong params?
            None => {
                let errMsg = format!("wrong parameter types for callback function");
                errMsg.push_to_lua(&mut tmpLua);
                unsafe { liblua::lua_error(lua); }
                unreachable!()
            },
            Some(a) => a
        };

        let retValue = self.do_call(args);
        let nb = retValue.push_to_lua(&mut tmpLua);

        unsafe { std::mem::forget(tmpLua) };   // do not call lua_close on this temporary context

        nb as libc::c_int
    }
}

macro_rules! pushable_function(
    ($b:block | $($ty:ident),*) => (
        impl<Ret: Pushable $(, $ty : CopyReadable+Clone)*> Pushable for fn($($ty),*)->Ret {
            fn push_to_lua(&self, lua: &mut Lua) -> uint {
                // pushing the function pointer as a lightuserdata
                unsafe { liblua::lua_pushlightuserdata(lua.lua, std::mem::transmute(*self)) };

                // pushing wrapper2 as a lightuserdata
                let wrapper2 = wrapper2::<fn($($ty),*)->Ret>;
                unsafe { liblua::lua_pushlightuserdata(lua.lua, std::mem::transmute(wrapper2)) };

                // pushing wrapper1 as a closure
                unsafe { liblua::lua_pushcclosure(lua.lua, std::mem::transmute(wrapper1), 2) };

                1
            }
        }

        impl<Ret: Pushable $(, $ty : CopyReadable+Clone)*> Callable<($($ty),*),Ret> for fn($($ty),*)->Ret {
            fn do_call(&self, args: ($($ty),*))
                -> Ret
            {
                $b
            }
        }
    );
)

pushable_function!({ (*self)() } | )
pushable_function!({ (*self)(args) } | Arg1 )
pushable_function!({ (*self)(args.ref0().clone(), args.ref1().clone()) } | Arg1, Arg2 )
pushable_function!({ (*self)(args.ref0().clone(), args.ref1().clone(), args.ref2().clone()) } | Arg1, Arg2, Arg3 )
pushable_function!({ (*self)(args.ref0().clone(), args.ref1().clone(), args.ref2().clone(), args.ref3().clone()) } | Arg1, Arg2, Arg3, Arg4 )
pushable_function!({ (*self)(args.ref0().clone(), args.ref1().clone(), args.ref2().clone(), args.ref3().clone(), args.ref4().clone()) } | Arg1, Arg2, Arg3, Arg4, Arg5 )
// TODO: finish

#[cfg(test)]
mod tests {
    #[test]
    fn simple_function() {
        let mut lua = super::super::Lua::new();

        fn ret5() -> int { 5 };
        lua.set("ret5", ret5).unwrap();

        let val: int = lua.execute("return ret5()").unwrap();
        assert_eq!(val, 5);
    }

    #[test]
    fn one_argument() {
        let mut lua = super::super::Lua::new();

        fn plus_one(val: int) -> int { val + 1 };
        lua.set("plus_one", plus_one).unwrap();

        let val: int = lua.execute("return plus_one(3)").unwrap();
        assert_eq!(val, 4);
    }

    #[test]
    fn two_arguments() {
        let mut lua = super::super::Lua::new();

        fn add(val1: int, val2: int) -> int { val1 + val2 };
        lua.set("add", add).unwrap();

        let val: int = lua.execute("return add(3, 7)").unwrap();
        assert_eq!(val, 10);
    }

    #[test]
    fn wrong_arguments_types() {
        let mut lua = super::super::Lua::new();

        fn add(val1: int, val2: int) -> int { val1 + val2 };
        lua.set("add", add).unwrap();

        match lua.execute("return add(3, \"hello\")") {
            Ok(x) => { let a: int = x; fail!() },
            Err(_) => ()        // TODO: check for execerror
        }
    }
}
<|endoftext|>


<commit_before>#![feature(try_trait)]
// Copyright 2020 Google LLC
//
// 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.

//! See LICENSE for licensing information.
//!
//! This build.rs script provides Cargo _features_ indicating the target ICU4C library version,
//! enabling some conditionally compiled Rust code in this crate that depends on the particular
//! ICU4C version.
//!
//! Please refer to README.md for instructions on how to build the library for your use.

use {
    anyhow::{Context, Result},
    std::process,
};

/// A `Command` that also knows its name.
struct Command {
    name: String,
    rep: process::Command,
}

impl Command {
    /// Creates a new command to run, with the executable `name`.
    pub fn new(name: &'static str) -> Self {
        let rep = process::Command::new(&name);
        let name = String::from(name);
        Command { name, rep }
    }

    /// Runs this command with `args` as arguments.
    pub fn run(&mut self, args: &[&str]) -> Result<String> {
        self.rep.args(args);
        let stdout = self.stdout()?;
        Ok(String::from(&stdout).trim().to_string())
    }

    // Captures the stdout of the command.
    fn stdout(&mut self) -> Result<String> {
        let output = self
            .rep
            .output()
            .with_context(|| format!("could not execute command: {}", self.name))?;
        let result = String::from_utf8(output.stdout)
            .with_context(|| format!("could not convert output to UTF8"))?;
        Ok(result.trim().to_string())
    }
}

/// A command representing an auto-configuration detector.  Use `ICUConfig::new()` to create.
struct ICUConfig {
    rep: Command,
}

impl ICUConfig {
    /// Creates a new ICUConfig.
    fn new() -> Self {
        ICUConfig {
            rep: Command::new("pkg-config"),
        }
    }
    /// Obtains the major-minor version number for the library. Returns a string like `64.2`.
    fn version(&mut self) -> Result<String> {
        self.rep
            .run(&["--modversion", "icu-i18n"])
            .with_context(|| format!("while getting ICU version; is icu-config in $PATH?"))
    }

    /// Returns the config major number.  For example, will return "64" for
    /// version "64.2"
    fn version_major() -> Result<String> {
        let version = ICUConfig::new().version()?;
        let components = version.split(".");
        let last = components
            .take(1)
            .last()
            .with_context(|| format!("could not parse version number: {}", version))?;
        Ok(last.to_string())
    }

    fn version_major_int() -> Result<i32> {
        let version_str = ICUConfig::version_major()?;
        Ok(version_str.parse().unwrap())
    }
}

fn main() -> Result<()> {
    std::env::set_var("RUST_BACKTRACE", "full");
    let icu_major_version = ICUConfig::version_major_int()?;
    println!("icu-major-version: {}", icu_major_version);
    if icu_major_version >= 64 {
        println!("cargo:rustc-cfg=feature=\"icu_version_64_plus\"");
    }
    if icu_major_version >= 67 {
        println!("cargo:rustc-cfg=feature=\"icu_version_67_plus\"");
    }
    println!("done");
    Ok(())
}
<commit_msg>rust_icu_uloc: Make build.rs no-op if icu_config is disabled<commit_after>#![feature(try_trait)]
// Copyright 2020 Google LLC
//
// 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.

//! See LICENSE for licensing information.
//!
//! This build.rs script provides Cargo _features_ indicating the target ICU4C library version,
//! enabling some conditionally compiled Rust code in this crate that depends on the particular
//! ICU4C version.
//!
//! Please refer to README.md for instructions on how to build the library for your use.

#[cfg(feature = "icu_config")]
mod inner {
    use {
        anyhow::{Context, Result},
        std::process,
    };

    /// A `Command` that also knows its name.
    struct Command {
        name: String,
        rep: process::Command,
    }

    impl Command {
        /// Creates a new command to run, with the executable `name`.
        pub fn new(name: &'static str) -> Self {
            let rep = process::Command::new(&name);
            let name = String::from(name);
            Command { name, rep }
        }

        /// Runs this command with `args` as arguments.
        pub fn run(&mut self, args: &[&str]) -> Result<String> {
            self.rep.args(args);
            let stdout = self.stdout()?;
            Ok(String::from(&stdout).trim().to_string())
        }

        // Captures the stdout of the command.
        fn stdout(&mut self) -> Result<String> {
            let output = self
                .rep
                .output()
                .with_context(|| format!("could not execute command: {}", self.name))?;
            let result = String::from_utf8(output.stdout)
                .with_context(|| format!("could not convert output to UTF8"))?;
            Ok(result.trim().to_string())
        }
    }

    /// A command representing an auto-configuration detector.  Use `ICUConfig::new()` to create.
    pub struct ICUConfig {
        rep: Command,
    }

    impl ICUConfig {
        /// Creates a new ICUConfig.
        pub fn new() -> Self {
            ICUConfig {
                rep: Command::new("pkg-config"),
            }
        }
        /// Obtains the major-minor version number for the library. Returns a string like `64.2`.
        pub fn version(&mut self) -> Result<String> {
            self.rep
                .run(&["--modversion", "icu-i18n"])
                .with_context(|| format!("while getting ICU version; is icu-config in $PATH?"))
        }

        /// Returns the config major number.  For example, will return "64" for
        /// version "64.2"
        pub fn version_major() -> Result<String> {
            let version = ICUConfig::new().version()?;
            let components = version.split(".");
            let last = components
                .take(1)
                .last()
                .with_context(|| format!("could not parse version number: {}", version))?;
            Ok(last.to_string())
        }

        pub fn version_major_int() -> Result<i32> {
            let version_str = ICUConfig::version_major()?;
            Ok(version_str.parse().unwrap())
        }
    }
}

#[cfg(feature = "icu_config")]
fn main() -> anyhow::Result<()> {
    std::env::set_var("RUST_BACKTRACE", "full");
    let icu_major_version = inner::ICUConfig::version_major_int()?;
    println!("icu-major-version: {}", icu_major_version);
    if icu_major_version >= 64 {
        println!("cargo:rustc-cfg=feature=\"icu_version_64_plus\"");
    }
    if icu_major_version >= 67 {
        println!("cargo:rustc-cfg=feature=\"icu_version_67_plus\"");
    }
    println!("done");
    Ok(())
}

/// No-op if icu_config is disabled.
#[cfg(not(feature = "icu_config"))]
fn main() {}
<|endoftext|>


<commit_before>use crate::colors::{BitDepth, ColorType};
use crate::headers::IhdrData;
use crate::png::PngImage;
use bit_vec::BitVec;

const ONE_BIT_PERMUTATIONS: [u8; 2] = [0b0000_0000, 0b1111_1111];
const TWO_BIT_PERMUTATIONS: [u8; 5] = [
    0b0000_0000,
    0b0000_1111,
    0b0011_1100,
    0b1111_0000,
    0b1111_1111,
];
const FOUR_BIT_PERMUTATIONS: [u8; 11] = [
    0b0000_0000,
    0b0000_0011,
    0b0000_1100,
    0b0011_0000,
    0b1100_0000,
    0b0000_1111,
    0b0011_1100,
    0b1111_0000,
    0b0011_1111,
    0b1111_1100,
    0b1111_1111,
];

/// Attempt to reduce the bit depth of the image
/// Returns true if the bit depth was reduced, false otherwise
#[must_use]
pub fn reduce_bit_depth(png: &PngImage, minimum_bits: usize) -> Option<PngImage> {
    if png.ihdr.bit_depth != BitDepth::Sixteen {
        if png.ihdr.color_type == ColorType::Indexed || png.ihdr.color_type == ColorType::Grayscale
        {
            return reduce_bit_depth_8_or_less(png, minimum_bits);
        }
        return None;
    }

    // Reduce from 16 to 8 bits per channel per pixel
    let mut reduced = Vec::with_capacity(
        (png.ihdr.width * png.ihdr.height * u32::from(png.channels_per_pixel()) + png.ihdr.height)
            as usize,
    );
    let mut high_byte = 0;

    for line in png.scan_lines() {
        reduced.push(line.filter);
        for (i, &byte) in line.data.iter().enumerate() {
            if i % 2 == 0 {
                // High byte
                high_byte = byte;
            } else {
                // Low byte
                if high_byte != byte {
                    // Can't reduce, exit early
                    return None;
                }
                reduced.push(byte);
            }
        }
    }

    Some(PngImage {
        data: reduced,
        ihdr: IhdrData {
            bit_depth: BitDepth::Eight,
            ..png.ihdr
        },
        palette: None,
        transparency_pixel: png.transparency_pixel.clone(),
        aux_headers: png.aux_headers.clone(),
    })
}

#[must_use]
pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Option<PngImage> {
    assert!(minimum_bits >= 1 && minimum_bits < 8);
    let mut reduced = BitVec::with_capacity(png.data.len() * 8);
    let bit_depth: usize = png.ihdr.bit_depth.as_u8() as usize;
    if minimum_bits >= bit_depth {
        return None;
    }
    for line in png.scan_lines() {
        if png.ihdr.color_type == ColorType::Indexed {
            let line_max = line
                .data
                .iter()
                .map(|&byte| match png.ihdr.bit_depth {
                    BitDepth::Two => (byte & 0x3)
                        .max((byte >> 2) & 0x3)
                        .max((byte >> 4) & 0x3)
                        .max(byte >> 6),
                    BitDepth::Four => (byte & 0xF).max(byte >> 4),
                    _ => byte,
                })
                .max()
                .unwrap_or(0);
            let required_bits = match line_max {
                x if x > 0x0F => 8,
                x if x > 0x03 => 4,
                x if x > 0x01 => 2,
                _ => 1,
            };
            if required_bits > minimum_bits {
                minimum_bits = required_bits;
                if minimum_bits >= bit_depth {
                    // Not reducable
                    return None;
                }
            }
        } else {
            let bit_vec = BitVec::from_bytes(&line.data);
            for byte in bit_vec.to_bytes() {
                while minimum_bits < bit_depth {
                    let permutations: &[u8] = if minimum_bits == 1 {
                        &ONE_BIT_PERMUTATIONS
                    } else if minimum_bits == 2 {
                        &TWO_BIT_PERMUTATIONS
                    } else if minimum_bits == 4 {
                        &FOUR_BIT_PERMUTATIONS
                    } else {
                        return None;
                    };
                    if permutations.iter().any(|perm| *perm == byte) {
                        break;
                    } else {
                        minimum_bits <<= 1;
                    }
                }
            }
        }
    }

    for line in png.scan_lines() {
        reduced.extend(BitVec::from_bytes(&[line.filter]));
        let bit_vec = BitVec::from_bytes(&line.data);
        for (i, bit) in bit_vec.iter().enumerate() {
            let bit_index = bit_depth - (i % bit_depth);
            if bit_index <= minimum_bits {
                reduced.push(bit);
            }
        }
        // Pad end of line to get 8 bits per byte
        while reduced.len() % 8 != 0 {
            reduced.push(false);
        }
    }

    Some(PngImage {
        data: reduced.to_bytes(),
        ihdr: IhdrData {
            bit_depth: BitDepth::from_u8(minimum_bits as u8),
            ..png.ihdr
        },
        aux_headers: png.aux_headers.clone(),
        palette: png.palette.clone(),
        transparency_pixel: png.transparency_pixel.clone(),
    })
}
<commit_msg>Fixes for grey scale reduction (#171)<commit_after>use crate::colors::{BitDepth, ColorType};
use crate::headers::IhdrData;
use crate::png::PngImage;
use bit_vec::BitVec;

const ONE_BIT_PERMUTATIONS: [u8; 2] = [0b0000_0000, 0b1111_1111];
const TWO_BIT_PERMUTATIONS: [u8; 4] = [
    0b0000_0000,
    0b0101_0101,
    0b1010_1010,
    0b1111_1111,
];
const FOUR_BIT_PERMUTATIONS: [u8; 16] = [
    0b0000_0000,
    0b0001_0001,
    0b0010_0010,
    0b0011_0011,
    0b0100_0100,
    0b0101_0101,
    0b0110_0110,
    0b0111_0111,
    0b1000_1000,
    0b1001_1001,
    0b1010_1010,
    0b1011_1011,
    0b1100_1100,
    0b1101_1101,
    0b1110_1110,
    0b1111_1111,
];

/// Attempt to reduce the bit depth of the image
/// Returns true if the bit depth was reduced, false otherwise
#[must_use]
pub fn reduce_bit_depth(png: &PngImage, minimum_bits: usize) -> Option<PngImage> {
    if png.ihdr.bit_depth != BitDepth::Sixteen {
        if png.ihdr.color_type == ColorType::Indexed || png.ihdr.color_type == ColorType::Grayscale
        {
            return reduce_bit_depth_8_or_less(png, minimum_bits);
        }
        return None;
    }

    // Reduce from 16 to 8 bits per channel per pixel
    let mut reduced = Vec::with_capacity(
        (png.ihdr.width * png.ihdr.height * u32::from(png.channels_per_pixel()) + png.ihdr.height)
            as usize,
    );
    let mut high_byte = 0;

    for line in png.scan_lines() {
        reduced.push(line.filter);
        for (i, &byte) in line.data.iter().enumerate() {
            if i % 2 == 0 {
                // High byte
                high_byte = byte;
            } else {
                // Low byte
                if high_byte != byte {
                    // Can't reduce, exit early
                    return None;
                }
                reduced.push(byte);
            }
        }
    }

    Some(PngImage {
        data: reduced,
        ihdr: IhdrData {
            bit_depth: BitDepth::Eight,
            ..png.ihdr
        },
        palette: None,
        transparency_pixel: png.transparency_pixel.clone(),
        aux_headers: png.aux_headers.clone(),
    })
}

#[must_use]
pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Option<PngImage> {
    assert!(minimum_bits >= 1 && minimum_bits < 8);
    let mut reduced = BitVec::with_capacity(png.data.len() * 8);
    let bit_depth: usize = png.ihdr.bit_depth.as_u8() as usize;
    if minimum_bits >= bit_depth {
        return None;
    }
    for line in png.scan_lines() {
        if png.ihdr.color_type == ColorType::Indexed {
            let line_max = line
                .data
                .iter()
                .map(|&byte| match png.ihdr.bit_depth {
                    BitDepth::Two => (byte & 0x3)
                        .max((byte >> 2) & 0x3)
                        .max((byte >> 4) & 0x3)
                        .max(byte >> 6),
                    BitDepth::Four => (byte & 0xF).max(byte >> 4),
                    _ => byte,
                })
                .max()
                .unwrap_or(0);
            let required_bits = match line_max {
                x if x > 0x0F => 8,
                x if x > 0x03 => 4,
                x if x > 0x01 => 2,
                _ => 1,
            };
            if required_bits > minimum_bits {
                minimum_bits = required_bits;
                if minimum_bits >= bit_depth {
                    // Not reducable
                    return None;
                }
            }
        } else {
            let bit_vec = BitVec::from_bytes(&line.data);
            for byte in bit_vec.to_bytes() {
                while minimum_bits < bit_depth {
                    let permutations: &[u8] = if minimum_bits == 1 {
                        &ONE_BIT_PERMUTATIONS
                    } else if minimum_bits == 2 {
                        &TWO_BIT_PERMUTATIONS
                    } else if minimum_bits == 4 {
                        &FOUR_BIT_PERMUTATIONS
                    } else {
                        return None;
                    };
                    if permutations.iter().any(|perm| *perm == byte) {
                        break;
                    } else {
                        minimum_bits <<= 1;
                    }
                }
            }
        }
    }

    for line in png.scan_lines() {
        reduced.extend(BitVec::from_bytes(&[line.filter]));
        let bit_vec = BitVec::from_bytes(&line.data);
        for (i, bit) in bit_vec.iter().enumerate() {
            let bit_index = bit_depth - (i % bit_depth);
            if bit_index <= minimum_bits {
                reduced.push(bit);
            }
        }
        // Pad end of line to get 8 bits per byte
        while reduced.len() % 8 != 0 {
            reduced.push(false);
        }
    }

    Some(PngImage {
        data: reduced.to_bytes(),
        ihdr: IhdrData {
            bit_depth: BitDepth::from_u8(minimum_bits as u8),
            ..png.ihdr
        },
        aux_headers: png.aux_headers.clone(),
        palette: png.palette.clone(),
        transparency_pixel: png.transparency_pixel.clone(),
    })
}
<|endoftext|>


<commit_before>#[doc(
    brief = "Attribute parsing",
    desc =
    "The attribute parser provides methods for pulling documentation out of \
     an AST's attributes."
)];

use syntax::ast;
use syntax::attr;
use core::tuple;

export CrateAttrs;
export parse_crate, parse_desc;
export parse_hidden;

type CrateAttrs = {
    name: Option<~str>
};

#[cfg(test)]
mod test {

    fn parse_attributes(source: ~str) -> ~[ast::attribute] {
        use syntax::parse;
        use parse::parser;
        use parse::attr::parser_attr;
        use syntax::codemap;
        use syntax::diagnostic;

        let parse_sess = syntax::parse::new_parse_sess(None);
        let parser = parse::new_parser_from_source_str(
            parse_sess, ~[], ~"-", codemap::fss_none, @source);

        parser.parse_outer_attributes()
    }
}

fn doc_meta(
    attrs: ~[ast::attribute]
) -> Option<@ast::meta_item> {

    /*!
     * Given a vec of attributes, extract the meta_items contained in the \
     * doc attribute
     */

    let doc_attrs = attr::find_attrs_by_name(attrs, ~"doc");
    let doc_metas = do doc_attrs.map |attr| {
        attr::attr_meta(attr::desugar_doc_attr(attr))
    };

    if vec::is_not_empty(doc_metas) {
        if vec::len(doc_metas) != 1u {
            warn!("ignoring %u doc attributes", vec::len(doc_metas) - 1u);
        }
        Some(doc_metas[0])
    } else {
        None
    }
}

fn parse_crate(attrs: ~[ast::attribute]) -> CrateAttrs {
    let link_metas = attr::find_linkage_metas(attrs);

    {
        name: attr::last_meta_item_value_str_by_name(link_metas, ~"name")
    }
}

#[test]
fn should_extract_crate_name_from_link_attribute() {
    let source = ~"#[link(name = \"snuggles\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == Some(~"snuggles");
}

#[test]
fn should_not_extract_crate_name_if_no_link_attribute() {
    let source = ~"";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == None;
}

#[test]
fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() {
    let source = ~"#[link(whatever)]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == None;
}

fn parse_desc(attrs: ~[ast::attribute]) -> Option<~str> {
    match doc_meta(attrs) {
      Some(meta) => {
        attr::get_meta_item_value_str(meta)
      }
      None => None
    }
}

#[test]
fn parse_desc_should_handle_undocumented_mods() {
    let source = ~"";
    let attrs = test::parse_attributes(source);
    let attrs = parse_desc(attrs);
    assert attrs == None;
}

#[test]
fn parse_desc_should_parse_simple_doc_attributes() {
    let source = ~"#[doc = \"basic\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_desc(attrs);
    assert attrs == Some(~"basic");
}

fn parse_hidden(attrs: ~[ast::attribute]) -> bool {
    match doc_meta(attrs) {
      Some(meta) => {
        match attr::get_meta_item_list(meta) {
          Some(metas) => {
            let hiddens = attr::find_meta_items_by_name(metas, ~"hidden");
            vec::is_not_empty(hiddens)
          }
          None => false
        }
      }
      None => false
    }
}

#[test]
fn shoulde_parse_hidden_attribute() {
    let source = ~"#[doc(hidden)]";
    let attrs = test::parse_attributes(source);
    assert parse_hidden(attrs) == true;
}

#[test]
fn shoulde_not_parse_non_hidden_attribute() {
    let source = ~"#[doc = \"\"]";
    let attrs = test::parse_attributes(source);
    assert parse_hidden(attrs) == false;
}
<commit_msg>rustdoc: Fix spelling in tests<commit_after>#[doc(
    brief = "Attribute parsing",
    desc =
    "The attribute parser provides methods for pulling documentation out of \
     an AST's attributes."
)];

use syntax::ast;
use syntax::attr;
use core::tuple;

export CrateAttrs;
export parse_crate, parse_desc;
export parse_hidden;

type CrateAttrs = {
    name: Option<~str>
};

#[cfg(test)]
mod test {

    fn parse_attributes(source: ~str) -> ~[ast::attribute] {
        use syntax::parse;
        use parse::parser;
        use parse::attr::parser_attr;
        use syntax::codemap;
        use syntax::diagnostic;

        let parse_sess = syntax::parse::new_parse_sess(None);
        let parser = parse::new_parser_from_source_str(
            parse_sess, ~[], ~"-", codemap::fss_none, @source);

        parser.parse_outer_attributes()
    }
}

fn doc_meta(
    attrs: ~[ast::attribute]
) -> Option<@ast::meta_item> {

    /*!
     * Given a vec of attributes, extract the meta_items contained in the \
     * doc attribute
     */

    let doc_attrs = attr::find_attrs_by_name(attrs, ~"doc");
    let doc_metas = do doc_attrs.map |attr| {
        attr::attr_meta(attr::desugar_doc_attr(attr))
    };

    if vec::is_not_empty(doc_metas) {
        if vec::len(doc_metas) != 1u {
            warn!("ignoring %u doc attributes", vec::len(doc_metas) - 1u);
        }
        Some(doc_metas[0])
    } else {
        None
    }
}

fn parse_crate(attrs: ~[ast::attribute]) -> CrateAttrs {
    let link_metas = attr::find_linkage_metas(attrs);

    {
        name: attr::last_meta_item_value_str_by_name(link_metas, ~"name")
    }
}

#[test]
fn should_extract_crate_name_from_link_attribute() {
    let source = ~"#[link(name = \"snuggles\")]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == Some(~"snuggles");
}

#[test]
fn should_not_extract_crate_name_if_no_link_attribute() {
    let source = ~"";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == None;
}

#[test]
fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() {
    let source = ~"#[link(whatever)]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_crate(attrs);
    assert attrs.name == None;
}

fn parse_desc(attrs: ~[ast::attribute]) -> Option<~str> {
    match doc_meta(attrs) {
      Some(meta) => {
        attr::get_meta_item_value_str(meta)
      }
      None => None
    }
}

#[test]
fn parse_desc_should_handle_undocumented_mods() {
    let source = ~"";
    let attrs = test::parse_attributes(source);
    let attrs = parse_desc(attrs);
    assert attrs == None;
}

#[test]
fn parse_desc_should_parse_simple_doc_attributes() {
    let source = ~"#[doc = \"basic\"]";
    let attrs = test::parse_attributes(source);
    let attrs = parse_desc(attrs);
    assert attrs == Some(~"basic");
}

fn parse_hidden(attrs: ~[ast::attribute]) -> bool {
    match doc_meta(attrs) {
      Some(meta) => {
        match attr::get_meta_item_list(meta) {
          Some(metas) => {
            let hiddens = attr::find_meta_items_by_name(metas, ~"hidden");
            vec::is_not_empty(hiddens)
          }
          None => false
        }
      }
      None => false
    }
}

#[test]
fn should_parse_hidden_attribute() {
    let source = ~"#[doc(hidden)]";
    let attrs = test::parse_attributes(source);
    assert parse_hidden(attrs) == true;
}

#[test]
fn should_not_parse_non_hidden_attribute() {
    let source = ~"#[doc = \"\"]";
    let attrs = test::parse_attributes(source);
    assert parse_hidden(attrs) == false;
}
<|endoftext|>