<commit_before>/// Macro that generates a `struct` implementation of a specified trait.
///
/// This macro generates a `struct` that implements the traits `Clone`, `Debug`
/// and `Default`. Create instances of the mock object by calling the `struct`'s
/// `default()` method.
///
/// The `struct` has a field for each method of the `trait`, which manages their
/// respective method's behaviour and call expectations. For example, if one
/// defines a mock like so:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// mock_trait!(
///     MockTaskManager,
///     max_threads(()) -> u32,
///     set_max_threads(u32) -> ()
/// );
///
/// # fn main() {
///     // only here to make `cargo test` happy
/// }
/// ```
///
/// Then the following code is generated:
///
/// ```
/// #[derive(Debug, Clone)]
/// struct MockTaskManager {
///     max_threads: double::Mock<(), u32>,
///     set_max_threads: double::Mock<(u32), ()>,
/// }
///
/// impl Default for MockTaskManager {
///     fn default() -> Self {
///         MockTaskManager {
///             max_threads: double::Mock::default(),
///             set_max_threads: double::Mock::default(),
///         }
///     }
/// }
/// ```
///
/// Note that just defining this macro is not enough. This macro is used to
/// generate the necessary boilerplate, but the generated struct *does not*
/// implement the desired `trait`. To do that, use `double`'s `mock_method`
/// macro.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate double;
///
/// trait TaskManager {
///    fn max_threads(&self) -> u32;
///    fn set_max_threads(&mut self, max_threads: u32);
/// }
///
/// mock_trait!(
///     MockTaskManager,
///     max_threads(()) -> u32,
///     set_max_threads(u32) -> ()
/// );
///
/// # fn main() {
/// let mock = MockTaskManager::default();
/// mock.max_threads.return_value(42u32);
/// assert_eq!(42, mock.max_threads.call(()));
/// mock.set_max_threads.call(9001u32);
/// assert!(mock.set_max_threads.called_with(9001u32));
/// # }
/// ```
#[macro_export]
macro_rules! mock_trait {
    ($mock_name:ident $(, $method:ident($($arg_type:ty),* ) -> $retval:ty )* ) => (
        #[derive(Debug, Clone)]
        struct $mock_name {
            $(
                $method: double::Mock<(($($arg_type),*)), $retval>
            ),*
        }

        impl Default for $mock_name {
            fn default() -> Self {
                $mock_name {
                    $(
                        $method: double::Mock::default()
                    ),*
                }
            }
        }
    );
}

/// Macro that generates a mock implementation of a `trait` method.
///
/// This should be used to implement a `trait` on a mock type generated by
/// `double`'s `mock_trait` macro. If one has generated a mock `struct` using
/// `mock_trait`, then the actual *implementation* of the desired trait can be
/// auto-generated using `mock_method`, like so:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// trait TaskManager {
///    fn max_threads(&self) -> u32;
///    fn set_max_threads(&mut self, max_threads: u32);
/// }
///
/// mock_trait!(
///     MockTaskManager,
///     max_threads(()) -> u32,
///     set_max_threads(u32) -> ()
/// );
///
/// // Actually implement the trait that should be mocked
/// impl TaskManager for MockTaskManager {
///     mock_method!(max_threads(&self) -> u32);
///     mock_method!(set_max_threads(&mut self, max_threads: u32));
/// }
///
/// # fn main() {
/// let mut mock = MockTaskManager::default();
/// mock.max_threads.return_value(42u32);
/// assert_eq!(42, mock.max_threads());
/// assert!(mock.max_threads.called_with(()));
/// mock.set_max_threads(9001u32);
/// assert!(mock.set_max_threads.called_with(9001u32));
/// # }
/// ```
///
/// There are many different variants of `mock_method`. In total there are 12
/// variants. 8 variants provides a combination of the following:
///
/// 1. const method (`&self`) **or** mutable method (`&mut self`)
/// 2. return value (`fn foo(&self) -> bool`) **or** no return value (`fn foo(&self)`)
/// 3. automatically generated method body **or** custom method body
///
/// (1) allows both constant and mutable methods tobe mocked, like in the
/// `MockTaskManager` example above.
///
/// (2) is for convenience. It means one doesn't have to specify `-> ()`
/// explicitly for mocked methods that don't return values. This can also be
/// shown in the `MockTaskManager` example. Notice how the return type is not
/// specified when generating the `set_max_threads()` mock.
///
/// (3) is useful when the stored call arguments' types (defined by the
/// `mock_trait()` macro) are different to the mocked method. There are cases
/// where type differences in the stored args and the actual method args are
/// required. For example, suppose you had the following trait:
///
/// ```
/// trait TextStreamWriter {
///     fn write(text: &str);
/// }
/// ```
///
/// A mock can't _store_ received `text` arguments as `&str` because the mock
/// needs to the _own_ the given arguments (and `&str` is a non-owning
/// reference). Therefore, the mock trait has to be specified like so:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// trait TextStreamWriter {
///     fn write(&mut self, text: &str);
/// }
///
/// mock_trait!(
///     MockTextStreamWriter,
///     // have to use `String`, not `&str` here, since `&str` is a reference
///     write(String) -> ()
/// );
///
/// impl TextStreamWriter for MockTextStreamWriter {
///     mock_method!(write(&mut self, text: &str), self, {
///         // manually convert the reference to an owned `String` before
///         // passing it to the underlying mock object
///         self.write.call(text.to_owned())
///     });
/// }
/// # fn main() {
///     // only here to make `cargo test` happy
/// }
/// ```
///
/// Using variant (3) of `mock_method` means we specify the body of the
/// generated function manually. The custom body simply converts the `&str`
/// argument to an owned string and passes it into the underlying `write` `Mock`
/// object manually. (normally auto-generated bodies do this for you).
///
/// The name of the underlying mock object is always the same as the mocked
/// method's name.
///
/// `&str` parameters are common. It can be inconvenient haven't to manually
/// specify the body each time they appear. There are plans to add a macro to
/// generate a body that calls `to_owned()` automatically.
/// (TODO: implement the macro)
///
/// ### Type Parameters
///
/// There are an additional 4 variants to handle method type parameters
/// (e.g. `fn foo<T: Eq>(&self, a: &T)`). These variants allow one to generate
/// mock methods which take some generic type parameters.
///
/// For example, suppose one had a `Comparator` trait that was responsible for
/// comparing any two values in the program. It might look something like this:
///
/// ```
/// trait Comparator {
///    fn is_equal<T: Eq>(&self, a: &T, b: &T) -> bool;
/// }
/// ```
///
/// `T` can be multiple types. Currently, we cannot store call arguments that
/// have generic types in the underlying `Mock` objects. Therefore, one has to
/// convert the generic types to a different, common representation. One way
/// to get around this limitation is converting each generic type to a `String`.
/// e.g. for the `Comparator` trait:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// use std::string::ToString;
///
/// trait Comparator {
///    fn is_equal<T: Eq + ToString>(&self, a: &T, b: &T) -> bool;
/// }
///
/// mock_trait!(
///     MockComparator,
///     // store all passed in call args as strings
///     is_equal((String, String)) -> bool
/// );
///
/// impl Comparator for MockComparator {
///     mock_method!(is_equal<(T: Eq + ToString)>(&self, a: &T, b: &T) -> bool, self, {
///         // Convert both arguments to strings and manually pass to underlying
///         // mock object.
///         // Notice how the both arguments as passed as a single tuple. The
///         // underlying mock object always expects a single tuple.
///         self.is_equal.call((a.to_string(), b.to_string()))
///     });
/// }
/// # fn main() {
///     // only here to make `cargo test` happy
/// }
/// ```
///
/// If the `to_string` conversions for all `T` are not lossy, then our mock
/// expectations can be exact. If the `to_string` conversions _are_ lossy, then
/// this mechanism can still be used, providing all the properties of the passed
/// in objects are captured in the resultant `String`s.
///
/// This approach requires the writer to ensure the code under test adds the
/// `ToString` trait to the `trait`'s type argument constraints. This limitation
/// forces test writers to modify production code to use `double` for mocking.
///
/// Despite this, there is still value in using `double` for mocking generic
/// methods with type arguments. Despite adding boilerplate to production code
/// and manually implementing mock method bodies being cumbersome, the value add
/// is that all argument matching, expectations, calling test functions, etc.
/// are all still handled by `double`. Arguably, reimplenting those features is
/// more cumbersome than the small amount of boilerplate required to mock
/// methods with type arguments.
#[macro_export]
macro_rules! mock_method {

    // immutable, no return value, no type parameter, no body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*)) => (
        fn $method(&self $(,$arg_name: $arg_type)*) {
            self.$method.call(($($arg_name.clone()),*))
        }
    );

    // immutable, no return value, no type parameter, body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*), $sel:ident, $body:tt ) => (
        fn $method(&$sel $(,$arg_name: $arg_type)*) $body
    );

    // immutable, no return value, type parameter, no body
    // not provided, since type parameters need a custom body 99% of the time

    // immutable, no return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&self $(,$arg_name:ident: $arg_type:ty)*),
        $sel:ident, $body:tt) => (
            fn $method<$($type_params)*>(&$sel $(,$arg_name: $arg_type)*) $body
    );

    // immutable, return value, no type parameter, no body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty ) => (
        fn $method(&self $(,$arg_name: $arg_type)*) -> $retval {
            self.$method.call(($($arg_name.clone()),*))
        }
    );

    // immutable, return value, no type parameter, body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty, $sel:ident, $body:tt ) => (
        fn $method(&$sel $(,$arg_name: $arg_type)*) -> $retval $body
    );

    // immutable, return value, type parameter, no body
    // not provided, since type parameters need a custom body 99% of the time

    // immutable, return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&self $(,$arg_name:ident: $arg_type:ty)*)
        -> $retval:ty, $sel:ident, $body:tt ) => (
            fn $method<$($type_params)*>(&$sel $(,$arg_name: $arg_type)*) -> $retval $body
    );

    // mutable, no return value, no type parameter, no body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*)) => (
        fn $method(&mut self $(,$arg_name: $arg_type),*) {
            self.$method.call(($($arg_name.clone()),*))
        }
    );

    // mutable, no return value, no type parameter, body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*), $sel:ident, $body:tt ) => (
        fn $method(&mut $sel $(,$arg_name: $arg_type)*) $body
    );

    // mutable, no return value, type parameter, no body
    // not provided, since type parameters need a custom body 99% of the time

    // mutable, no return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&mut self $(,$arg_name:ident: $arg_type:ty)*),
        $sel:ident, $body:tt) => (
            fn $method<$($type_params)*>(&mut $sel $(,$arg_name: $arg_type)*) $body
    );

    // mutable, return value, no type parameter, no body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty ) => (
        fn $method(&mut self $(,$arg_name: $arg_type),*) -> $retval {
            self.$method.call(($($arg_name.clone()),*))
        }
    );

    // mutable, return value, no type parameter, body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty, $sel:ident, $body:tt ) => (
        fn $method(&mut $sel $(,$arg_name: $arg_type)*) -> $retval $body
    );

    // mutable, return value, type parameter, no body
    // not provided, since type parameters need a custom body 99% of the time

    // mutable, return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&mut self $(,$arg_name:ident: $arg_type:ty)*)
        -> $retval:ty, $sel:ident, $body:tt ) => (
            fn $method<$($type_params)*>(&mut $sel $(,$arg_name: $arg_type)*) -> $retval $body
    );

}
<commit_msg>allow definition of pub struct via mock_trait<commit_after>/// Macro that generates a `struct` implementation of a specified trait.
///
/// This macro generates a `struct` that implements the traits `Clone`, `Debug`
/// and `Default`. Create instances of the mock object by calling the `struct`'s
/// `default()` method.
///
/// The `struct` has a field for each method of the `trait`, which manages their
/// respective method's behaviour and call expectations. For example, if one
/// defines a mock like so:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// mock_trait!(
///     MockTaskManager,
///     max_threads(()) -> u32,
///     set_max_threads(u32) -> ()
/// );
///
/// # fn main() {
///     // only here to make `cargo test` happy
/// }
/// ```
///
/// Then the following code is generated:
///
/// ```
/// #[derive(Debug, Clone)]
/// struct MockTaskManager {
///     max_threads: double::Mock<(), u32>,
///     set_max_threads: double::Mock<(u32), ()>,
/// }
///
/// impl Default for MockTaskManager {
///     fn default() -> Self {
///         MockTaskManager {
///             max_threads: double::Mock::default(),
///             set_max_threads: double::Mock::default(),
///         }
///     }
/// }
/// ```
///
/// Note that just defining this macro is not enough. This macro is used to
/// generate the necessary boilerplate, but the generated struct *does not*
/// implement the desired `trait`. To do that, use `double`'s `mock_method`
/// macro.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate double;
///
/// trait TaskManager {
///    fn max_threads(&self) -> u32;
///    fn set_max_threads(&mut self, max_threads: u32);
/// }
///
/// mock_trait!(
///     MockTaskManager,
///     max_threads(()) -> u32,
///     set_max_threads(u32) -> ()
/// );
///
/// # fn main() {
/// let mock = MockTaskManager::default();
/// mock.max_threads.return_value(42u32);
/// assert_eq!(42, mock.max_threads.call(()));
/// mock.set_max_threads.call(9001u32);
/// assert!(mock.set_max_threads.called_with(9001u32));
/// # }
/// ```
#[macro_export]
macro_rules! mock_trait {
    ($mock_name:ident $(, $method:ident($($arg_type:ty),* ) -> $retval:ty )* ) => (
        #[derive(Debug, Clone)]
        struct $mock_name {
            $(
                $method: double::Mock<(($($arg_type),*)), $retval>
            ),*
        }

        impl Default for $mock_name {
            fn default() -> Self {
                $mock_name {
                    $(
                        $method: double::Mock::default()
                    ),*
                }
            }
        }
    );

    (pub $mock_name:ident $(, $method:ident($($arg_type:ty),* ) -> $retval:ty )* ) => (
        #[derive(Debug, Clone)]
        pub struct $mock_name {
            $(
                $method: double::Mock<(($($arg_type),*)), $retval>
            ),*
        }

        impl Default for $mock_name {
            fn default() -> Self {
                $mock_name {
                    $(
                        $method: double::Mock::default()
                    ),*
                }
            }
        }
    );
}

/// Macro that generates a mock implementation of a `trait` method.
///
/// This should be used to implement a `trait` on a mock type generated by
/// `double`'s `mock_trait` macro. If one has generated a mock `struct` using
/// `mock_trait`, then the actual *implementation* of the desired trait can be
/// auto-generated using `mock_method`, like so:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// trait TaskManager {
///    fn max_threads(&self) -> u32;
///    fn set_max_threads(&mut self, max_threads: u32);
/// }
///
/// mock_trait!(
///     MockTaskManager,
///     max_threads(()) -> u32,
///     set_max_threads(u32) -> ()
/// );
///
/// // Actually implement the trait that should be mocked
/// impl TaskManager for MockTaskManager {
///     mock_method!(max_threads(&self) -> u32);
///     mock_method!(set_max_threads(&mut self, max_threads: u32));
/// }
///
/// # fn main() {
/// let mut mock = MockTaskManager::default();
/// mock.max_threads.return_value(42u32);
/// assert_eq!(42, mock.max_threads());
/// assert!(mock.max_threads.called_with(()));
/// mock.set_max_threads(9001u32);
/// assert!(mock.set_max_threads.called_with(9001u32));
/// # }
/// ```
///
/// There are many different variants of `mock_method`. In total there are 12
/// variants. 8 variants provides a combination of the following:
///
/// 1. const method (`&self`) **or** mutable method (`&mut self`)
/// 2. return value (`fn foo(&self) -> bool`) **or** no return value (`fn foo(&self)`)
/// 3. automatically generated method body **or** custom method body
///
/// (1) allows both constant and mutable methods tobe mocked, like in the
/// `MockTaskManager` example above.
///
/// (2) is for convenience. It means one doesn't have to specify `-> ()`
/// explicitly for mocked methods that don't return values. This can also be
/// shown in the `MockTaskManager` example. Notice how the return type is not
/// specified when generating the `set_max_threads()` mock.
///
/// (3) is useful when the stored call arguments' types (defined by the
/// `mock_trait()` macro) are different to the mocked method. There are cases
/// where type differences in the stored args and the actual method args are
/// required. For example, suppose you had the following trait:
///
/// ```
/// trait TextStreamWriter {
///     fn write(text: &str);
/// }
/// ```
///
/// A mock can't _store_ received `text` arguments as `&str` because the mock
/// needs to the _own_ the given arguments (and `&str` is a non-owning
/// reference). Therefore, the mock trait has to be specified like so:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// trait TextStreamWriter {
///     fn write(&mut self, text: &str);
/// }
///
/// mock_trait!(
///     MockTextStreamWriter,
///     // have to use `String`, not `&str` here, since `&str` is a reference
///     write(String) -> ()
/// );
///
/// impl TextStreamWriter for MockTextStreamWriter {
///     mock_method!(write(&mut self, text: &str), self, {
///         // manually convert the reference to an owned `String` before
///         // passing it to the underlying mock object
///         self.write.call(text.to_owned())
///     });
/// }
/// # fn main() {
///     // only here to make `cargo test` happy
/// }
/// ```
///
/// Using variant (3) of `mock_method` means we specify the body of the
/// generated function manually. The custom body simply converts the `&str`
/// argument to an owned string and passes it into the underlying `write` `Mock`
/// object manually. (normally auto-generated bodies do this for you).
///
/// The name of the underlying mock object is always the same as the mocked
/// method's name.
///
/// `&str` parameters are common. It can be inconvenient haven't to manually
/// specify the body each time they appear. There are plans to add a macro to
/// generate a body that calls `to_owned()` automatically.
/// (TODO: implement the macro)
///
/// ### Type Parameters
///
/// There are an additional 4 variants to handle method type parameters
/// (e.g. `fn foo<T: Eq>(&self, a: &T)`). These variants allow one to generate
/// mock methods which take some generic type parameters.
///
/// For example, suppose one had a `Comparator` trait that was responsible for
/// comparing any two values in the program. It might look something like this:
///
/// ```
/// trait Comparator {
///    fn is_equal<T: Eq>(&self, a: &T, b: &T) -> bool;
/// }
/// ```
///
/// `T` can be multiple types. Currently, we cannot store call arguments that
/// have generic types in the underlying `Mock` objects. Therefore, one has to
/// convert the generic types to a different, common representation. One way
/// to get around this limitation is converting each generic type to a `String`.
/// e.g. for the `Comparator` trait:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// use std::string::ToString;
///
/// trait Comparator {
///    fn is_equal<T: Eq + ToString>(&self, a: &T, b: &T) -> bool;
/// }
///
/// mock_trait!(
///     MockComparator,
///     // store all passed in call args as strings
///     is_equal((String, String)) -> bool
/// );
///
/// impl Comparator for MockComparator {
///     mock_method!(is_equal<(T: Eq + ToString)>(&self, a: &T, b: &T) -> bool, self, {
///         // Convert both arguments to strings and manually pass to underlying
///         // mock object.
///         // Notice how the both arguments as passed as a single tuple. The
///         // underlying mock object always expects a single tuple.
///         self.is_equal.call((a.to_string(), b.to_string()))
///     });
/// }
/// # fn main() {
///     // only here to make `cargo test` happy
/// }
/// ```
///
/// If the `to_string` conversions for all `T` are not lossy, then our mock
/// expectations can be exact. If the `to_string` conversions _are_ lossy, then
/// this mechanism can still be used, providing all the properties of the passed
/// in objects are captured in the resultant `String`s.
///
/// This approach requires the writer to ensure the code under test adds the
/// `ToString` trait to the `trait`'s type argument constraints. This limitation
/// forces test writers to modify production code to use `double` for mocking.
///
/// Despite this, there is still value in using `double` for mocking generic
/// methods with type arguments. Despite adding boilerplate to production code
/// and manually implementing mock method bodies being cumbersome, the value add
/// is that all argument matching, expectations, calling test functions, etc.
/// are all still handled by `double`. Arguably, reimplenting those features is
/// more cumbersome than the small amount of boilerplate required to mock
/// methods with type arguments.
#[macro_export]
macro_rules! mock_method {

    // immutable, no return value, no type parameter, no body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*)) => (
        fn $method(&self $(,$arg_name: $arg_type)*) {
            self.$method.call(($($arg_name.clone()),*))
        }
    );

    // immutable, no return value, no type parameter, body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*), $sel:ident, $body:tt ) => (
        fn $method(&$sel $(,$arg_name: $arg_type)*) $body
    );

    // immutable, no return value, type parameter, no body
    // not provided, since type parameters need a custom body 99% of the time

    // immutable, no return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&self $(,$arg_name:ident: $arg_type:ty)*),
        $sel:ident, $body:tt) => (
            fn $method<$($type_params)*>(&$sel $(,$arg_name: $arg_type)*) $body
    );

    // immutable, return value, no type parameter, no body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty ) => (
        fn $method(&self $(,$arg_name: $arg_type)*) -> $retval {
            self.$method.call(($($arg_name.clone()),*))
        }
    );

    // immutable, return value, no type parameter, body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty, $sel:ident, $body:tt ) => (
        fn $method(&$sel $(,$arg_name: $arg_type)*) -> $retval $body
    );

    // immutable, return value, type parameter, no body
    // not provided, since type parameters need a custom body 99% of the time

    // immutable, return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&self $(,$arg_name:ident: $arg_type:ty)*)
        -> $retval:ty, $sel:ident, $body:tt ) => (
            fn $method<$($type_params)*>(&$sel $(,$arg_name: $arg_type)*) -> $retval $body
    );

    // mutable, no return value, no type parameter, no body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*)) => (
        fn $method(&mut self $(,$arg_name: $arg_type),*) {
            self.$method.call(($($arg_name.clone()),*))
        }
    );

    // mutable, no return value, no type parameter, body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*), $sel:ident, $body:tt ) => (
        fn $method(&mut $sel $(,$arg_name: $arg_type)*) $body
    );

    // mutable, no return value, type parameter, no body
    // not provided, since type parameters need a custom body 99% of the time

    // mutable, no return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&mut self $(,$arg_name:ident: $arg_type:ty)*),
        $sel:ident, $body:tt) => (
            fn $method<$($type_params)*>(&mut $sel $(,$arg_name: $arg_type)*) $body
    );

    // mutable, return value, no type parameter, no body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty ) => (
        fn $method(&mut self $(,$arg_name: $arg_type),*) -> $retval {
            self.$method.call(($($arg_name.clone()),*))
        }
    );

    // mutable, return value, no type parameter, body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty, $sel:ident, $body:tt ) => (
        fn $method(&mut $sel $(,$arg_name: $arg_type)*) -> $retval $body
    );

    // mutable, return value, type parameter, no body
    // not provided, since type parameters need a custom body 99% of the time

    // mutable, return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&mut self $(,$arg_name:ident: $arg_type:ty)*)
        -> $retval:ty, $sel:ident, $body:tt ) => (
            fn $method<$($type_params)*>(&mut $sel $(,$arg_name: $arg_type)*) -> $retval $body
    );

}
<|endoftext|>


<commit_before>/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
///
/// # Example
///
/// ```
/// # use anyhow::{bail, Result};
/// #
/// # fn has_permission(user: usize, resource: usize) -> bool {
/// #     true
/// # }
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #     let resource = 0;
/// #
/// if !has_permission(user, resource) {
///     bail!("permission denied for accessing {}", resource);
/// }
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{bail, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// if depth > MAX_DEPTH {
///     bail!(ScienceError::RecursionLimitExceeded);
/// }
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! bail {
    ($msg:literal $(,)?) => {
        return $crate::private::Err($crate::anyhow!($msg));
    };
    ($err:expr $(,)?) => {
        return $crate::private::Err($crate::anyhow!($err));
    };
    ($fmt:expr, $($arg:tt)*) => {
        return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
    };
}

/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`.
///
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
/// rather than panicking.
///
/// # Example
///
/// ```
/// # use anyhow::{ensure, Result};
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{ensure, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
    ($cond:expr, $msg:literal $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($msg));
        }
    };
    ($cond:expr, $err:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($err));
        }
    };
    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
        }
    };
}

/// Construct an ad-hoc error from a string.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
/// string with arguments. It also can take any custom type which implements
/// `Debug` and `Display`.
///
/// # Example
///
/// ```
/// # type V = ();
/// #
/// use anyhow::{anyhow, Result};
///
/// fn lookup(key: &str) -> Result<V> {
///     if key.len() != 16 {
///         return Err(anyhow!("key length must be 16 characters, got {:?}", key));
///     }
///
///     // ...
///     # Ok(())
/// }
/// ```
#[macro_export]
macro_rules! anyhow {
    ($msg:literal $(,)?) => {
        // Handle $:literal as a special case to make cargo-expanded code more
        // concise in the common case.
        $crate::private::new_adhoc($msg)
    };
    ($err:expr $(,)?) => ({
        use $crate::private::kind::*;
        let error = $err;
        (&error).anyhow_kind().new(error)
    });
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}
<commit_msg>Indicate that `anyhow!` is not just for strings<commit_after>/// Return early with an error.
///
/// This macro is equivalent to `return Err(From::from($err))`.
///
/// # Example
///
/// ```
/// # use anyhow::{bail, Result};
/// #
/// # fn has_permission(user: usize, resource: usize) -> bool {
/// #     true
/// # }
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #     let resource = 0;
/// #
/// if !has_permission(user, resource) {
///     bail!("permission denied for accessing {}", resource);
/// }
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{bail, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// if depth > MAX_DEPTH {
///     bail!(ScienceError::RecursionLimitExceeded);
/// }
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! bail {
    ($msg:literal $(,)?) => {
        return $crate::private::Err($crate::anyhow!($msg));
    };
    ($err:expr $(,)?) => {
        return $crate::private::Err($crate::anyhow!($err));
    };
    ($fmt:expr, $($arg:tt)*) => {
        return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
    };
}

/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`.
///
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
/// rather than panicking.
///
/// # Example
///
/// ```
/// # use anyhow::{ensure, Result};
/// #
/// # fn main() -> Result<()> {
/// #     let user = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// #     Ok(())
/// # }
/// ```
///
/// ```
/// # use anyhow::{ensure, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
///     #[error("recursion limit exceeded")]
///     RecursionLimitExceeded,
///     # #[error("...")]
///     # More = (stringify! {
///     ...
///     # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// #     let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// #     Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
    ($cond:expr, $msg:literal $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($msg));
        }
    };
    ($cond:expr, $err:expr $(,)?) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($err));
        }
    };
    ($cond:expr, $fmt:expr, $($arg:tt)*) => {
        if !$cond {
            return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
        }
    };
}

/// Construct an ad-hoc error from a string or existing non-`anyhow` error
/// value.
///
/// This evaluates to an `Error`. It can take either just a string, or a format
/// string with arguments. It also can take any custom type which implements
/// `Debug` and `Display`.
///
/// # Example
///
/// ```
/// # type V = ();
/// #
/// use anyhow::{anyhow, Result};
///
/// fn lookup(key: &str) -> Result<V> {
///     if key.len() != 16 {
///         return Err(anyhow!("key length must be 16 characters, got {:?}", key));
///     }
///
///     // ...
///     # Ok(())
/// }
/// ```
#[macro_export]
macro_rules! anyhow {
    ($msg:literal $(,)?) => {
        // Handle $:literal as a special case to make cargo-expanded code more
        // concise in the common case.
        $crate::private::new_adhoc($msg)
    };
    ($err:expr $(,)?) => ({
        use $crate::private::kind::*;
        let error = $err;
        (&error).anyhow_kind().new(error)
    });
    ($fmt:expr, $($arg:tt)*) => {
        $crate::private::new_adhoc(format!($fmt, $($arg)*))
    };
}
<|endoftext|>


<commit_before>macro_rules! println_color_category(
    ($color:expr, $text:tt, $($arg:tt)*) => {{
        let mut t = try!(term::stderr().ok_or(term::Error::NotSupported));
        try!(t.fg($color));
        if !$text.is_empty() {
            try!(write!(t, "[ {} ] ", $text));
        }
        try!(writeln!(t, $($arg)*));
        try!(t.reset());
    }}
);

macro_rules! println_info(
    ($($arg:tt)*) => {{
        println_color_category!(term::color::YELLOW, "INFO", $($arg)*);
    }}
);

macro_rules! println_ok(
    ($($arg:tt)*) => {{
        println_color_category!(term::color::GREEN, "OKAY", $($arg)*);
    }}
);
<commit_msg>Removed unnecessary if around literals<commit_after>macro_rules! println_color_category(
    ($color:expr, $text:tt, $($arg:tt)*) => {{
        let mut t = try!(term::stderr().ok_or(term::Error::NotSupported));
        try!(t.fg($color));
        try!(write!(t, "[ {} ] ", $text));
        try!(writeln!(t, $($arg)*));
        try!(t.reset());
    }}
);

macro_rules! println_info(
    ($($arg:tt)*) => {{
        println_color_category!(term::color::YELLOW, "INFO", $($arg)*);
    }}
);

macro_rules! println_ok(
    ($($arg:tt)*) => {{
        println_color_category!(term::color::GREEN, "OKAY", $($arg)*);
    }}
);
<|endoftext|>


<commit_before>use std::string::{String};
use std::sync::{Arc};
use std::ops::{Add, Mul};
use math::{Vec2};
use node::{Node, Graph};
use tensor::{Tensor};

fn operation<T>(vec: Vec<Tensor<T>>) -> Tensor<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    &vec[0] + &vec[1]
}

fn operation_prime<T>(gradient: &Tensor<T>, _: Vec<&Tensor<T>>) -> Vec<Tensor<T>> where T: Mul<Output=T> + Add<Output=T> + Copy {
    vec![gradient.clone(), gradient.clone()]
}

fn calc_dim(dims: Vec<Vec2>) -> Vec2 {
    let Vec2(x1, y1) = dims[0];
    let Vec2(x2, y2) = dims[1];
    assert_eq!(x1, x2);
    assert_eq!(y1, y2);
    dims[0]
}

pub fn add<'a, T>(node_id: String, a: Arc<Graph<T>>, b: Arc<Graph<T>>) -> Node<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    Node::new(node_id, operation, operation_prime, vec![a, b], calc_dim)
}
<commit_msg>transformation add partial<commit_after>use std::string::{String};
use std::sync::{Arc};
use std::ops::{Add, Mul};
use math::{Vec2};
use node::{Node, Graph};
use tensor::{Tensor};

fn operation<T>(vec: Vec<Tensor<T>>) -> Tensor<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    let Vec2(x1, _) = vec[0].dim();
    let Vec2(x2, _) = vec[1].dim();
    if x1 != 1 && x2 == 1 {

    } else {
        &vec[0] + &vec[1]
    }

}

fn operation_prime<T>(gradient: &Tensor<T>, _: Vec<&Tensor<T>>) -> Vec<Tensor<T>> where T: Mul<Output=T> + Add<Output=T> + Copy {
    vec![gradient.clone(), gradient.clone()]
}

fn calc_dim(dims: Vec<Vec2>) -> Vec2 {
    let Vec2(x1, y1) = dims[0];
    let Vec2(x2, y2) = dims[1];
    assert!(x1 == 0 && x2 == 1 || x1 == x2);
    assert_eq!(y1, y2);
    dims[0]
}

pub fn add<T>(node_id: String, a: Arc<Graph<T>>, b: Arc<Graph<T>>) -> Node<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    Node::new(node_id, operation, operation_prime, vec![a, b], calc_dim)
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate encoding;

use std::borrow::Cow;
use std::default::Default;
use std::error;
use std::fmt;
use std::io;

use self::byteorder::{ByteOrder, BigEndian, LittleEndian};
use self::encoding::label::encoding_from_whatwg_label;
use self::encoding::types::EncodingRef;
use self::encoding::types::DecoderTrap::Strict;

use super::{Catalog, Message};
use metadata::parse_metadata;

#[allow(non_upper_case_globals)]
static utf8_encoding: EncodingRef = &encoding::codec::utf_8::UTF8Encoding;

/// Represents an error encountered while parsing an MO file.
#[derive(Debug)]
pub enum Error {
    /// An incorrect magic number has been encountered
    BadMagic,
    /// An invalid byte sequence for the given encoding has been encountered
    DecodingError,
    /// An unexpected EOF occured
    Eof,
    /// An I/O error occured
    Io(io::Error),
    /// Incorrect syntax encountered while parsing the meta information
    MalformedMetadata,
    /// Meta information string was not the first string in the catalog
    MisplacedMetadata,
    /// An unknown encoding was specified in the metadata
    UnknownEncoding,
}
// Can not use use `Error::*` as per this issue:
// (https://github.com/rust-lang/rust/issues/4865)
use Error::{BadMagic, DecodingError, Eof, Io, MalformedMetadata, MisplacedMetadata,
            UnknownEncoding};

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            BadMagic => "bad magic number",
            DecodingError => "invalid byte sequence in a string",
            Eof => "unxpected end of file",
            Io(ref err) => err.description(),
            MalformedMetadata => "metadata syntax error",
            MisplacedMetadata => "misplaced metadata",
            UnknownEncoding => "unknown encoding specified",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let self_err: &error::Error = self;
        write!(fmt, "{}", self_err.description())
    }
}

impl From<io::Error> for Error {
    fn from(inner: io::Error) -> Error {
        Io(inner)
    }
}

impl From<Cow<'static, str>> for Error {
    fn from(_: Cow<'static, str>) -> Error {
        DecodingError
    }
}

/// ParseOptions allows setting options for parsing MO catalogs.
///
/// # Examples
/// ```ignore
/// use std::fs::File;
///
/// extern crate encoding;
/// use encoding::all::ISO_8859_1;
///
/// let file = File::open("french.mo").unwrap();
/// let catalog = ParseOptions::new().force_encoding(ISO_8859_1).parse(file).unwrap();
/// ```
#[allow(missing_debug_implementations)]
#[derive(Default)]
pub struct ParseOptions {
    force_encoding: Option<EncodingRef>,
    force_plural: Option<Box<Fn(u64) -> usize + 'static>>,
}

impl ParseOptions {
    /// Returns a new instance of ParseOptions with default options.
    pub fn new() -> Self {
        Default::default()
    }

    /// Tries to parse the catalog from the given reader using the specified options.
    pub fn parse<R: io::Read>(&self, reader: R) -> Result<Catalog, Error> {
        parse_catalog(reader, self)
    }

    /// Forces a use of a specific encoding
    /// when parsing strings from a catalog.
    /// If this option is not enabled,
    /// the parser tries to use the encoding specified in the metadata
    /// or UTF-8 if metadata is non-existent.
    pub fn force_encoding(&mut self, encoding: EncodingRef) -> &mut Self {
        self.force_encoding = Some(encoding);
        self
    }

    /// Forces a use of the given plural formula
    /// for deciding the proper plural form for a message.
    /// If this option is not enabled,
    /// the parser tries to use the plural formula
    /// specified in the catalog,
    /// falling back on `n != 1`
    /// in case it fails to find or parse one.
    pub fn force_plural<T: Fn(u64) -> usize + 'static>(&mut self, plural: T) -> &mut Self {
        self.force_plural = Some(Box::new(plural));
        self
    }
}

/// According to the given magic number of a MO file,
/// returns the function which reads a `u32` in the relevant endianness.
fn get_read_u32_fn(magic: &[u8]) -> Option<fn(&[u8]) -> u32> {
    if magic == [0xde, 0x12, 0x04, 0x95] {
        Some(LittleEndian::read_u32)
    } else if magic == [0x95, 0x04, 0x12, 0xde] {
        Some(BigEndian::read_u32)
    } else {
        None
    }
}

pub fn parse_catalog<R: io::Read>(mut file: R, opts: &ParseOptions) -> Result<Catalog, Error> {
    let mut contents = vec![];
    let n = try!(file.read_to_end(&mut contents));
    if n < 28 {
        return Err(Eof);
    }

    let read_u32 = match get_read_u32_fn(&contents[0..4]) {
        Some(f) => f,
        None => return Err(BadMagic),
    };

    // ignore hashing tables (bytes at 20..28)
    let num_strings = read_u32(&contents[8..12]) as usize;
    let mut off_otable = read_u32(&contents[12..16]) as usize;
    let mut off_ttable = read_u32(&contents[16..20]) as usize;
    if n < off_otable || n < off_ttable {
        return Err(Eof);
    }

    let mut catalog = Catalog::new();
    let mut encoding = opts.force_encoding.unwrap_or(utf8_encoding);

    for i in 0..num_strings {
        let id;
        let context;
        let translated: Vec<String>;
        // Parse the original string
        {
            if n < off_otable + 8 {
                return Err(Eof);
            }
            let len = read_u32(&contents[off_otable..off_otable + 4]) as usize;
            let off = read_u32(&contents[off_otable + 4..off_otable + 8]) as usize;
            // +1 compensates for the ending NUL byte which is not included in length
            if n < off + len + 1 {
                return Err(Eof);
            }
            let mut original = &contents[off..off + len + 1];
            // check for context
            context = match original.iter().position(|x| *x == 4) {
                Some(idx) => {
                    let ctx = &original[..idx];
                    original = &original[idx + 1..];
                    Some(try!(encoding.decode(ctx, Strict)))
                }
                None => None,
            };
            // extract msg_id singular, ignoring the plural
            id = match original.iter().position(|x| *x == 0).map(|i| &original[..i]) {
                Some(b) => try!(encoding.decode(b, Strict)),
                None => return Err(Eof),
            };
            if id == "" && i != 0 {
                return Err(MisplacedMetadata);
            }
        }

        // Parse the translation strings
        {
            if n < off_ttable + 8 {
                return Err(Eof);
            }
            let len = read_u32(&contents[off_ttable..off_ttable + 4]) as usize;
            let off = read_u32(&contents[off_ttable + 4..off_ttable + 8]) as usize;
            // +1 compensates for the ending NUL byte which is not included in length
            if n < off + len + 1 {
                return Err(Eof);
            }
            translated = try!((&contents[off..off + len])
                                  .split(|x| *x == 0)
                                  .map(|b| encoding.decode(b, Strict))
                                  .collect::<Result<Vec<_>, _>>());
            if id == "" {
                let map = parse_metadata(&*translated[0]).unwrap();
                if let (Some(c), None) = (map.charset(), opts.force_encoding) {
                    encoding = match encoding_from_whatwg_label(c) {
                        Some(enc_ref) => enc_ref,
                        None => return Err(UnknownEncoding),
                    }
                }
            }
        }

        catalog.insert(Message::new(id, context, translated));

        off_otable += 8;
        off_ttable += 8;
    }

    Ok(catalog)
}

#[test]
fn test_get_read_u32_fn() {
    use std::mem;

    assert!(get_read_u32_fn(&[]).is_none());
    assert!(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95, 0x00]).is_none());

    {
        let le_ptr: *const ();
        let ret_ptr;
        unsafe {
            le_ptr = mem::transmute(LittleEndian::read_u32 as usize);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95]).unwrap());
        }
        assert_eq!(le_ptr, ret_ptr);
    }

    {
        let be_ptr: *const ();
        let ret_ptr;
        unsafe {
            be_ptr = mem::transmute(BigEndian::read_u32 as usize);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0x95, 0x04, 0x12, 0xde]).unwrap());
        }
        assert_eq!(be_ptr, ret_ptr);
    }
}

#[test]
fn test_parse_catalog() {
    macro_rules! assert_variant {
        ($value:expr, $variant:path) => {
            match $value {
                $variant => (),
                _ => panic!("Expected {:?}, got {:?}", $variant, $value),
            }
        };
    }

    let fluff = [0; 24]; // zeros to pad our magic test cases to satisfy the length requirements

    {
        let mut reader = vec![1u8, 2, 3];
        reader.extend(fluff.iter().cloned());
        let err = parse_catalog(&reader[..], &ParseOptions::new()).unwrap_err();
        assert_variant!(err, Eof);
    }

    {
        let mut reader = vec![1u8, 2, 3, 4];
        reader.extend(fluff.iter().cloned());
        let err = parse_catalog(&reader[..], &ParseOptions::new()).unwrap_err();
        assert_variant!(err, BadMagic);
    }

    {
        let mut reader = vec![0x95, 0x04, 0x12, 0xde];
        reader.extend(fluff.iter().cloned());
        assert!(parse_catalog(&reader[..], &ParseOptions::new()).is_ok());
    }

    {
        let mut reader = vec![0xde, 0x12, 0x04, 0x95];
        reader.extend(fluff.iter().cloned());
        assert!(parse_catalog(&reader[..], &ParseOptions::new()).is_ok());
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/1.mo");
        let catalog = parse_catalog(reader, &ParseOptions::new()).unwrap();
        assert_eq!(catalog.strings.len(), 1);
        assert_eq!(catalog.strings["this is context\x04Text"],
                   Message::new("Text", Some("this is context"), vec!["Tekstas", "Tekstai"]));
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/2.mo");
        let catalog = parse_catalog(reader, &ParseOptions::new()).unwrap();
        assert_eq!(catalog.strings.len(), 2);
        assert_eq!(catalog.strings["Image"],
                   Message::new("Image", None, vec!["Nuotrauka", "Nuotraukos"]));
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/invalid_utf8.mo");
        let err = parse_catalog(reader, &ParseOptions::new()).unwrap_err();
        assert_variant!(err, DecodingError);
    }

    // cp1257_meta
    {
        let reader: &[u8] = include_bytes!("../test_cases/cp1257_meta.mo");
        let catalog = parse_catalog(reader, &ParseOptions::new()).unwrap();
        assert_eq!(catalog.gettext("Garlic"), "Česnakas");
    }

    // cp1257_forced
    {
        let reader: &[u8] = include_bytes!("../test_cases/cp1257_forced.mo");
        for enc_name in &["cp1257", "windows-1257", "x-cp1257"] {
            let encoding = encoding_from_whatwg_label(enc_name).unwrap();
            let catalog = ParseOptions::new().force_encoding(encoding).parse(reader).unwrap();
            assert_eq!(catalog.gettext("Garlic"), "Česnakas");
        }
    }
}
<commit_msg>Change the usage of ParseOptions<commit_after>extern crate byteorder;
extern crate encoding;

use std::borrow::Cow;
use std::default::Default;
use std::error;
use std::fmt;
use std::io;

use self::byteorder::{ByteOrder, BigEndian, LittleEndian};
use self::encoding::label::encoding_from_whatwg_label;
use self::encoding::types::EncodingRef;
use self::encoding::types::DecoderTrap::Strict;

use super::{Catalog, Message};
use metadata::parse_metadata;

#[allow(non_upper_case_globals)]
static utf8_encoding: EncodingRef = &encoding::codec::utf_8::UTF8Encoding;

/// Represents an error encountered while parsing an MO file.
#[derive(Debug)]
pub enum Error {
    /// An incorrect magic number has been encountered
    BadMagic,
    /// An invalid byte sequence for the given encoding has been encountered
    DecodingError,
    /// An unexpected EOF occured
    Eof,
    /// An I/O error occured
    Io(io::Error),
    /// Incorrect syntax encountered while parsing the meta information
    MalformedMetadata,
    /// Meta information string was not the first string in the catalog
    MisplacedMetadata,
    /// An unknown encoding was specified in the metadata
    UnknownEncoding,
}
// Can not use use `Error::*` as per this issue:
// (https://github.com/rust-lang/rust/issues/4865)
use Error::{BadMagic, DecodingError, Eof, Io, MalformedMetadata, MisplacedMetadata,
            UnknownEncoding};

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            BadMagic => "bad magic number",
            DecodingError => "invalid byte sequence in a string",
            Eof => "unxpected end of file",
            Io(ref err) => err.description(),
            MalformedMetadata => "metadata syntax error",
            MisplacedMetadata => "misplaced metadata",
            UnknownEncoding => "unknown encoding specified",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let self_err: &error::Error = self;
        write!(fmt, "{}", self_err.description())
    }
}

impl From<io::Error> for Error {
    fn from(inner: io::Error) -> Error {
        Io(inner)
    }
}

impl From<Cow<'static, str>> for Error {
    fn from(_: Cow<'static, str>) -> Error {
        DecodingError
    }
}

/// ParseOptions allows setting options for parsing MO catalogs.
///
/// # Examples
/// ```ignore
/// use std::fs::File;
///
/// extern crate encoding;
/// use encoding::all::ISO_8859_1;
///
/// let file = File::open("french.mo").unwrap();
/// let catalog = ParseOptions::new().force_encoding(ISO_8859_1).parse(file).unwrap();
/// ```
#[allow(missing_debug_implementations)]
#[derive(Default)]
pub struct ParseOptions {
    force_encoding: Option<EncodingRef>,
    force_plural: Option<Box<Fn(u64) -> usize + 'static>>,
}

impl ParseOptions {
    /// Returns a new instance of ParseOptions with default options.
    pub fn new() -> Self {
        Default::default()
    }

    /// Tries to parse the catalog from the given reader using the specified options.
    pub fn parse<R: io::Read>(self, reader: R) -> Result<Catalog, Error> {
        parse_catalog(reader, self)
    }

    /// Forces a use of a specific encoding
    /// when parsing strings from a catalog.
    /// If this option is not enabled,
    /// the parser tries to use the encoding specified in the metadata
    /// or UTF-8 if metadata is non-existent.
    pub fn force_encoding(mut self, encoding: EncodingRef) -> Self {
        self.force_encoding = Some(encoding);
        self
    }

    /// Forces a use of the given plural formula
    /// for deciding the proper plural form for a message.
    /// If this option is not enabled,
    /// the parser tries to use the plural formula
    /// specified in the catalog,
    /// falling back on `n != 1`
    /// in case it fails to find or parse one.
    pub fn force_plural<T: Fn(u64) -> usize + 'static>(mut self, plural: T) -> Self {
        self.force_plural = Some(Box::new(plural));
        self
    }
}

/// According to the given magic number of a MO file,
/// returns the function which reads a `u32` in the relevant endianness.
fn get_read_u32_fn(magic: &[u8]) -> Option<fn(&[u8]) -> u32> {
    if magic == [0xde, 0x12, 0x04, 0x95] {
        Some(LittleEndian::read_u32)
    } else if magic == [0x95, 0x04, 0x12, 0xde] {
        Some(BigEndian::read_u32)
    } else {
        None
    }
}

pub fn parse_catalog<R: io::Read>(mut file: R, opts: ParseOptions) -> Result<Catalog, Error> {
    let mut contents = vec![];
    let n = try!(file.read_to_end(&mut contents));
    if n < 28 {
        return Err(Eof);
    }

    let read_u32 = match get_read_u32_fn(&contents[0..4]) {
        Some(f) => f,
        None => return Err(BadMagic),
    };

    // ignore hashing tables (bytes at 20..28)
    let num_strings = read_u32(&contents[8..12]) as usize;
    let mut off_otable = read_u32(&contents[12..16]) as usize;
    let mut off_ttable = read_u32(&contents[16..20]) as usize;
    if n < off_otable || n < off_ttable {
        return Err(Eof);
    }

    let mut catalog = Catalog::new();
    let mut encoding = opts.force_encoding.unwrap_or(utf8_encoding);

    for i in 0..num_strings {
        let id;
        let context;
        let translated: Vec<String>;
        // Parse the original string
        {
            if n < off_otable + 8 {
                return Err(Eof);
            }
            let len = read_u32(&contents[off_otable..off_otable + 4]) as usize;
            let off = read_u32(&contents[off_otable + 4..off_otable + 8]) as usize;
            // +1 compensates for the ending NUL byte which is not included in length
            if n < off + len + 1 {
                return Err(Eof);
            }
            let mut original = &contents[off..off + len + 1];
            // check for context
            context = match original.iter().position(|x| *x == 4) {
                Some(idx) => {
                    let ctx = &original[..idx];
                    original = &original[idx + 1..];
                    Some(try!(encoding.decode(ctx, Strict)))
                }
                None => None,
            };
            // extract msg_id singular, ignoring the plural
            id = match original.iter().position(|x| *x == 0).map(|i| &original[..i]) {
                Some(b) => try!(encoding.decode(b, Strict)),
                None => return Err(Eof),
            };
            if id == "" && i != 0 {
                return Err(MisplacedMetadata);
            }
        }

        // Parse the translation strings
        {
            if n < off_ttable + 8 {
                return Err(Eof);
            }
            let len = read_u32(&contents[off_ttable..off_ttable + 4]) as usize;
            let off = read_u32(&contents[off_ttable + 4..off_ttable + 8]) as usize;
            // +1 compensates for the ending NUL byte which is not included in length
            if n < off + len + 1 {
                return Err(Eof);
            }
            translated = try!((&contents[off..off + len])
                                  .split(|x| *x == 0)
                                  .map(|b| encoding.decode(b, Strict))
                                  .collect::<Result<Vec<_>, _>>());
            if id == "" {
                let map = parse_metadata(&*translated[0]).unwrap();
                if let (Some(c), None) = (map.charset(), opts.force_encoding) {
                    encoding = match encoding_from_whatwg_label(c) {
                        Some(enc_ref) => enc_ref,
                        None => return Err(UnknownEncoding),
                    }
                }
            }
        }

        catalog.insert(Message::new(id, context, translated));

        off_otable += 8;
        off_ttable += 8;
    }

    Ok(catalog)
}

#[test]
fn test_get_read_u32_fn() {
    use std::mem;

    assert!(get_read_u32_fn(&[]).is_none());
    assert!(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95, 0x00]).is_none());

    {
        let le_ptr: *const ();
        let ret_ptr;
        unsafe {
            le_ptr = mem::transmute(LittleEndian::read_u32 as usize);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95]).unwrap());
        }
        assert_eq!(le_ptr, ret_ptr);
    }

    {
        let be_ptr: *const ();
        let ret_ptr;
        unsafe {
            be_ptr = mem::transmute(BigEndian::read_u32 as usize);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0x95, 0x04, 0x12, 0xde]).unwrap());
        }
        assert_eq!(be_ptr, ret_ptr);
    }
}

#[test]
fn test_parse_catalog() {
    macro_rules! assert_variant {
        ($value:expr, $variant:path) => {
            match $value {
                $variant => (),
                _ => panic!("Expected {:?}, got {:?}", $variant, $value),
            }
        };
    }

    let fluff = [0; 24]; // zeros to pad our magic test cases to satisfy the length requirements

    {
        let mut reader = vec![1u8, 2, 3];
        reader.extend(fluff.iter().cloned());
        let err = parse_catalog(&reader[..], ParseOptions::new()).unwrap_err();
        assert_variant!(err, Eof);
    }

    {
        let mut reader = vec![1u8, 2, 3, 4];
        reader.extend(fluff.iter().cloned());
        let err = parse_catalog(&reader[..], ParseOptions::new()).unwrap_err();
        assert_variant!(err, BadMagic);
    }

    {
        let mut reader = vec![0x95, 0x04, 0x12, 0xde];
        reader.extend(fluff.iter().cloned());
        assert!(parse_catalog(&reader[..], ParseOptions::new()).is_ok());
    }

    {
        let mut reader = vec![0xde, 0x12, 0x04, 0x95];
        reader.extend(fluff.iter().cloned());
        assert!(parse_catalog(&reader[..], ParseOptions::new()).is_ok());
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/1.mo");
        let catalog = parse_catalog(reader, ParseOptions::new()).unwrap();
        assert_eq!(catalog.strings.len(), 1);
        assert_eq!(catalog.strings["this is context\x04Text"],
                   Message::new("Text", Some("this is context"), vec!["Tekstas", "Tekstai"]));
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/2.mo");
        let catalog = parse_catalog(reader, ParseOptions::new()).unwrap();
        assert_eq!(catalog.strings.len(), 2);
        assert_eq!(catalog.strings["Image"],
                   Message::new("Image", None, vec!["Nuotrauka", "Nuotraukos"]));
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/invalid_utf8.mo");
        let err = parse_catalog(reader, ParseOptions::new()).unwrap_err();
        assert_variant!(err, DecodingError);
    }

    // cp1257_meta
    {
        let reader: &[u8] = include_bytes!("../test_cases/cp1257_meta.mo");
        let catalog = parse_catalog(reader, ParseOptions::new()).unwrap();
        assert_eq!(catalog.gettext("Garlic"), "Česnakas");
    }

    // cp1257_forced
    {
        let reader: &[u8] = include_bytes!("../test_cases/cp1257_forced.mo");
        for enc_name in &["cp1257", "windows-1257", "x-cp1257"] {
            let encoding = encoding_from_whatwg_label(enc_name).unwrap();
            let catalog = ParseOptions::new().force_encoding(encoding).parse(reader).unwrap();
            assert_eq!(catalog.gettext("Garlic"), "Česnakas");
        }
    }
}
<|endoftext|>


<commit_before>//! Syntactic analysis of programs.

use lexer::Token;
use lexer::Tokens;

///
/// Instructions.
///
#[derive(Debug, PartialEq)]
pub enum Instruction {
    /// Move to the next cell (`>`).
    Next,
    /// Move to the previous cell (`<`
    Prev,
    /// Increment the current cell (`+`).
    Inc,
    /// Decrement the current cell (`-`).
    Dec,
    /// Read a byte from the input into the current cell (`,`).
    Read,
    /// Write a byte from the current cell into the output (`,`).
    Write,
    /// Start of a loop ending on the given index (`[`).
    LoopStart(usize),
    /// End of a loop starting on the given index (`[`).
    LoopEnd(usize),
}

/// A vector of instructions.
pub type Instructions = Vec<Instruction>;

/// An internal stack of opened loop indexes that need to be closed before
/// parsing is finished.
type LoopStack = Vec<usize>;

///
/// Parses the given vector of tokens into a vector of instructions.
///
/// # Arguments
///
/// * `tokens` - Tokens representing a program.
///
pub fn parse(tokens: &Tokens) -> Result<Instructions, String> {
    let mut instructions = Instructions::with_capacity(tokens.len());
    let mut loop_stack = LoopStack::new();
    for (i, token) in tokens.iter().enumerate() {
        match *token {
            Token::Next => instructions.push(Instruction::Next),
            Token::Prev => instructions.push(Instruction::Prev),
            Token::Inc => instructions.push(Instruction::Inc),
            Token::Dec => instructions.push(Instruction::Dec),
            Token::Read => instructions.push(Instruction::Read),
            Token::Write => instructions.push(Instruction::Write),
            Token::LoopStart =>
                try!(handle_loop_start(&mut instructions, &mut loop_stack, i)),
            Token::LoopEnd =>
                try!(handle_loop_end(&mut instructions, &mut loop_stack, i)),
        }
    }
    try!(ensure_all_loops_have_ended(&loop_stack));
    Ok(instructions)
}

fn handle_loop_start(instructions: &mut Instructions,
                     loop_stack: &mut LoopStack,
                     i: usize)
                     -> Result<(), String> {
    // We don't know the target yet, so pass 0. It will be updated later when
    // we reach the target.
    instructions.push(Instruction::LoopStart(0));
    loop_stack.push(i);
    Ok(())
}

fn handle_loop_end(instructions: &mut Instructions,
                   loop_stack: &mut LoopStack,
                   i: usize)
                   -> Result<(), String> {
    let target = match loop_stack.pop() {
        Some(target) => target,
        None => {
            return Err(
                format!("missing start of a loop ended at index {}", i)
            );
        }
    };
    instructions.push(Instruction::LoopEnd(target));
    // Update the index of the target in the loop start because it was
    // initialized to zero.
    instructions[target] = Instruction::LoopStart(i);
    Ok(())
}

fn ensure_all_loops_have_ended(loop_stack: &LoopStack) -> Result<(), String> {
    if !loop_stack.is_empty() {
        return Err(
            format!(
                "missing end of a loop started at index {}",
                loop_stack.last().unwrap()
            )
        );
    }
    Ok(())
}

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

    #[test]
    fn test_parse_returns_empty_vec_when_there_are_no_tokens() {
        assert_eq!(parse(&vec![]).unwrap(), vec![]);
    }

    #[test]
    fn test_parse_correctly_parses_infinite_loop() {
        // []
        let tokens = vec![
            Token::LoopStart,
            Token::LoopEnd,
        ];
        let expected_result = Ok(vec![
            Instruction::LoopStart(1),
            Instruction::LoopEnd(0),
        ]);
        assert_eq!(parse(&tokens), expected_result);
    }

    #[test]
    fn test_parse_correctly_parses_valid_program() {
        // [->+<,]
        let tokens = vec![
            Token::LoopStart,
            Token::Dec,
            Token::Next,
            Token::Inc,
            Token::Prev,
            Token::Read,
            Token::LoopEnd,
        ];
        let expected_result = Ok(vec![
            Instruction::LoopStart(6),
            Instruction::Dec,
            Instruction::Next,
            Instruction::Inc,
            Instruction::Prev,
            Instruction::Read,
            Instruction::LoopEnd(0),
        ]);
        assert_eq!(parse(&tokens), expected_result);
    }

    #[test]
    fn test_parse_returns_error_when_missing_loop_end() {
        assert_eq!(
            parse(&vec![Token::LoopStart]),
            Err("missing end of a loop started at index 0".to_string())
        );
    }

    #[test]
    fn test_parse_returns_error_when_missing_loop_start() {
        assert_eq!(
            parse(&vec![Token::LoopEnd]),
            Err("missing start of a loop ended at index 0".to_string())
        );
    }
}
<commit_msg>Simplify ensure_all_loops_have_ended().<commit_after>//! Syntactic analysis of programs.

use lexer::Token;
use lexer::Tokens;

///
/// Instructions.
///
#[derive(Debug, PartialEq)]
pub enum Instruction {
    /// Move to the next cell (`>`).
    Next,
    /// Move to the previous cell (`<`
    Prev,
    /// Increment the current cell (`+`).
    Inc,
    /// Decrement the current cell (`-`).
    Dec,
    /// Read a byte from the input into the current cell (`,`).
    Read,
    /// Write a byte from the current cell into the output (`,`).
    Write,
    /// Start of a loop ending on the given index (`[`).
    LoopStart(usize),
    /// End of a loop starting on the given index (`[`).
    LoopEnd(usize),
}

/// A vector of instructions.
pub type Instructions = Vec<Instruction>;

/// An internal stack of opened loop indexes that need to be closed before
/// parsing is finished.
type LoopStack = Vec<usize>;

///
/// Parses the given vector of tokens into a vector of instructions.
///
/// # Arguments
///
/// * `tokens` - Tokens representing a program.
///
pub fn parse(tokens: &Tokens) -> Result<Instructions, String> {
    let mut instructions = Instructions::with_capacity(tokens.len());
    let mut loop_stack = LoopStack::new();
    for (i, token) in tokens.iter().enumerate() {
        match *token {
            Token::Next => instructions.push(Instruction::Next),
            Token::Prev => instructions.push(Instruction::Prev),
            Token::Inc => instructions.push(Instruction::Inc),
            Token::Dec => instructions.push(Instruction::Dec),
            Token::Read => instructions.push(Instruction::Read),
            Token::Write => instructions.push(Instruction::Write),
            Token::LoopStart =>
                try!(handle_loop_start(&mut instructions, &mut loop_stack, i)),
            Token::LoopEnd =>
                try!(handle_loop_end(&mut instructions, &mut loop_stack, i)),
        }
    }
    try!(ensure_all_loops_have_ended(&loop_stack));
    Ok(instructions)
}

fn handle_loop_start(instructions: &mut Instructions,
                     loop_stack: &mut LoopStack,
                     i: usize)
                     -> Result<(), String> {
    // We don't know the target yet, so pass 0. It will be updated later when
    // we reach the target.
    instructions.push(Instruction::LoopStart(0));
    loop_stack.push(i);
    Ok(())
}

fn handle_loop_end(instructions: &mut Instructions,
                   loop_stack: &mut LoopStack,
                   i: usize)
                   -> Result<(), String> {
    let target = match loop_stack.pop() {
        Some(target) => target,
        None => {
            return Err(
                format!("missing start of a loop ended at index {}", i)
            );
        }
    };
    instructions.push(Instruction::LoopEnd(target));
    // Update the index of the target in the loop start because it was
    // initialized to zero.
    instructions[target] = Instruction::LoopStart(i);
    Ok(())
}

fn ensure_all_loops_have_ended(loop_stack: &LoopStack) -> Result<(), String> {
    match loop_stack.last() {
        None => Ok(()),
        Some(i) => Err(format!("missing end of a loop started at index {}", i)),
    }
}

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

    #[test]
    fn test_parse_returns_empty_vec_when_there_are_no_tokens() {
        assert_eq!(parse(&vec![]).unwrap(), vec![]);
    }

    #[test]
    fn test_parse_correctly_parses_infinite_loop() {
        // []
        let tokens = vec![
            Token::LoopStart,
            Token::LoopEnd,
        ];
        let expected_result = Ok(vec![
            Instruction::LoopStart(1),
            Instruction::LoopEnd(0),
        ]);
        assert_eq!(parse(&tokens), expected_result);
    }

    #[test]
    fn test_parse_correctly_parses_valid_program() {
        // [->+<,]
        let tokens = vec![
            Token::LoopStart,
            Token::Dec,
            Token::Next,
            Token::Inc,
            Token::Prev,
            Token::Read,
            Token::LoopEnd,
        ];
        let expected_result = Ok(vec![
            Instruction::LoopStart(6),
            Instruction::Dec,
            Instruction::Next,
            Instruction::Inc,
            Instruction::Prev,
            Instruction::Read,
            Instruction::LoopEnd(0),
        ]);
        assert_eq!(parse(&tokens), expected_result);
    }

    #[test]
    fn test_parse_returns_error_when_missing_loop_end() {
        assert_eq!(
            parse(&vec![Token::LoopStart]),
            Err("missing end of a loop started at index 0".to_string())
        );
    }

    #[test]
    fn test_parse_returns_error_when_missing_loop_start() {
        assert_eq!(
            parse(&vec![Token::LoopEnd]),
            Err("missing start of a loop ended at index 0".to_string())
        );
    }
}
<|endoftext|>


<commit_before>use pom::char_class::{alpha, hex_digit, oct_digit, multispace};
use pom::{parser, Parser};
use pom::parser::*;
use std::str::FromStr;
use xref::*;
use super::{Object, ObjectId, Dictionary, Stream, StringFormat};
use reader::Reader;
use content::*;

fn eol() -> Parser<u8, u8> {
	sym(b'\r') * sym(b'\n') | sym(b'\n') | sym(b'\r')
}

fn comment() -> Parser<u8, ()> {
	sym(b'%') * none_of(b"\r\n").repeat(0..) * eol().discard()
}

fn space() -> Parser<u8, ()> {
	( one_of(b" \t\n\r\0\x0C").repeat(1..).discard()
	| comment()
	).repeat(0..).discard()
}

fn integer() -> Parser<u8, i64> {
	let number = one_of(b"+-").opt() + one_of(b"0123456789").repeat(1..);
	number.collect().convert(|v|String::from_utf8(v)).convert(|s|i64::from_str(&s))
}

fn real() -> Parser<u8, f64> {
	let number = one_of(b"+-").opt() +
		( one_of(b"0123456789").repeat(1..) * sym(b'.') - one_of(b"0123456789").repeat(0..)
		| sym(b'.') - one_of(b"0123456789").repeat(1..)
		);
	number.collect().convert(|v|String::from_utf8(v)).convert(|s|f64::from_str(&s))
}

fn hex_char() -> Parser<u8, u8> {
	let number = is_a(hex_digit).repeat(2);
	number.collect().convert(|v|u8::from_str_radix(&String::from_utf8(v).unwrap(), 16))
}

fn oct_char() -> Parser<u8, u8> {
	let number = is_a(oct_digit).repeat(1..4);
	number.collect().convert(|v|u8::from_str_radix(&String::from_utf8(v).unwrap(), 8))
}

fn name() -> Parser<u8, Vec<u8>> {
	sym(b'/') * (none_of(b" \t\n\r\x0C()<>[]{}/%#") | sym(b'#') * hex_char()).repeat(0..)
}

fn escape_sequence() -> Parser<u8, Vec<u8>> {
	sym(b'\\') *
	( sym(b'\\').map(|_| vec![b'\\'])
	| sym(b'(').map(|_| vec![b'('])
	| sym(b')').map(|_| vec![b')'])
	| sym(b'n').map(|_| vec![b'\n'])
	| sym(b'r').map(|_| vec![b'\r'])
	| sym(b't').map(|_| vec![b'\t'])
	| sym(b'b').map(|_| vec![b'\x08'])
	| sym(b'f').map(|_| vec![b'\x0C'])
	| oct_char().map(|c| vec![c])
	| eol()     .map(|_| vec![])
	| empty()   .map(|_| vec![])
	)
}

fn nested_literal_string() -> Parser<u8, Vec<u8>> {
	sym(b'(') *
	( none_of(b"\\()").repeat(1..)
	| escape_sequence()
	| call(nested_literal_string)
	).repeat(0..).map(|segments| {
		let mut bytes = segments.into_iter().fold(
			vec![b'('],
			|mut bytes, mut segment| {
				bytes.append(&mut segment);
				bytes
			});
		bytes.push(b')');
		bytes
	})
	- sym(b')')
}

fn literal_string() -> Parser<u8, Vec<u8>> {
	sym(b'(') *
	( none_of(b"\\()").repeat(1..)
	| escape_sequence()
	| nested_literal_string()
	).repeat(0..).map(|segments|segments.concat())
	- sym(b')')
}

fn hexadecimal_string() -> Parser<u8, Vec<u8>> {
	sym(b'<') * hex_char().repeat(0..) - sym(b'>')
}

fn array() -> Parser<u8, Vec<Object>> {
	sym(b'[') * space() * call(direct_object).repeat(0..) - sym(b']')
}

fn dictionary() -> Parser<u8, Dictionary> {
	let entry = name() - space() + call(direct_object);
	let entries = seq(b"<<") * space() * entry.repeat(0..) - seq(b">>");
	entries.map(|entries| entries.into_iter().fold(
		Dictionary::new(),
		|mut dict: Dictionary, (key, value)| { dict.set(String::from_utf8(key).unwrap(), value); dict }
	))
}

fn stream<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, Stream> {
	dictionary() - space() - seq(b"stream") - eol() >>
	move |dict: Dictionary| {
		let length = dict.get("Length").and_then(|value| {
			if let Some(id) = value.as_reference() {
				return reader.get_object(id).and_then(|value|value.as_i64());
			}
			return value.as_i64();
		}).expect("Stream Length should be an integer.");
		let stream = take(length as usize) - eol().opt() - seq(b"endstream");
		stream.map(move |data|Stream::new(dict.clone(), data))
	}
}

fn object_id() -> Parser<u8, ObjectId> {
	let id = one_of(b"0123456789").repeat(1..).convert(|v|u32::from_str(&String::from_utf8(v).unwrap()));
	let gen = one_of(b"0123456789").repeat(1..).convert(|v|u16::from_str(&String::from_utf8(v).unwrap()));
	id - space() + gen - space()
}

pub fn direct_object() -> Parser<u8, Object> {
	( seq(b"null").map(|_|Object::Null)
	| seq(b"true").map(|_|Object::Boolean(true))
	| seq(b"false").map(|_|Object::Boolean(false))
	| object_id().map(|id|Object::Reference(id)) - sym(b'R')
	| real().map(|num|Object::Real(num))
	| integer().map(|num|Object::Integer(num))
	| name().map(|bytes| Object::Name(bytes))
	| literal_string().map(Object::string_literal)
	| hexadecimal_string().map(|bytes| Object::String(bytes, StringFormat::Hexadecimal))
	| array().map(|items|Object::Array(items))
	| dictionary().map(|dict|Object::Dictionary(dict))
	) - space()
}

fn object<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, Object> {
	( seq(b"null").map(|_|Object::Null)
	| seq(b"true").map(|_|Object::Boolean(true))
	| seq(b"false").map(|_|Object::Boolean(false))
	| object_id().map(|id|Object::Reference(id)) - sym(b'R')
	| real().map(|num|Object::Real(num))
	| integer().map(|num|Object::Integer(num))
	| name().map(|text| Object::Name(text))
	| literal_string().map(Object::string_literal)
	| hexadecimal_string().map(|bytes| Object::String(bytes, StringFormat::Hexadecimal))
	| array().map(|items|Object::Array(items))
	| stream(reader).map(|stream|Object::Stream(stream))
	| dictionary().map(|dict|Object::Dictionary(dict))
	) - space()
}

pub fn indirect_object<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, (ObjectId, Object)> {
	object_id() - seq(b"obj") - space() + object(reader) - space() - seq(b"endobj") - space()
}

pub fn header() -> Parser<u8, String> {
	seq(b"%PDF-") * none_of(b"\r\n").repeat(0..).convert(|v|String::from_utf8(v)) - eol() - comment().repeat(0..)
}

fn xref() -> Parser<u8, Xref> {
	let xref_entry = integer().map(|i|i as u32) - sym(b' ') + integer().map(|i|i as u16) - sym(b' ') + one_of(b"nf").map(|k|k==b'n') - take(2);
	let xref_section = integer().map(|i|i as usize) - sym(b' ') + integer() - sym(b' ').opt() - eol() + xref_entry.repeat(1..);
	let xref = seq(b"xref") * eol() * xref_section.repeat(1..) - space();
	xref.map(|sections| {
		sections.into_iter().fold(
		Xref::new(0),
		|mut xref: Xref, ((start, _count), entries): ((usize, i64), Vec<((u32, u16), bool)>)| {
			for (index, ((offset, generation), is_normal)) in entries.into_iter().enumerate() {
				if is_normal {
					xref.insert((start + index) as u32, XrefEntry::Normal{offset, generation});
				}
			}
			xref
		})
	})
}

fn trailer() -> Parser<u8, Dictionary> {
	seq(b"trailer") * space() * dictionary() - space()
}

pub fn xref_and_trailer<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, (Xref, Dictionary)> {
	(xref() + trailer()).map(|(mut xref, trailer)| {
		xref.size = trailer.get("Size").and_then(|value| value.as_i64())
			.expect("Size is absent in trailer.") as u32;
		(xref, trailer)
	})
	| indirect_object(reader).convert(|(_, obj)| {
		match obj {
			Object::Stream(stream) => Ok(decode_xref_stream(stream)),
			_ => Err("Xref is not a stream object.")
		}
	})
}

pub fn xref_start() -> Parser<u8, i64> {
	seq(b"startxref") * eol() * integer() - eol() - seq(b"%%EOF") - space()
}

// The following code create parser to parse content stream.

fn content_space() -> Parser<u8, ()> {
	is_a(multispace).repeat(0..).discard()
}

fn operator() -> Parser<u8, String> {
	(is_a(alpha) | one_of(b"*'\"")).repeat(1..).convert(|v|String::from_utf8(v))
}

fn operand() -> Parser<u8, Object> {
	( seq(b"null").map(|_|Object::Null)
	| seq(b"true").map(|_|Object::Boolean(true))
	| seq(b"false").map(|_|Object::Boolean(false))
	| real().map(|num|Object::Real(num))
	| integer().map(|num|Object::Integer(num))
	| name().map(|text| Object::Name(text))
	| literal_string().map(Object::string_literal)
	| hexadecimal_string().map(|bytes| Object::String(bytes, StringFormat::Hexadecimal))
	| array().map(|items|Object::Array(items))
	| dictionary().map(|dict|Object::Dictionary(dict))
	) - content_space()
}

fn operation() -> Parser<u8, Operation> {
	let operation = operand().repeat(0..) + operator() - content_space();
	operation.map(|(operands, operator)| {
		Operation {operator, operands}
	})
}

pub fn content() -> Parser<u8, Content> {
	content_space() * operation().repeat(0..).map(|operations| Content{operations})
}

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

	#[test]
	fn parse_real_number() {
		let r0 = real().parse(&mut DataInput::new(b"0.12"));
		assert_eq!(r0, Ok(0.12));
		let r1 = real().parse(&mut DataInput::new(b"-.12"));
		assert_eq!(r1, Ok(-0.12));
		let r2 = real().parse(&mut DataInput::new(b"10."));
		assert_eq!(r2, Ok(10.0));
	}

	#[test]
	fn parse_string() {
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"()")),
			Ok(b"".to_vec()));
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"(text())")),
			Ok(b"text()".to_vec()));
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"(text\r\n\\\\(nested\\t\\b\\f))")),
			Ok(b"text\r\n\\(nested\t\x08\x0C)".to_vec()));
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"(text\\0\\53\\053\\0053)")),
			Ok(b"text\0++\x053".to_vec()));
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"(text line\\\n())")),
			Ok(b"text line()".to_vec()));
		assert_eq!(
			name().parse(&mut DataInput::new(b"/ABC#5f")),
			Ok(b"ABC\x5F".to_vec()));
	}

	#[test]
	fn parse_name() {
		let text = b"/#cb#ce#cc#e5";
		let name = name().parse(&mut DataInput::new(text));
		println!("{:?}", name);
		assert_eq!(name.is_ok(), true);
	}

	#[test]
	/// Run `cargo test -- --nocapture` to see output
	fn parse_content() {
		let stream = b"
2 J
BT
/F1 12 Tf
0 Tc
0 Tw
72.5 712 TD
[(Unencoded streams can be read easily) 65 (,) ] TJ
0 -14 TD
[(b) 20 (ut generally tak) 10 (e more space than \\311)] TJ
T* (encoded streams.) Tj
		";
		let content = content().parse(&mut DataInput::new(stream));
		println!("{:?}", content);
		assert_eq!(content.is_ok(), true);
	}
}
<commit_msg>Hexadecimal strings can contain white space.<commit_after>use pom::char_class::{alpha, hex_digit, oct_digit, multispace};
use pom::{parser, Parser};
use pom::parser::*;
use std::str::FromStr;
use xref::*;
use super::{Object, ObjectId, Dictionary, Stream, StringFormat};
use reader::Reader;
use content::*;

fn eol() -> Parser<u8, u8> {
	sym(b'\r') * sym(b'\n') | sym(b'\n') | sym(b'\r')
}

fn comment() -> Parser<u8, ()> {
	sym(b'%') * none_of(b"\r\n").repeat(0..) * eol().discard()
}

fn white_space() -> Parser<u8, ()> {
	one_of(b" \t\n\r\0\x0C").repeat(0..).discard()
}

fn space() -> Parser<u8, ()> {
	( one_of(b" \t\n\r\0\x0C").repeat(1..).discard()
	| comment()
	).repeat(0..).discard()
}

fn integer() -> Parser<u8, i64> {
	let number = one_of(b"+-").opt() + one_of(b"0123456789").repeat(1..);
	number.collect().convert(|v|String::from_utf8(v)).convert(|s|i64::from_str(&s))
}

fn real() -> Parser<u8, f64> {
	let number = one_of(b"+-").opt() +
		( one_of(b"0123456789").repeat(1..) * sym(b'.') - one_of(b"0123456789").repeat(0..)
		| sym(b'.') - one_of(b"0123456789").repeat(1..)
		);
	number.collect().convert(|v|String::from_utf8(v)).convert(|s|f64::from_str(&s))
}

fn hex_char() -> Parser<u8, u8> {
	let number = is_a(hex_digit).repeat(2);
	number.collect().convert(|v|u8::from_str_radix(&String::from_utf8(v).unwrap(), 16))
}

fn oct_char() -> Parser<u8, u8> {
	let number = is_a(oct_digit).repeat(1..4);
	number.collect().convert(|v|u8::from_str_radix(&String::from_utf8(v).unwrap(), 8))
}

fn name() -> Parser<u8, Vec<u8>> {
	sym(b'/') * (none_of(b" \t\n\r\x0C()<>[]{}/%#") | sym(b'#') * hex_char()).repeat(0..)
}

fn escape_sequence() -> Parser<u8, Vec<u8>> {
	sym(b'\\') *
	( sym(b'\\').map(|_| vec![b'\\'])
	| sym(b'(').map(|_| vec![b'('])
	| sym(b')').map(|_| vec![b')'])
	| sym(b'n').map(|_| vec![b'\n'])
	| sym(b'r').map(|_| vec![b'\r'])
	| sym(b't').map(|_| vec![b'\t'])
	| sym(b'b').map(|_| vec![b'\x08'])
	| sym(b'f').map(|_| vec![b'\x0C'])
	| oct_char().map(|c| vec![c])
	| eol()     .map(|_| vec![])
	| empty()   .map(|_| vec![])
	)
}

fn nested_literal_string() -> Parser<u8, Vec<u8>> {
	sym(b'(') *
	( none_of(b"\\()").repeat(1..)
	| escape_sequence()
	| call(nested_literal_string)
	).repeat(0..).map(|segments| {
		let mut bytes = segments.into_iter().fold(
			vec![b'('],
			|mut bytes, mut segment| {
				bytes.append(&mut segment);
				bytes
			});
		bytes.push(b')');
		bytes
	})
	- sym(b')')
}

fn literal_string() -> Parser<u8, Vec<u8>> {
	sym(b'(') *
	( none_of(b"\\()").repeat(1..)
	| escape_sequence()
	| nested_literal_string()
	).repeat(0..).map(|segments|segments.concat())
	- sym(b')')
}

fn hexadecimal_string() -> Parser<u8, Vec<u8>> {
	sym(b'<') * (white_space() * hex_char()).repeat(0..) - (white_space() * sym(b'>'))
}

fn array() -> Parser<u8, Vec<Object>> {
	sym(b'[') * space() * call(direct_object).repeat(0..) - sym(b']')
}

fn dictionary() -> Parser<u8, Dictionary> {
	let entry = name() - space() + call(direct_object);
	let entries = seq(b"<<") * space() * entry.repeat(0..) - seq(b">>");
	entries.map(|entries| entries.into_iter().fold(
		Dictionary::new(),
		|mut dict: Dictionary, (key, value)| { dict.set(String::from_utf8(key).unwrap(), value); dict }
	))
}

fn stream<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, Stream> {
	dictionary() - space() - seq(b"stream") - eol() >>
	move |dict: Dictionary| {
		let length = dict.get("Length").and_then(|value| {
			if let Some(id) = value.as_reference() {
				return reader.get_object(id).and_then(|value|value.as_i64());
			}
			return value.as_i64();
		}).expect("Stream Length should be an integer.");
		let stream = take(length as usize) - eol().opt() - seq(b"endstream");
		stream.map(move |data|Stream::new(dict.clone(), data))
	}
}

fn object_id() -> Parser<u8, ObjectId> {
	let id = one_of(b"0123456789").repeat(1..).convert(|v|u32::from_str(&String::from_utf8(v).unwrap()));
	let gen = one_of(b"0123456789").repeat(1..).convert(|v|u16::from_str(&String::from_utf8(v).unwrap()));
	id - space() + gen - space()
}

pub fn direct_object() -> Parser<u8, Object> {
	( seq(b"null").map(|_|Object::Null)
	| seq(b"true").map(|_|Object::Boolean(true))
	| seq(b"false").map(|_|Object::Boolean(false))
	| object_id().map(|id|Object::Reference(id)) - sym(b'R')
	| real().map(|num|Object::Real(num))
	| integer().map(|num|Object::Integer(num))
	| name().map(|bytes| Object::Name(bytes))
	| literal_string().map(Object::string_literal)
	| hexadecimal_string().map(|bytes| Object::String(bytes, StringFormat::Hexadecimal))
	| array().map(|items|Object::Array(items))
	| dictionary().map(|dict|Object::Dictionary(dict))
	) - space()
}

fn object<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, Object> {
	( seq(b"null").map(|_|Object::Null)
	| seq(b"true").map(|_|Object::Boolean(true))
	| seq(b"false").map(|_|Object::Boolean(false))
	| object_id().map(|id|Object::Reference(id)) - sym(b'R')
	| real().map(|num|Object::Real(num))
	| integer().map(|num|Object::Integer(num))
	| name().map(|text| Object::Name(text))
	| literal_string().map(Object::string_literal)
	| hexadecimal_string().map(|bytes| Object::String(bytes, StringFormat::Hexadecimal))
	| array().map(|items|Object::Array(items))
	| stream(reader).map(|stream|Object::Stream(stream))
	| dictionary().map(|dict|Object::Dictionary(dict))
	) - space()
}

pub fn indirect_object<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, (ObjectId, Object)> {
	object_id() - seq(b"obj") - space() + object(reader) - space() - seq(b"endobj") - space()
}

pub fn header() -> Parser<u8, String> {
	seq(b"%PDF-") * none_of(b"\r\n").repeat(0..).convert(|v|String::from_utf8(v)) - eol() - comment().repeat(0..)
}

fn xref() -> Parser<u8, Xref> {
	let xref_entry = integer().map(|i|i as u32) - sym(b' ') + integer().map(|i|i as u16) - sym(b' ') + one_of(b"nf").map(|k|k==b'n') - take(2);
	let xref_section = integer().map(|i|i as usize) - sym(b' ') + integer() - sym(b' ').opt() - eol() + xref_entry.repeat(1..);
	let xref = seq(b"xref") * eol() * xref_section.repeat(1..) - space();
	xref.map(|sections| {
		sections.into_iter().fold(
		Xref::new(0),
		|mut xref: Xref, ((start, _count), entries): ((usize, i64), Vec<((u32, u16), bool)>)| {
			for (index, ((offset, generation), is_normal)) in entries.into_iter().enumerate() {
				if is_normal {
					xref.insert((start + index) as u32, XrefEntry::Normal{offset, generation});
				}
			}
			xref
		})
	})
}

fn trailer() -> Parser<u8, Dictionary> {
	seq(b"trailer") * space() * dictionary() - space()
}

pub fn xref_and_trailer<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, (Xref, Dictionary)> {
	(xref() + trailer()).map(|(mut xref, trailer)| {
		xref.size = trailer.get("Size").and_then(|value| value.as_i64())
			.expect("Size is absent in trailer.") as u32;
		(xref, trailer)
	})
	| indirect_object(reader).convert(|(_, obj)| {
		match obj {
			Object::Stream(stream) => Ok(decode_xref_stream(stream)),
			_ => Err("Xref is not a stream object.")
		}
	})
}

pub fn xref_start() -> Parser<u8, i64> {
	seq(b"startxref") * eol() * integer() - eol() - seq(b"%%EOF") - space()
}

// The following code create parser to parse content stream.

fn content_space() -> Parser<u8, ()> {
	is_a(multispace).repeat(0..).discard()
}

fn operator() -> Parser<u8, String> {
	(is_a(alpha) | one_of(b"*'\"")).repeat(1..).convert(|v|String::from_utf8(v))
}

fn operand() -> Parser<u8, Object> {
	( seq(b"null").map(|_|Object::Null)
	| seq(b"true").map(|_|Object::Boolean(true))
	| seq(b"false").map(|_|Object::Boolean(false))
	| real().map(|num|Object::Real(num))
	| integer().map(|num|Object::Integer(num))
	| name().map(|text| Object::Name(text))
	| literal_string().map(Object::string_literal)
	| hexadecimal_string().map(|bytes| Object::String(bytes, StringFormat::Hexadecimal))
	| array().map(|items|Object::Array(items))
	| dictionary().map(|dict|Object::Dictionary(dict))
	) - content_space()
}

fn operation() -> Parser<u8, Operation> {
	let operation = operand().repeat(0..) + operator() - content_space();
	operation.map(|(operands, operator)| {
		Operation {operator, operands}
	})
}

pub fn content() -> Parser<u8, Content> {
	content_space() * operation().repeat(0..).map(|operations| Content{operations})
}

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

	#[test]
	fn parse_real_number() {
		let r0 = real().parse(&mut DataInput::new(b"0.12"));
		assert_eq!(r0, Ok(0.12));
		let r1 = real().parse(&mut DataInput::new(b"-.12"));
		assert_eq!(r1, Ok(-0.12));
		let r2 = real().parse(&mut DataInput::new(b"10."));
		assert_eq!(r2, Ok(10.0));
	}

	#[test]
	fn parse_string() {
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"()")),
			Ok(b"".to_vec()));
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"(text())")),
			Ok(b"text()".to_vec()));
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"(text\r\n\\\\(nested\\t\\b\\f))")),
			Ok(b"text\r\n\\(nested\t\x08\x0C)".to_vec()));
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"(text\\0\\53\\053\\0053)")),
			Ok(b"text\0++\x053".to_vec()));
		assert_eq!(
			literal_string().parse(&mut DataInput::new(b"(text line\\\n())")),
			Ok(b"text line()".to_vec()));
		assert_eq!(
			name().parse(&mut DataInput::new(b"/ABC#5f")),
			Ok(b"ABC\x5F".to_vec()));
	}

	#[test]
	fn parse_name() {
		let text = b"/#cb#ce#cc#e5";
		let name = name().parse(&mut DataInput::new(text));
		println!("{:?}", name);
		assert_eq!(name.is_ok(), true);
	}

	#[test]
	/// Run `cargo test -- --nocapture` to see output
	fn parse_content() {
		let stream = b"
2 J
BT
/F1 12 Tf
0 Tc
0 Tw
72.5 712 TD
[(Unencoded streams can be read easily) 65 (,) ] TJ
0 -14 TD
[(b) 20 (ut generally tak) 10 (e more space than \\311)] TJ
T* (encoded streams.) Tj
		";
		let content = content().parse(&mut DataInput::new(stream));
		println!("{:?}", content);
		assert_eq!(content.is_ok(), true);
	}
}
<|endoftext|>


<commit_before>use ::*;

pub fn sword_symbol(direction : &Direction) -> String {
    match *direction {
        Up    => "⤉".to_string(), // U-2909
        Down  => "⤈".to_string(), // U-2908
        Left  => "↢".to_string(), // U-21a2
        Right => "↣".to_string(), // U-21a3
    }
}

// PLAYER
pub struct Player {
   pub coord : Coord,
   pub facing : Direction,
   pub sword_coord : Coord,
   pub symbol : String,
   pub dirty : bool,
   pub score : u64,
}

impl Player {
    pub fn new(coord : Coord) -> Self {
        Self {
            coord : coord,
            facing : Right,
            sword_coord : coord.to_the(Right),
            symbol : String::from("☥"), // U-2625
            dirty : true,
            score : 0,
        }
    }
    pub fn travel(&mut self,
                  direction : Direction,
                  floor : &Floor,
                  dirty_coords : &mut Vec<Coord>) -> bool {
        let mut moved = false;
        // Do I change direction?
        if self.facing != direction {
            self.dirty = true;
            dirty_coords.push(self.sword_coord);
            self.facing = direction;
        } else {
            // Can I move?
            let to_coord = self.coord.to_the(self.facing);
            if !floor.is_wall(&to_coord) {
                self.dirty = true;
                moved = true;
                dirty_coords.push(self.coord);
                dirty_coords.push(self.sword_coord);
                self.coord = to_coord;
            }
        }
        // Update the sword's position
        self.sword_coord = self.coord.to_the(self.facing);
        return moved;
    }
}
<commit_msg>Another unnecessary comment<commit_after>use ::*;

pub fn sword_symbol(direction : &Direction) -> String {
    match *direction {
        Up    => "⤉".to_string(), // U-2909
        Down  => "⤈".to_string(), // U-2908
        Left  => "↢".to_string(), // U-21a2
        Right => "↣".to_string(), // U-21a3
    }
}

pub struct Player {
   pub coord : Coord,
   pub facing : Direction,
   pub sword_coord : Coord,
   pub symbol : String,
   pub dirty : bool,
   pub score : u64,
}

impl Player {
    pub fn new(coord : Coord) -> Self {
        Self {
            coord : coord,
            facing : Right,
            sword_coord : coord.to_the(Right),
            symbol : String::from("☥"), // U-2625
            dirty : true,
            score : 0,
        }
    }
    pub fn travel(&mut self,
                  direction : Direction,
                  floor : &Floor,
                  dirty_coords : &mut Vec<Coord>) -> bool {
        let mut moved = false;
        // Do I change direction?
        if self.facing != direction {
            self.dirty = true;
            dirty_coords.push(self.sword_coord);
            self.facing = direction;
        } else {
            // Can I move?
            let to_coord = self.coord.to_the(self.facing);
            if !floor.is_wall(&to_coord) {
                self.dirty = true;
                moved = true;
                dirty_coords.push(self.coord);
                dirty_coords.push(self.sword_coord);
                self.coord = to_coord;
            }
        }
        // Update the sword's position
        self.sword_coord = self.coord.to_the(self.facing);
        return moved;
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::{File, read_dir};
use std::io::Read;
use std::path::PathBuf;
use serde::de::Deserialize;
use serde_protobuf::descriptor::Descriptors;
use serde_protobuf::de::Deserializer;
use serde_value::Value;
use protobuf::{CodedInputStream, parse_from_reader};

pub fn process_single(read: &mut Read) {
    let mut descriptors = Descriptors::new();

    for fdset_path in discover_fdsets() {
        let mut fdset_file = File::open(fdset_path.as_path()).unwrap();
        let proto = parse_from_reader(&mut fdset_file).unwrap();
        descriptors.add_file_set_proto(&proto);
    }

    descriptors.resolve_refs();

    let byte_is = CodedInputStream::new(read);

    let mut deserializer = Deserializer::for_named_message(&descriptors, ".com.example.dog.Dog", byte_is).unwrap();
    let value = Value::deserialize(&mut deserializer).unwrap();
    println!("{:?}", value);
}

pub fn process_stream(read: &mut Read) {
    let mut stream = CodedInputStream::new(read);

    loop {
        match stream.eof() {
            Err(e) => panic!(e),
            Ok(true) => break,
            Ok(false) => break,
            //todo: actually do deserialization here
        }
    }
}

fn discover_fdsets() -> Vec<PathBuf> {
    let mut fdset_files = Vec::new();

    let mut home = env::home_dir().expect("Could not find $HOME");
    home.push(".pq");
    let paths = read_dir(home.as_path()).unwrap();

    for p in paths {
        let path = match p {
            Ok(p) => p.path(),
            Err(_) => continue,
        };
        match path.extension() {
            Some(x) => {
                if x != "fdset" {
                    continue;
                }
            },
            None => continue,
        }
        fdset_files.push(path);
    }
    return fdset_files;
}
<commit_msg>Discover all MessageDescriptors per fdset<commit_after>use std::env;
use std::fs::{File, read_dir};
use std::io::Read;
use std::path::PathBuf;
use serde::de::Deserialize;
use serde_protobuf::descriptor::{Descriptors, MessageDescriptor};
use serde_protobuf::de::Deserializer;
use serde_value::Value;
use protobuf::{CodedInputStream, parse_from_reader};
use protobuf::descriptor::{FileDescriptorSet, FileDescriptorProto};

pub fn process_single(read: &mut Read) {
    let mut descriptors = Descriptors::new();
    let mut message_descriptors = Vec::new();

    for fdset_path in discover_fdsets() {
        let mut fdset_file = File::open(fdset_path.as_path()).unwrap();
        let fdset: FileDescriptorSet = parse_from_reader(&mut fdset_file).unwrap();
        descriptors.add_file_set_proto(&fdset);
        let fdset_protos: &[FileDescriptorProto] = fdset.get_file();
        for file_proto in fdset_protos.iter() {
            for message_proto in file_proto.get_message_type().iter() {
                println!("{:?}", message_proto);
                message_descriptors.push(MessageDescriptor::from_proto(&fdset_path.to_string_lossy().into_owned().as_str(), message_proto));
            }
        }
    }

    descriptors.resolve_refs();

    let byte_is = CodedInputStream::new(read);

    for md in message_descriptors {
        println!("ATTEMPT TO DESERIALIE WITH: {:?}\n\n", md);
        let mut deserializer = Deserializer::new(&descriptors, &md, byte_is);
        let value = Value::deserialize(&mut deserializer).unwrap();
        println!("{:?}", value);
    }
}

pub fn process_stream(read: &mut Read) {
    let mut stream = CodedInputStream::new(read);

    loop {
        match stream.eof() {
            Err(e) => panic!(e),
            Ok(true) => break,
            Ok(false) => break,
            //todo: actually do deserialization here
        }
    }
}

fn discover_fdsets() -> Vec<PathBuf> {
    let mut fdset_files = Vec::new();

    let mut home = env::home_dir().expect("Could not find $HOME");
    home.push(".pq");
    let paths = read_dir(home.as_path()).unwrap();

    for p in paths {
        let path = match p {
            Ok(p) => p.path(),
            Err(_) => continue,
        };
        match path.extension() {
            Some(x) => {
                if x != "fdset" {
                    continue;
                }
            },
            None => continue,
        }
        fdset_files.push(path);
    }
    fdset_files
}
<|endoftext|>