<commit_before>//! A generator for structs that can easily be converted to/from arrays and
//! slices.

/// The `struct_array!` macro generates a `struct` that can be easily converted
/// to/from arrays and slices.
///
/// The format of the macro is similar to a normal struct definition, as shown
/// in the example below. The only differences are an annotation after the
/// struct name for the member type and number of members, and the lack of type
/// annotations on individual members.
///
/// The members of the struct must all be the same type, and the **number of
/// members must be specified correctly**. As long as the number of members is
/// specified correctly, I think everything is safe.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate struct_array;
///
/// struct_array! {
///     /// Example struct array.
///     #[derive(Clone,Debug,PartialEq)]
///     struct Example[u32; 2] {
///         /// x member
///         pub x,
///         /// y member
///         pub y,
///     }
/// }
///
/// fn main() {
///     // Deref as an array.
///     {
///         let example = Example { x: 42, y: 56 };
///         let array: [u32; 2] = *example;
///         assert_eq!(array, [42, 56]);
///     }
///
///     // Deref as a slice (via derefing as an array).
///     {
///         let example = Example { x: 42, y: 56 };
///         let slice: &[u32] = &*example;
///         assert_eq!(slice, &[42, 56]);
///     }
///
///     // Index (via derefing as an array).
///     {
///         let mut example = Example { x: 42, y: 56 };
///         example[1] = 23;
///         assert_eq!(example, Example { x: 42, y: 23 });
///     }
///
///     // Convert into an array.
///     {
///         let example = Example { x: 42, y: 56 };
///         let array: [u32; 2] = example.into();
///         assert_eq!(array, [42, 56]);
///     }
///
///     // Convert from an array to a struct.
///     {
///         let array = [42, 56];
///         let example: Example = array.into();
///         assert_eq!(example, Example { x: 42, y: 56 });
///     }
///
///     // Convert from a slice to a struct reference.
///     {
///         let slice = &[42, 56][..];
///         let example: &Example = slice.into();
///         assert_eq!(example, &Example { x: 42, y: 56 });
///     }
/// }
///
/// ```
///
/// # Attributes
///
/// The generated struct is `repr(C)`. Additional attributes can be attached to
/// the generated `struct` as shown in the example.
///
/// # Visibility
///
/// Members of the generated struct are always `pub`, but the struct itself is
/// not `pub` by default. The struct definition can be made `pub` by adding
/// `pub` before `struct`:
///
/// ```ignore
/// #[macro_use]
/// extern crate struct_array;
///
/// mod example {
///     struct_array! {
///         pub struct Example1[u32; 2] {
///             pub x,
///             pub y,
///         }
///     }
///
///     struct_array! {
///         struct Example2[u32; 2] {
///             pub x,
///             pub y,
///         }
///     }
/// }
///
/// fn main() {
///     let example1 = example::Example1 { x: 42, y: 56 };
///     let example2 = example::Example2 { x: 42, y: 56 }; // error: struct `Example2` is private.
/// }
/// ```
///
/// # Trait implementations
///
/// The struct generated by `struct_array! { struct Foo[T; len] { .. } }`
/// implements:
///
/// * `Deref<Target=[T; len]> for Foo`
/// * `DerefMut<Target=[T; len]> for Foo`
/// * `Into<[T; len] for Foo`
/// * `From<[T; len]> for Foo`
/// * `Into<&[T; len] for &Foo`
/// * `From<&[T; len] for &Foo`
/// * `Into<&mut [T; len] for &mut Foo`
/// * `From<&mut [T; len] for &mut Foo`
/// * `Into<&[T]> for &Foo`
/// * `From<&[T]> for &Foo`
/// * `Into<&mut [T]> for &mut Foo`
/// * `From<&mut [T]> for &mut Foo`
///
/// Note that converting from a slice will panic if the `len()` of the slice
/// does not must match the `len` specified for the struct. You can derive or
/// implement additional traits as for normal structs.
#[macro_export]
macro_rules! struct_array {
    (
        $( #[$attr:meta] )*
        pub struct $name:ident[$member_type:ident; $member_count:expr] {
            $(
                $( #[$member_attr:meta] )*
                pub $member:ident
            ),+
        }
    ) => {
        $( #[$attr] )*
        #[repr(C)]
        pub struct $name {
            $(
                $( #[$member_attr] )*
                pub $member: $member_type,
            )+
        }

        struct_array! {
            @_impl struct
                $name[$member_type; $member_count] {
                    $( $member ),+
                }
        }
    };
    (
        $( #[$attr:meta] )*
        struct $name:ident[$member_type:ident; $member_count:expr] {
            $(
                $( #[$member_attr:meta] )*
                pub $member:ident
            ),+
        }
    ) => {
        $( #[$attr] )*
        #[repr(C)]
        struct $name {
            $(
                $( #[$member_attr] )*
                pub $member: $member_type,
            )+
        }

        struct_array! {
            @_impl struct
                $name[$member_type; $member_count] {
                    $( $member ),+
                }
        }
    };
    (
        $( #[$attr:meta] )*
        pub struct $name:ident[$member_type:ident; $member_count:expr] {
            $(
                $( #[$member_attr:meta] )*
                pub $member:ident
            ),+,
        }
    ) => {
        $( #[$attr] )*
        #[repr(C)]
        pub struct $name {
            $(
                $( #[$member_attr] )*
                pub $member: $member_type,
            )+
        }

        struct_array! {
            @_impl struct
                $name[$member_type; $member_count] {
                    $( $member ),+
                }
        }
    };
    (
        $( #[$attr:meta] )*
        struct $name:ident[$member_type:ident; $member_count:expr] {
            $(
                $( #[$member_attr:meta] )*
                pub $member:ident
            ),+,
        }
    ) => {
        $( #[$attr] )*
        #[repr(C)]
        struct $name {
            $(
                $( #[$member_attr] )*
                pub $member: $member_type,
            )+
        }

        struct_array! {
            @_impl struct
                $name[$member_type; $member_count] {
                    $( $member ),+
                }
        }
    };
    (
        @_impl struct $name:ident[$member_type:ident; $member_count:expr] {
            $( $member:ident ),+
        }
    ) => {
        impl ::std::ops::Deref for $name {
            type Target = [$member_type; $member_count];

            fn deref(&self) -> &[$member_type; $member_count] {
                unsafe {
                    &*(self as *const $name as *const [$member_type; $member_count])
                }
            }
        }

        impl ::std::ops::DerefMut for $name {
            fn deref_mut(&mut self) -> &mut [$member_type; $member_count] {
                unsafe {
                    &mut *(self as *mut $name as *mut [$member_type; $member_count])
                }
            }
        }

        impl Into<[$member_type; $member_count]> for $name {
            fn into(self) -> [$member_type; $member_count] {
                unsafe {
                    ::std::mem::transmute(self)
                }
            }
        }

        impl From<[$member_type; $member_count]> for $name {
            fn from(array: [$member_type; $member_count]) -> $name {
                unsafe {
                    ::std::mem::transmute(array)
                }
            }
        }

        impl<'a> Into<&'a [$member_type; $member_count]> for &'a $name {
            fn into(self) -> &'a [$member_type; $member_count] {
                unsafe {
                    &*(self as *const $name as *const [$member_type; $member_count])
                }
            }
        }

        impl<'a> From<&'a [$member_type; $member_count]> for &'a $name {
            fn from(array: &[$member_type; $member_count]) -> &$name {
                unsafe {
                    &*(array as *const [$member_type; $member_count] as *const $name)
                }
            }
        }

        impl<'a> Into<&'a mut [$member_type; $member_count]> for &'a mut $name {
            fn into(self) -> &'a mut [$member_type; $member_count] {
                unsafe {
                    &mut *(self as *mut $name as *mut [$member_type; $member_count])
                }
            }
        }

        impl<'a> From<&'a mut [$member_type; $member_count]> for &'a mut $name {
            fn from(array: &mut [$member_type; $member_count]) -> &mut $name {
                unsafe {
                    &mut *(array as *mut [$member_type; $member_count] as *mut $name)
                }
            }
        }

        impl<'a> Into<&'a [$member_type]> for &'a $name {
            fn into(self) -> &'a [$member_type] {
                unsafe {
                    ::std::slice::from_raw_parts(self as *const $name as *const $member_type, $member_count)
                }
            }
        }

        impl<'a> From<&'a [$member_type]> for &'a $name {
            fn from(slice: &'a [$member_type]) -> &'a $name {
                assert!(slice.len() == $member_count);
                unsafe {
                    &*(slice.as_ptr() as *const $name)
                }
            }
        }

        impl<'a> Into<&'a mut [$member_type]> for &'a mut $name {
            fn into(self) -> &'a mut [$member_type] {
                unsafe {
                    ::std::slice::from_raw_parts_mut(self as *mut $name as *mut $member_type, $member_count)
                }
            }
        }

        impl<'a> From<&'a mut [$member_type]> for &'a mut $name {
            fn from(slice: &'a mut [$member_type]) -> &'a mut $name {
                assert!(slice.len() == $member_count);
                unsafe {
                    &mut *(slice.as_mut_ptr() as *mut $name)
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    struct_array! {
        /// Example struct array.
        #[derive(Clone,Debug,PartialEq)]
        struct Example[u32; 2] {
            /// x member
            pub x,
            /// y member
            pub y,
        }
    }

    #[test]
    fn test_deref() {
        let foo = Example {
            x: 0,
            y: 1,
        };
        let bar: &[u32; 2] = &foo;
        assert_eq!(bar, &[0, 1]);
    }

    #[test]
    fn test_deref_mut() {
        let mut foo = Example {
            x: 0,
            y: 1,
        };
        {
            let bar: &mut [u32; 2] = &mut foo;
            bar[1] = 2;
            assert_eq!(bar, &[0, 2]);
        }
        assert_eq!(foo, Example { x: 0, y: 2 });
    }

    #[test]
    fn test_into_array() {
        let foo = Example { x: 0, y: 1 };
        let bar: [u32; 2] = foo.into();
        assert_eq!(bar, [0, 1]);
    }

    #[test]
    fn test_from_array() {
        let foo = [0, 1];
        let mut bar: Example = foo.into();
        bar.y = 2;
        assert_eq!(bar, Example { x: 0, y: 2 });
    }

    #[test]
    fn test_into_array_ref() {
        let foo = &Example { x: 0, y: 1 };
        let bar: &[u32; 2] = foo.into();
        assert_eq!(bar, &[0, 1]);
    }

    #[test]
    fn test_from_array_ref() {
        let foo = &[0, 1];
        let bar: &Example = foo.into();
        assert_eq!(bar, &Example { x: 0, y: 1 });
    }

    #[test]
    fn test_into_array_ref_mut() {
        let mut foo = &mut Example { x: 0, y: 1 };
        {
            let mut bar: &mut [u32; 2] = foo.into();
            bar[1] = 2;
            assert_eq!(bar, &mut [0, 2]);
        }
        assert_eq!(foo, &mut Example { x: 0, y: 2 });
    }

    #[test]
    fn test_from_array_ref_mut() {
        let foo = &mut [0, 1];
        {
            let mut bar: &mut Example = foo.into();
            bar.y = 2;
            assert_eq!(bar, &mut Example { x: 0, y: 2 });
        }
        assert_eq!(foo, &mut [0, 2]);
    }

    #[test]
    fn test_into_slice() {
        let foo = Example { x: 0, y: 1 };
        let bar: &[u32] = (&foo).into();
        assert_eq!(bar, [0, 1]);
    }

    #[test]
    fn test_from_slice() {
        let foo = [0, 1];
        let bar: &[u32] = &foo;
        let baz: &Example = bar.into();
        assert_eq!(baz, &Example { x: 0, y: 1 });
    }

    #[test]
    fn test_into_mut_slice() {
        let mut foo = Example { x: 0, y: 1 };
        {
            let bar: &mut [u32] = (&mut foo).into();
            bar[1] = 2;
            assert_eq!(bar, &mut [0, 2]);
        }
        assert_eq!(foo, Example { x: 0, y: 2 });
    }

    #[test]
    fn test_from_mut_slice() {
        let mut foo = [0, 1];
        {
            let mut bar: &mut [u32] = &mut foo;
            let mut baz: &mut Example = bar.into();
            baz.y = 2;
            assert_eq!(baz, &Example { x: 0, y: 2 });
        }
        assert_eq!(foo, [0, 2]);
    }
}
<commit_msg>Clarify test names<commit_after>//! A generator for structs that can easily be converted to/from arrays and
//! slices.

/// The `struct_array!` macro generates a `struct` that can be easily converted
/// to/from arrays and slices.
///
/// The format of the macro is similar to a normal struct definition, as shown
/// in the example below. The only differences are an annotation after the
/// struct name for the member type and number of members, and the lack of type
/// annotations on individual members.
///
/// The members of the struct must all be the same type, and the **number of
/// members must be specified correctly**. As long as the number of members is
/// specified correctly, I think everything is safe.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate struct_array;
///
/// struct_array! {
///     /// Example struct array.
///     #[derive(Clone,Debug,PartialEq)]
///     struct Example[u32; 2] {
///         /// x member
///         pub x,
///         /// y member
///         pub y,
///     }
/// }
///
/// fn main() {
///     // Deref as an array.
///     {
///         let example = Example { x: 42, y: 56 };
///         let array: [u32; 2] = *example;
///         assert_eq!(array, [42, 56]);
///     }
///
///     // Deref as a slice (via derefing as an array).
///     {
///         let example = Example { x: 42, y: 56 };
///         let slice: &[u32] = &*example;
///         assert_eq!(slice, &[42, 56]);
///     }
///
///     // Index (via derefing as an array).
///     {
///         let mut example = Example { x: 42, y: 56 };
///         example[1] = 23;
///         assert_eq!(example, Example { x: 42, y: 23 });
///     }
///
///     // Convert into an array.
///     {
///         let example = Example { x: 42, y: 56 };
///         let array: [u32; 2] = example.into();
///         assert_eq!(array, [42, 56]);
///     }
///
///     // Convert from an array to a struct.
///     {
///         let array = [42, 56];
///         let example: Example = array.into();
///         assert_eq!(example, Example { x: 42, y: 56 });
///     }
///
///     // Convert from a slice to a struct reference.
///     {
///         let slice = &[42, 56][..];
///         let example: &Example = slice.into();
///         assert_eq!(example, &Example { x: 42, y: 56 });
///     }
/// }
///
/// ```
///
/// # Attributes
///
/// The generated struct is `repr(C)`. Additional attributes can be attached to
/// the generated `struct` as shown in the example.
///
/// # Visibility
///
/// Members of the generated struct are always `pub`, but the struct itself is
/// not `pub` by default. The struct definition can be made `pub` by adding
/// `pub` before `struct`:
///
/// ```ignore
/// #[macro_use]
/// extern crate struct_array;
///
/// mod example {
///     struct_array! {
///         pub struct Example1[u32; 2] {
///             pub x,
///             pub y,
///         }
///     }
///
///     struct_array! {
///         struct Example2[u32; 2] {
///             pub x,
///             pub y,
///         }
///     }
/// }
///
/// fn main() {
///     let example1 = example::Example1 { x: 42, y: 56 };
///     let example2 = example::Example2 { x: 42, y: 56 }; // error: struct `Example2` is private.
/// }
/// ```
///
/// # Trait implementations
///
/// The struct generated by `struct_array! { struct Foo[T; len] { .. } }`
/// implements:
///
/// * `Deref<Target=[T; len]> for Foo`
/// * `DerefMut<Target=[T; len]> for Foo`
/// * `Into<[T; len] for Foo`
/// * `From<[T; len]> for Foo`
/// * `Into<&[T; len] for &Foo`
/// * `From<&[T; len] for &Foo`
/// * `Into<&mut [T; len] for &mut Foo`
/// * `From<&mut [T; len] for &mut Foo`
/// * `Into<&[T]> for &Foo`
/// * `From<&[T]> for &Foo`
/// * `Into<&mut [T]> for &mut Foo`
/// * `From<&mut [T]> for &mut Foo`
///
/// Note that converting from a slice will panic if the `len()` of the slice
/// does not must match the `len` specified for the struct. You can derive or
/// implement additional traits as for normal structs.
#[macro_export]
macro_rules! struct_array {
    (
        $( #[$attr:meta] )*
        pub struct $name:ident[$member_type:ident; $member_count:expr] {
            $(
                $( #[$member_attr:meta] )*
                pub $member:ident
            ),+
        }
    ) => {
        $( #[$attr] )*
        #[repr(C)]
        pub struct $name {
            $(
                $( #[$member_attr] )*
                pub $member: $member_type,
            )+
        }

        struct_array! {
            @_impl struct
                $name[$member_type; $member_count] {
                    $( $member ),+
                }
        }
    };
    (
        $( #[$attr:meta] )*
        struct $name:ident[$member_type:ident; $member_count:expr] {
            $(
                $( #[$member_attr:meta] )*
                pub $member:ident
            ),+
        }
    ) => {
        $( #[$attr] )*
        #[repr(C)]
        struct $name {
            $(
                $( #[$member_attr] )*
                pub $member: $member_type,
            )+
        }

        struct_array! {
            @_impl struct
                $name[$member_type; $member_count] {
                    $( $member ),+
                }
        }
    };
    (
        $( #[$attr:meta] )*
        pub struct $name:ident[$member_type:ident; $member_count:expr] {
            $(
                $( #[$member_attr:meta] )*
                pub $member:ident
            ),+,
        }
    ) => {
        $( #[$attr] )*
        #[repr(C)]
        pub struct $name {
            $(
                $( #[$member_attr] )*
                pub $member: $member_type,
            )+
        }

        struct_array! {
            @_impl struct
                $name[$member_type; $member_count] {
                    $( $member ),+
                }
        }
    };
    (
        $( #[$attr:meta] )*
        struct $name:ident[$member_type:ident; $member_count:expr] {
            $(
                $( #[$member_attr:meta] )*
                pub $member:ident
            ),+,
        }
    ) => {
        $( #[$attr] )*
        #[repr(C)]
        struct $name {
            $(
                $( #[$member_attr] )*
                pub $member: $member_type,
            )+
        }

        struct_array! {
            @_impl struct
                $name[$member_type; $member_count] {
                    $( $member ),+
                }
        }
    };
    (
        @_impl struct $name:ident[$member_type:ident; $member_count:expr] {
            $( $member:ident ),+
        }
    ) => {
        impl ::std::ops::Deref for $name {
            type Target = [$member_type; $member_count];

            fn deref(&self) -> &[$member_type; $member_count] {
                unsafe {
                    &*(self as *const $name as *const [$member_type; $member_count])
                }
            }
        }

        impl ::std::ops::DerefMut for $name {
            fn deref_mut(&mut self) -> &mut [$member_type; $member_count] {
                unsafe {
                    &mut *(self as *mut $name as *mut [$member_type; $member_count])
                }
            }
        }

        impl Into<[$member_type; $member_count]> for $name {
            fn into(self) -> [$member_type; $member_count] {
                unsafe {
                    ::std::mem::transmute(self)
                }
            }
        }

        impl From<[$member_type; $member_count]> for $name {
            fn from(array: [$member_type; $member_count]) -> $name {
                unsafe {
                    ::std::mem::transmute(array)
                }
            }
        }

        impl<'a> Into<&'a [$member_type; $member_count]> for &'a $name {
            fn into(self) -> &'a [$member_type; $member_count] {
                unsafe {
                    &*(self as *const $name as *const [$member_type; $member_count])
                }
            }
        }

        impl<'a> From<&'a [$member_type; $member_count]> for &'a $name {
            fn from(array: &[$member_type; $member_count]) -> &$name {
                unsafe {
                    &*(array as *const [$member_type; $member_count] as *const $name)
                }
            }
        }

        impl<'a> Into<&'a mut [$member_type; $member_count]> for &'a mut $name {
            fn into(self) -> &'a mut [$member_type; $member_count] {
                unsafe {
                    &mut *(self as *mut $name as *mut [$member_type; $member_count])
                }
            }
        }

        impl<'a> From<&'a mut [$member_type; $member_count]> for &'a mut $name {
            fn from(array: &mut [$member_type; $member_count]) -> &mut $name {
                unsafe {
                    &mut *(array as *mut [$member_type; $member_count] as *mut $name)
                }
            }
        }

        impl<'a> Into<&'a [$member_type]> for &'a $name {
            fn into(self) -> &'a [$member_type] {
                unsafe {
                    ::std::slice::from_raw_parts(self as *const $name as *const $member_type, $member_count)
                }
            }
        }

        impl<'a> From<&'a [$member_type]> for &'a $name {
            fn from(slice: &'a [$member_type]) -> &'a $name {
                assert!(slice.len() == $member_count);
                unsafe {
                    &*(slice.as_ptr() as *const $name)
                }
            }
        }

        impl<'a> Into<&'a mut [$member_type]> for &'a mut $name {
            fn into(self) -> &'a mut [$member_type] {
                unsafe {
                    ::std::slice::from_raw_parts_mut(self as *mut $name as *mut $member_type, $member_count)
                }
            }
        }

        impl<'a> From<&'a mut [$member_type]> for &'a mut $name {
            fn from(slice: &'a mut [$member_type]) -> &'a mut $name {
                assert!(slice.len() == $member_count);
                unsafe {
                    &mut *(slice.as_mut_ptr() as *mut $name)
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    struct_array! {
        /// Example struct array.
        #[derive(Clone,Debug,PartialEq)]
        struct Example[u32; 2] {
            /// x member
            pub x,
            /// y member
            pub y,
        }
    }

    #[test]
    fn test_deref() {
        let foo = Example {
            x: 0,
            y: 1,
        };
        let bar: &[u32; 2] = &foo;
        assert_eq!(bar, &[0, 1]);
    }

    #[test]
    fn test_deref_mut() {
        let mut foo = Example {
            x: 0,
            y: 1,
        };
        {
            let bar: &mut [u32; 2] = &mut foo;
            bar[1] = 2;
            assert_eq!(bar, &[0, 2]);
        }
        assert_eq!(foo, Example { x: 0, y: 2 });
    }

    #[test]
    fn test_into_array() {
        let foo = Example { x: 0, y: 1 };
        let bar: [u32; 2] = foo.into();
        assert_eq!(bar, [0, 1]);
    }

    #[test]
    fn test_from_array() {
        let foo = [0, 1];
        let mut bar: Example = foo.into();
        bar.y = 2;
        assert_eq!(bar, Example { x: 0, y: 2 });
    }

    #[test]
    fn test_into_array_ref() {
        let foo = &Example { x: 0, y: 1 };
        let bar: &[u32; 2] = foo.into();
        assert_eq!(bar, &[0, 1]);
    }

    #[test]
    fn test_from_array_ref() {
        let foo = &[0, 1];
        let bar: &Example = foo.into();
        assert_eq!(bar, &Example { x: 0, y: 1 });
    }

    #[test]
    fn test_into_array_ref_mut() {
        let mut foo = &mut Example { x: 0, y: 1 };
        {
            let mut bar: &mut [u32; 2] = foo.into();
            bar[1] = 2;
            assert_eq!(bar, &mut [0, 2]);
        }
        assert_eq!(foo, &mut Example { x: 0, y: 2 });
    }

    #[test]
    fn test_from_array_ref_mut() {
        let foo = &mut [0, 1];
        {
            let mut bar: &mut Example = foo.into();
            bar.y = 2;
            assert_eq!(bar, &mut Example { x: 0, y: 2 });
        }
        assert_eq!(foo, &mut [0, 2]);
    }

    #[test]
    fn test_into_slice_ref() {
        let foo = Example { x: 0, y: 1 };
        let bar: &[u32] = (&foo).into();
        assert_eq!(bar, [0, 1]);
    }

    #[test]
    fn test_from_slice_ref() {
        let foo = [0, 1];
        let bar: &[u32] = &foo;
        let baz: &Example = bar.into();
        assert_eq!(baz, &Example { x: 0, y: 1 });
    }

    #[test]
    fn test_into_slice_ref_mut() {
        let mut foo = Example { x: 0, y: 1 };
        {
            let bar: &mut [u32] = (&mut foo).into();
            bar[1] = 2;
            assert_eq!(bar, &mut [0, 2]);
        }
        assert_eq!(foo, Example { x: 0, y: 2 });
    }

    #[test]
    fn test_from_slice_ref_mut() {
        let mut foo = [0, 1];
        {
            let mut bar: &mut [u32] = &mut foo;
            let mut baz: &mut Example = bar.into();
            baz.y = 2;
            assert_eq!(baz, &Example { x: 0, y: 2 });
        }
        assert_eq!(foo, [0, 2]);
    }
}
<|endoftext|>


<commit_before>// use variable names from paper, namely registers M
#![allow(non_snake_case)]

#![crate_name = "basichll"]
#![crate_type = "lib"]

/* -------------------- std libs ------------------- */
use std::cmp;
use std::fmt;
use std::hash::{ Hash, Hasher, SipHasher };
use std::iter;
use std::num::{ Int, Float };
/* ------------------------------------------------- */

/* -------------------- helpers -------------------- */

fn alpha (m: usize) -> f64 {
    match m {
        16 => 0.673,
        32 => 0.697,
        64 => 0.709,
        _  => 0.7213/(1f64 + 1.079/(m as f64))
    }
}

fn leftmost_one_bit (v: u64) -> usize {
    let mut counter: usize = 0;
    let mut shiftable = v;

    while shiftable > 0 {
        shiftable >>= 1;
        counter += 1;
    }

    64 - counter
}

/* ------------------------------------------------- */

/* --------------- hyper log log ------------------- */

pub struct HLL {
    alpha: f64,
    b: u32,
    m: usize,
    M: Vec<u8>,
    // [!] this is pretty much a hack until I can think of something
    //     better to do for the monoid instance. Basically we need the
    //     zero value to always satisfy the left and right identity laws
    //     but because you need to have the number of registers be
    //     equivalent to do addition, it implies you need a distinct
    //     monoid instance per HLL configuration (i.e. an HLL of 4
    //     registers has a distinct zero from a HLL of 16).
    //
    //     Because I can't really do dependent types in rust, we instead
    //     have a distinguished zero element, that is allowed to bypass
    //     the assertions on the equivalent sizes...
    //
    //     For reference, Ed Kmett's haskell implementation actually does
    //     use higher kinded types and some tricky reflection to make the
    //     monoid instance be parameterised by a config type that is itself
    //     typed to a Peano natural encoded type. Twitter's algebird instance
    //     declares a separate class that encapsulates the notion of
    //     a "HyperLogLogMonoid" instance, and instances of that class are
    //     instantiated with the register size (i.e. the 'instance' for monoid
    //     is just an 'instance' of the class, for two interpretations of
    //     'instance').
    isZero: bool
}

impl HLL {
    pub fn one_hundred_twenty_eight () -> HLL {
        HLL::new(0.09192)
    }

    pub fn new(error: f64) -> HLL {
        assert!(error > 0.0 && error < 1.0);
        // error = 1.04 / sqrt(m)
        let m = Float::floor((1.04/error) * (1.04/error)) as usize;
        let b = Float::log2(m as f64) as u32;

        HLL {
            alpha: alpha(m),
            b: b,
            m: m,
            M: iter::repeat(0u8).take(m).collect(),
            isZero: false
        }
    }

    pub fn insert<T: Hash>(&mut self, val: &T) {
        let mut hasher = SipHasher::new();
        val.hash(&mut hasher);
        let hash = hasher.finish();

        // j is the first b many bits
        let j = (hash >> (64 - self.b)) as usize;
        // w is the remaining bits (i.e. b -> 64)
        let w = hash & (2u64.pow(64 - self.b) - 1) as u64;
        let rho = leftmost_one_bit(w) as u8;

        self.M[j] = cmp::max(self.M[j], rho);
    }

    pub fn count(&self) -> f64 {
        self.range_correction(self.raw_estimate())
    }

    fn raw_estimate(&self) -> f64 {
        let sum: f64 = self.M.iter().fold (0.0, |p, &r| p + 2.0f64.powi(-(r as i32)));

        self.alpha as f64 * ((self.m  * self.m) as f64) * (1.0 / sum)
    }

    fn empty_registers (&self) -> usize {
        self.M.iter().filter(|&r| *r == 0).count()
    }

    fn range_correction(&self, e: f64) -> f64 {
        let twoTo32: f64 = 2.0f64.powi(32) as f64;

        // small range correction
        if e <= (5.0*(self.m as f64))/2.0 {
            let v  = self.empty_registers() as f64;
            let fm = self.m as f64;

            return match v {
                0.0 => e,
                _   => fm * (fm / v).ln()
            }
        }

        // medium range (no) correction
        if e <= twoTo32/30.0 {
            return e;
        }

        -twoTo32 * (1.0 - e/twoTo32).ln()
    }

    pub fn registers(&self) -> Vec<u8> {
        self.M.clone()
    }

    pub fn clone (&self) -> HLL {
        HLL {
            alpha: self.alpha,
            b: self.b,
            m: self.m,
            M: self.M.clone(),
            isZero: self.isZero
        }
    }

    pub fn empty () -> HLL {
        HLL {
            alpha: 0.0,
            m: 0,
            b: 0,
            M: Vec::new(),
            isZero: true
        }
    }

}

/* ------------------------------------------------- */

/* --------------- trait instances ----------------- */

impl std::fmt::Display for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

impl std::fmt::Debug for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

impl std::cmp::Eq for HLL {}
impl std::cmp::PartialEq for HLL {
    fn eq(&self, other: &HLL) -> bool {
           self.alpha  == other.alpha
        && self.m      == other.m
        && self.b      == other.b
        && self.M      == other.M
        && self.isZero == other.isZero
    }
}

fn mergeRegisters (first: &Vec<u8>, second: &Vec<u8>) -> Vec<u8> {
    // TODO -- isn't this just zipWith max?
    let mut res: Vec<u8> = Vec::new();
    let mut zipper = first.iter().zip(second.iter());
    loop {
        match zipper.next() {
            None => return res,
            Some ((f, s)) => res.push(*cmp::max(f, s))
        }
    }
}

impl<'a> std::ops::Add<&'a HLL> for &'a HLL {
    type Output = HLL;

    fn add(self, other: &'a HLL) -> HLL {
        // [!] gross...
        if self.isZero { return other.clone(); }
        if other.isZero { return self.clone(); }

        assert!(self.alpha == other.alpha);
        assert!(self.b == other.b);
        assert!(self.m == other.m);

        HLL {
            alpha: self.alpha,
            b: self.b,
            m: self.m,
            M: mergeRegisters(&self.M, &other.M),
            isZero: false
        }
    }
}

/* ------------------------------------------------- */
<commit_msg>Resolve TODO by removing explicit recursion<commit_after>// use variable names from paper, namely registers M
#![allow(non_snake_case)]

#![crate_name = "basichll"]
#![crate_type = "lib"]

/* -------------------- std libs ------------------- */
use std::cmp;
use std::fmt;
use std::hash::{ Hash, Hasher, SipHasher };
use std::iter::{ repeat, Iterator };
use std::num::{ Int, Float };
/* ------------------------------------------------- */

/* -------------------- helpers -------------------- */

fn alpha (m: usize) -> f64 {
    match m {
        16 => 0.673,
        32 => 0.697,
        64 => 0.709,
        _  => 0.7213/(1f64 + 1.079/(m as f64))
    }
}

fn leftmost_one_bit (v: u64) -> usize {
    let mut counter: usize = 0;
    let mut shiftable = v;

    while shiftable > 0 {
        shiftable >>= 1;
        counter += 1;
    }

    64 - counter
}

/* ------------------------------------------------- */

/* --------------- hyper log log ------------------- */

pub struct HLL {
    alpha: f64,
    b: u32,
    m: usize,
    M: Vec<u8>,
    // [!] this is pretty much a hack until I can think of something
    //     better to do for the monoid instance. Basically we need the
    //     zero value to always satisfy the left and right identity laws
    //     but because you need to have the number of registers be
    //     equivalent to do addition, it implies you need a distinct
    //     monoid instance per HLL configuration (i.e. an HLL of 4
    //     registers has a distinct zero from a HLL of 16).
    //
    //     Because I can't really do dependent types in rust, we instead
    //     have a distinguished zero element, that is allowed to bypass
    //     the assertions on the equivalent sizes...
    //
    //     For reference, Ed Kmett's haskell implementation actually does
    //     use higher kinded types and some tricky reflection to make the
    //     monoid instance be parameterised by a config type that is itself
    //     typed to a Peano natural encoded type. Twitter's algebird instance
    //     declares a separate class that encapsulates the notion of
    //     a "HyperLogLogMonoid" instance, and instances of that class are
    //     instantiated with the register size (i.e. the 'instance' for monoid
    //     is just an 'instance' of the class, for two interpretations of
    //     'instance').
    isZero: bool
}

impl HLL {
    pub fn one_hundred_twenty_eight () -> HLL {
        HLL::new(0.09192)
    }

    pub fn new(error: f64) -> HLL {
        assert!(error > 0.0 && error < 1.0);
        // error = 1.04 / sqrt(m)
        let m = Float::floor((1.04/error) * (1.04/error)) as usize;
        let b = Float::log2(m as f64) as u32;

        HLL {
            alpha: alpha(m),
            b: b,
            m: m,
            M: repeat(0u8).take(m).collect(),
            isZero: false
        }
    }

    pub fn insert<T: Hash>(&mut self, val: &T) {
        let mut hasher = SipHasher::new();
        val.hash(&mut hasher);
        let hash = hasher.finish();

        // j is the first b many bits
        let j = (hash >> (64 - self.b)) as usize;
        // w is the remaining bits (i.e. b -> 64)
        let w = hash & (2u64.pow(64 - self.b) - 1) as u64;
        let rho = leftmost_one_bit(w) as u8;

        self.M[j] = cmp::max(self.M[j], rho);
    }

    pub fn count(&self) -> f64 {
        self.range_correction(self.raw_estimate())
    }

    fn raw_estimate(&self) -> f64 {
        let sum: f64 = self.M.iter().fold (0.0, |p, &r| p + 2.0f64.powi(-(r as i32)));

        self.alpha as f64 * ((self.m  * self.m) as f64) * (1.0 / sum)
    }

    fn empty_registers (&self) -> usize {
        self.M.iter().filter(|&r| *r == 0).count()
    }

    fn range_correction(&self, e: f64) -> f64 {
        let twoTo32: f64 = 2.0f64.powi(32) as f64;

        // small range correction
        if e <= (5.0*(self.m as f64))/2.0 {
            let v  = self.empty_registers() as f64;
            let fm = self.m as f64;

            return match v {
                0.0 => e,
                _   => fm * (fm / v).ln()
            }
        }

        // medium range (no) correction
        if e <= twoTo32/30.0 {
            return e;
        }

        -twoTo32 * (1.0 - e/twoTo32).ln()
    }

    pub fn registers(&self) -> Vec<u8> {
        self.M.clone()
    }

    pub fn clone (&self) -> HLL {
        HLL {
            alpha: self.alpha,
            b: self.b,
            m: self.m,
            M: self.M.clone(),
            isZero: self.isZero
        }
    }

    pub fn empty () -> HLL {
        HLL {
            alpha: 0.0,
            m: 0,
            b: 0,
            M: Vec::new(),
            isZero: true
        }
    }

}

/* ------------------------------------------------- */

/* --------------- trait instances ----------------- */

impl std::fmt::Display for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

impl std::fmt::Debug for HLL {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "α: {}, b: {}, m: {}", self.alpha, self.b, self.m)
    }
}

impl std::cmp::Eq for HLL {}
impl std::cmp::PartialEq for HLL {
    fn eq(&self, other: &HLL) -> bool {
           self.alpha  == other.alpha
        && self.m      == other.m
        && self.b      == other.b
        && self.M      == other.M
        && self.isZero == other.isZero
    }
}

fn zipWith<R, U: Iterator, C: Fn(U::Item, U::Item) -> R> (combo: C, left: U, right: U)
   -> Vec<R> {
    left.zip(right).map(| (l, r) | combo(l, r)).collect()
}

fn mergeRegisters (first: &Vec<u8>, second: &Vec<u8>) -> Vec<u8> {
    zipWith(|&l, &r| std::cmp::max(l, r), first.iter(), second.iter())
}

impl<'a> std::ops::Add<&'a HLL> for &'a HLL {
    type Output = HLL;

    fn add(self, other: &'a HLL) -> HLL {
        // [!] gross...
        if self.isZero { return other.clone(); }
        if other.isZero { return self.clone(); }

        assert!(self.alpha == other.alpha);
        assert!(self.b == other.b);
        assert!(self.m == other.m);

        HLL {
            alpha: self.alpha,
            b: self.b,
            m: self.m,
            M: mergeRegisters(&self.M, &other.M),
            isZero: false
        }
    }
}

/* ------------------------------------------------- */
<|endoftext|>


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

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable)]
pub struct Version {
    pub name: String,
    pub vers: String,
    pub deps: Vec<Dependency>,
    pub cksum: String,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable)]
pub struct Dependency {
    pub name: String,
    pub req: String,
    pub features: Vec<String>,
    pub optional: bool,
    pub default_features: bool,
    pub target: Option<String>,
    pub kind: Option<String>
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
    let crate_ = index.crates().nth(0).unwrap();
    let version = crate_.latest_version();
    let _ = version.deps;
}
<commit_msg>Dependency/Version should derive Clone<commit_after>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable, Clone)]
pub struct Version {
    pub name: String,
    pub vers: String,
    pub deps: Vec<Dependency>,
    pub cksum: String,
    pub features: HashMap<String, Vec<String>>,
    pub yanked: bool,
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable, Clone)]
pub struct Dependency {
    pub name: String,
    pub req: String,
    pub features: Vec<String>,
    pub optional: bool,
    pub default_features: bool,
    pub target: Option<String>,
    pub kind: Option<String>
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
    let crate_ = index.crates().nth(0).unwrap();
    let version = crate_.latest_version();
    let _ = version.deps;
}
<|endoftext|>


<commit_before>/*
* A basic EBML parser for Rust. Gives methods for both approaches; full parsing
* of an EBML file in-memory or incremental sequential parsing of nodes for
* environments that are more memory-constrained.
*
* The full parser allows you to get all sub-elements of a node in one call,
* because each node has a reference to the data it contains. All of the data is
* loaded into memory when the root node is parsed.
*
* The PartialElement only reads the data it needs to get the header of any
* single element. So if the data source is a file the full parser will load the
* whole file to memory, while the partial parser will only load at most one leaf
* node's value plus its id and size.
*
* The partial parser stores the offset of each node in the input stream, which
* is then used to jump to the node's data in the stream. This may cause the
* partial parser to do more random seeking.
*/

//extern crate time;
//use std::io::Memreader;
//use time::Timespec;

mod rebml {
    use time::Timespec;
    enum Value {
		Uint(u64),
		Int(i64),
		Str(String),
		DateTimespec),
		Bin(&[u8]),
        SubElement,
		Nil, // Empty element
	}

    mod incremental {
        use std::io::{IoResult,IoError};
        pub struct Parser {
            input: &Reader,
            id: u32,
            size: u64
        }

        impl Parser {
            /*
            Create new EBML Parser and read in the first tag, if any. Expects the stream to start with the top-level
            EBML tag [1A][45][DF][A3]. Consumes the input stream.
            */
            pub fn new(input: Reader) -> IoResult<Parser> {
                let mut parser: Parser;
                parser.input = input;
                match parser.read_id() {
                    Ok(val) => parser.id = val,
                    Err(err) => return err,
                }
                match parser.read_size() {
                    Ok(val) => parser.size = val,
                    Err(err) => return err
                }
            }

            /*
            Get next the next node after this one in the given input stream.
            */
            pub fn next(&self) -> Option<IoError> {
            }

            /*
            Get the subnode below this one, if any exists (returns IoError on failure)
            */
            pub fn down(&self) -> Option<IoError> {
            }

            /*
            Get the current depth in the Element tree
            */
            pub fn level(&self) -> u32 {}

            /*
            Get the value of this node
            */
            pub fn value(input: &Reader) -> IoResult<Value> {
            }

            /*
            Helper function to read an id from the stream
            */
            fn read_id(&self) -> IoResult<u32> {
                // read first byte
                let u8 = match self.input.read_byte() {
                    Ok(val) => val,
                    Err(err) => return err, // TODO: will this actually return from fn? is there a better way to format this block?
                }
                // TODO: Count zeroes to get number of trailing bytes
                // TODO: Read trailing bytes
            }

            /*
            Helper function to read size from the stream
            */
            fn read_size(&self) -> IoResult<u64> {
            }
        }
    }
}
<commit_msg>Implemented the read_id helper method and make a basic test.<commit_after>/*
* A basic EBML parser for Rust. Gives methods for both approaches; full parsing
* of an EBML file in-memory or incremental sequential parsing of nodes for
* environments that are more memory-constrained.
*
* The full parser allows you to get all sub-elements of a node in one call,
* because each node has a reference to the data it contains. All of the data is
* loaded into memory when the root node is parsed.
*
* The PartialElement only reads the data it needs to get the header of any
* single element. So if the data source is a file the full parser will load the
* whole file to memory, while the partial parser will only load at most one leaf
* node's value plus its id and size.
*
* The partial parser stores the offset of each node in the input stream, which
* is then used to jump to the node's data in the stream. This may cause the
* partial parser to do more random seeking.
*/

//extern crate time;
//use std::io::Memreader;
//use time::Timespec;

mod rebml {
    use time::Timespec;
    enum Value {
		Uint(u64),
		Int(i64),
		Str(String),
		DateTimespec),
		Bin(&[u8]),
        SubElement,
		Nil, // Empty element
	}

    mod incremental {
        use std::io::{IoResult,IoError};
        pub struct Parser {
            input: &Reader,
            id: u32,
            size: u64
        }

        impl Parser {
            /*
            Create new EBML Parser and read in the first tag, if any. Expects the stream to start with the top-level
            EBML tag [1A][45][DF][A3]. Consumes the input stream.
            */
            pub fn new(input: Reader) -> IoResult<Parser> {
                let mut parser: Parser;
                parser.input = input;
                parser.id = try!(self.read_id());
                parser.size = try!(self.read_size());
                return parser;
            }

            /*
            Get next the next node after this one in the given input stream.
            */
            pub fn next(&self) -> Option<IoError> {
            }

            /*
            Get the subnode below this one, if any exists (returns IoError on failure)
            */
            pub fn down(&self) -> Option<IoError> {
            }

            /*
            Get the current depth in the Element tree
            */
            pub fn level(&self) -> u32 {}

            /*
            Get the value of this node
            */
            pub fn value(input: &Reader) -> IoResult<Value> {
            }

            /*
            Helper function to extract the (remaining) byte count for a UTF-8-like value
            */
            fn byte_count(firstbyte: &u8) -> u8 {
                let mut mask = 0x80;
                let mut bytecount = 0;
                while firstbyte & mask == 0 {
                    firstbyte = firstbyte << 1;
                    bytecount += 1;
                }
                return bytecount;
            }

            /*
            Helper function to read an id from the stream
            */
            fn read_id(&self) -> IoResult<u32> {
                // read first byte
                let firstbyte = try!(self.input.read_byte());
                // Count zeroes to get number of trailing bytes
                let mut count = byte_count(firstbyte);
                let mut offset = 24;
                let mut id: u32 = firstbyte as u32 << offset;
                // TODO: Read trailing bytes and add them to the id
				let bytes = try!(self.input.read_exact(count));
				// functional method?
				id += bytes.iter()
				.zip(range_step(16, -1, -8))
				.fold(|acc, (i, o)| i as u32 << o);
				return id;
            }

            /*
            Helper function to read size from the stream
            */
            fn read_size(&self) -> IoResult<u64> {
            }
        }
    }

    [#test]
    fn test_new() {
		let bytes = vec![0x1Au8, 0x45, 0xDF, 0xA3, 0x80];
		let buf = BufReader::new(bytes)
		assert!(Parser::new(buf).is_ok());
	}
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

/*!
Bindings and wrappers for __GLib__
*/

extern crate libc;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate gio_sys as gio_ffi;

use libc::c_char;

pub use self::app_info::AppInfo;
pub use self::list::{List, Elem, RevElem};
pub use self::slist::{SList, SElem};
pub use self::glib_container::GlibContainer;
pub use self::error::{Error};
pub use self::permission::Permission;
pub use self::source::{Continue, idle_add, timeout_add, timeout_add_seconds};
pub use self::traits::FFIGObject;
pub use self::value::{Value, ValuePublic};
pub use types::Type;
pub use self::date::{TimeVal, Time, Date, Year, Month, Weekday, Day};

#[macro_use]
pub mod wrapper;
#[macro_use]
pub mod boxed;
#[macro_use]
pub mod refcounted;
#[macro_use]
pub mod object;

mod app_info;
mod list;
mod slist;
pub mod glib_container;
mod error;
mod permission;
pub mod signal;
pub mod source;
pub mod traits;
pub mod translate;
mod value;

pub mod types;
pub mod date;

pub fn to_gboolean(b: bool) -> glib_ffi::gboolean {
    match b {
        true => glib_ffi::GTRUE,
        false => glib_ffi::GFALSE
    }
}

pub fn to_bool(b: glib_ffi::gboolean) -> bool {
    b != glib_ffi::GFALSE
}

// An opaque structure used as the base of all interface types.
pub struct TypeInterface;

// An opaque structure used as the base of all type instances.
pub struct TypeInstance;

// An opaque structure used as the base of all classes.
pub struct TypeClass;

//FIXME: Check if this is actually correct (maybe not since ParamFlags is deprecated)
#[derive(Clone, Copy)]
pub enum ParamFlags{
    Readable,
    Writable,
    ReadWrite,
    Construct,
    ConstructOnly,
    LaxValidation,
    StaticName,
    Private,
    StaticNick,
    StaticBlurb,
    Deprecated
}

#[repr(C)]
pub struct ParamSpec {
    g_type_instance: TypeInstance,
    name: *mut c_char,
    flags: ParamFlags,
    value_type: glib_ffi::GType,
    owner_type: glib_ffi::GType,
}
<commit_msg>Reexport Object at the top level<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

/*!
Bindings and wrappers for __GLib__
*/

extern crate libc;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate gio_sys as gio_ffi;

use libc::c_char;

pub use self::app_info::AppInfo;
pub use self::list::{List, Elem, RevElem};
pub use self::slist::{SList, SElem};
pub use self::glib_container::GlibContainer;
pub use self::error::{Error};
pub use self::object::Object;
pub use self::permission::Permission;
pub use self::source::{Continue, idle_add, timeout_add, timeout_add_seconds};
pub use self::traits::FFIGObject;
pub use self::value::{Value, ValuePublic};
pub use types::Type;
pub use self::date::{TimeVal, Time, Date, Year, Month, Weekday, Day};

#[macro_use]
pub mod wrapper;
#[macro_use]
pub mod boxed;
#[macro_use]
pub mod refcounted;
#[macro_use]
pub mod object;

mod app_info;
mod list;
mod slist;
pub mod glib_container;
mod error;
mod permission;
pub mod signal;
pub mod source;
pub mod traits;
pub mod translate;
mod value;

pub mod types;
pub mod date;

pub fn to_gboolean(b: bool) -> glib_ffi::gboolean {
    match b {
        true => glib_ffi::GTRUE,
        false => glib_ffi::GFALSE
    }
}

pub fn to_bool(b: glib_ffi::gboolean) -> bool {
    b != glib_ffi::GFALSE
}

// An opaque structure used as the base of all interface types.
pub struct TypeInterface;

// An opaque structure used as the base of all type instances.
pub struct TypeInstance;

// An opaque structure used as the base of all classes.
pub struct TypeClass;

//FIXME: Check if this is actually correct (maybe not since ParamFlags is deprecated)
#[derive(Clone, Copy)]
pub enum ParamFlags{
    Readable,
    Writable,
    ReadWrite,
    Construct,
    ConstructOnly,
    LaxValidation,
    StaticName,
    Private,
    StaticNick,
    StaticBlurb,
    Deprecated
}

#[repr(C)]
pub struct ParamSpec {
    g_type_instance: TypeInstance,
    name: *mut c_char,
    flags: ParamFlags,
    value_type: glib_ffi::GType,
    owner_type: glib_ffi::GType,
}
<|endoftext|>


<commit_before>// Copyright 2015 Sam Doshi (sam@metal-fish.co.uk)
//
// Licensed under the MIT License <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

//! Midi types and traits for Rust

#![feature(globs, phase)]

#[cfg(test)] extern crate test;
#[cfg(test)] #[phase(plugin)] extern crate quickcheck_macros;
#[cfg(test)] extern crate quickcheck;

pub use types::{Channel, U7, U14};
pub use Channel::{Ch1,  Ch2,  Ch3,  Ch4,  Ch5,  Ch6,  Ch7,  Ch8,
                  Ch9,  Ch10, Ch11, Ch12, Ch13, Ch14, Ch15, Ch16};
pub use raw_message::RawMessage;
pub use RawMessage::{Status, StatusData, StatusDataData, Raw};
pub use message::Message;
pub use Message::{Start, TimingClock, Continue, Stop, ActiveSensing, SystemReset,
                  AllSoundOff, ResetAllControllers, LocalControlOff, LocalControlOn,
                  AllNotesOff, NoteOff,
                  ProgramChange, ControlChange, RPN7, RPN14, NRPN7, NRPN14,
                  SysEx, NoteOn, PitchBend, PolyphonicPressure, ChannelPressure};
pub use manufacturer::Manufacturer;
pub use to_raw_messages::ToRawMessages;

pub mod constants;
pub mod utils;

mod types;
mod raw_message;
mod message;
mod manufacturer;
mod to_raw_messages;

<commit_msg>update to latest rust<commit_after>// Copyright 2015 Sam Doshi (sam@metal-fish.co.uk)
//
// Licensed under the MIT License <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

//! Midi types and traits for Rust

#![feature(plugin)]

#[cfg(test)] extern crate test;
#[cfg(test)] #[plugin] #[no_link] extern crate quickcheck_macros;
#[cfg(test)] extern crate quickcheck;

pub use types::{Channel, U7, U14};
pub use Channel::{Ch1,  Ch2,  Ch3,  Ch4,  Ch5,  Ch6,  Ch7,  Ch8,
                  Ch9,  Ch10, Ch11, Ch12, Ch13, Ch14, Ch15, Ch16};
pub use raw_message::RawMessage;
pub use RawMessage::{Status, StatusData, StatusDataData, Raw};
pub use message::Message;
pub use Message::{Start, TimingClock, Continue, Stop, ActiveSensing, SystemReset,
                  AllSoundOff, ResetAllControllers, LocalControlOff, LocalControlOn,
                  AllNotesOff, NoteOff,
                  ProgramChange, ControlChange, RPN7, RPN14, NRPN7, NRPN14,
                  SysEx, NoteOn, PitchBend, PolyphonicPressure, ChannelPressure};
pub use manufacturer::Manufacturer;
pub use to_raw_messages::ToRawMessages;

pub mod constants;
pub mod utils;

mod types;
mod raw_message;
mod message;
mod manufacturer;
mod to_raw_messages;

<|endoftext|>


<commit_before>extern crate regex;

use std::ascii::*;
use regex::Regex;

mod cases;
// mod classcase;
// mod camelcase;
// mod snakecase;
// mod kebabcase;

use cases::classcase::to_class_case;
use cases::classcase::is_class_case;

use cases::camelcase::to_camel_case;
use cases::camelcase::is_camel_case;

use cases::snakecase::to_snake_case;
use cases::snakecase::is_snake_case;

use cases::kebabcase::to_kebab_case;
use cases::kebabcase::is_kebab_case;

#[test] #[allow(non_snake_case)]
fn returns_truthy_value_for_is_class_case_when_class() {
    let mock_string: String = "DataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_class_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == true);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_class_case_when_kebab() {
    let mock_string: String = "data-mapper-string-that-is-really-really-long".to_string();
    let asserted_bool: bool = is_class_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_class_case_when_camel() {
    let mock_string: String = "dataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_class_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_class_case_when_snake() {
    let mock_string: String = "data_mapper_string_that_is_really_really_long".to_string();
    let asserted_bool: bool = is_class_case(mock_string);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_camel_case_when_kebab() {
    let mock_string: String = "data-mapper-string-that-is-really-really-long".to_string();
    let asserted_bool: bool = is_camel_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_camel_case_when_class() {
    let mock_string: String = "DataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_camel_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_truthy_value_for_is_camel_case_when_camel() {
    let mock_string: String = "dataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_camel_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == true);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_camel_case_when_snake() {
    let mock_string: String = "data_mapper_string_that_is_really_really_long".to_string();
    let asserted_bool: bool = is_camel_case(mock_string);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_truthy_value_for_is_kebab_case_when_kebab() {
    let mock_string: String = "data-mapper-string-that-is-really-really-long".to_string();
    let asserted_bool: bool = is_kebab_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == true);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_kebab_case_when_class() {
    let mock_string: String = "DataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_kebab_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_kebab_case_when_camel() {
    let mock_string: String = "dataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_kebab_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_kebab_case_when_snake() {
    let mock_string: String = "data_mapper_string_that_is_really_really_long".to_string();
    let asserted_bool: bool = is_kebab_case(mock_string);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_snake_case_when_kebab() {
    let mock_string: String = "data-mapper-string-that-is-really-really-long".to_string();
    let asserted_bool: bool = is_snake_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_snake_case_when_class() {
    let mock_string: String = "DataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_snake_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_snake_case_when_camel() {
    let mock_string: String = "dataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_snake_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_truthy_value_for_is_snake_case_when_snake() {
    let mock_string: String = "data_mapper_string_that_is_really_really_long".to_string();
    let asserted_bool: bool = is_snake_case(mock_string);
    assert!(asserted_bool == true);
}

#[test] #[allow(non_snake_case)]
fn ClassCase_data_mapper_as_DataMapper() {
    let mock_string: String = "data_mapper".to_string();
    let expected_string: String = "DataMapper".to_string();
    let asserted_string: String = to_class_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn camelize_data_mapper_as_dataMapper() {
    let mock_string: String = "data_mapper".to_string();
    let expected_string: String = "dataMapper".to_string();
    let asserted_string: String = to_camel_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn snake_case_dataMapper_as_data_mapper() {
    let mock_string: String = "DataMapper".to_string();
    let expected_string: String = "data_mapper".to_string();
    let asserted_string: String = to_snake_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn kebab_case_data_mapper_as_data_mapper() {
    let mock_string: String = "data_mapper".to_string();
    let expected_string: String = "data-mapper".to_string();
    let asserted_string: String = to_kebab_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn kebab_case_DataMapper_as_data_mapper() {
    let mock_string: String = "DataMapper".to_string();
    let expected_string: String = "data-mapper".to_string();
    let asserted_string: String = to_kebab_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn kebab_case_dataMapper_as_data_mapper() {
    let mock_string: String = "dataMapper".to_string();
    let expected_string: String = "data-mapper".to_string();
    let asserted_string: String = to_kebab_case(mock_string);
    assert!(asserted_string == expected_string);
}
<commit_msg>Removed commented code<commit_after>extern crate regex;

use std::ascii::*;
use regex::Regex;

mod cases;

use cases::classcase::to_class_case;
use cases::classcase::is_class_case;

use cases::camelcase::to_camel_case;
use cases::camelcase::is_camel_case;

use cases::snakecase::to_snake_case;
use cases::snakecase::is_snake_case;

use cases::kebabcase::to_kebab_case;
use cases::kebabcase::is_kebab_case;

#[test] #[allow(non_snake_case)]
fn returns_truthy_value_for_is_class_case_when_class() {
    let mock_string: String = "DataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_class_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == true);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_class_case_when_kebab() {
    let mock_string: String = "data-mapper-string-that-is-really-really-long".to_string();
    let asserted_bool: bool = is_class_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_class_case_when_camel() {
    let mock_string: String = "dataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_class_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_class_case_when_snake() {
    let mock_string: String = "data_mapper_string_that_is_really_really_long".to_string();
    let asserted_bool: bool = is_class_case(mock_string);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_camel_case_when_kebab() {
    let mock_string: String = "data-mapper-string-that-is-really-really-long".to_string();
    let asserted_bool: bool = is_camel_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_camel_case_when_class() {
    let mock_string: String = "DataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_camel_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_truthy_value_for_is_camel_case_when_camel() {
    let mock_string: String = "dataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_camel_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == true);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_camel_case_when_snake() {
    let mock_string: String = "data_mapper_string_that_is_really_really_long".to_string();
    let asserted_bool: bool = is_camel_case(mock_string);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_truthy_value_for_is_kebab_case_when_kebab() {
    let mock_string: String = "data-mapper-string-that-is-really-really-long".to_string();
    let asserted_bool: bool = is_kebab_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == true);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_kebab_case_when_class() {
    let mock_string: String = "DataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_kebab_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_kebab_case_when_camel() {
    let mock_string: String = "dataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_kebab_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_kebab_case_when_snake() {
    let mock_string: String = "data_mapper_string_that_is_really_really_long".to_string();
    let asserted_bool: bool = is_kebab_case(mock_string);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_snake_case_when_kebab() {
    let mock_string: String = "data-mapper-string-that-is-really-really-long".to_string();
    let asserted_bool: bool = is_snake_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_snake_case_when_class() {
    let mock_string: String = "DataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_snake_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_falsey_value_for_is_snake_case_when_camel() {
    let mock_string: String = "dataMapperIsAReallyReallyLongString".to_string();
    let asserted_bool: bool = is_snake_case(mock_string);
    println!("{}",asserted_bool);
    assert!(asserted_bool == false);
}

#[test] #[allow(non_snake_case)]
fn returns_truthy_value_for_is_snake_case_when_snake() {
    let mock_string: String = "data_mapper_string_that_is_really_really_long".to_string();
    let asserted_bool: bool = is_snake_case(mock_string);
    assert!(asserted_bool == true);
}

#[test] #[allow(non_snake_case)]
fn ClassCase_data_mapper_as_DataMapper() {
    let mock_string: String = "data_mapper".to_string();
    let expected_string: String = "DataMapper".to_string();
    let asserted_string: String = to_class_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn camelize_data_mapper_as_dataMapper() {
    let mock_string: String = "data_mapper".to_string();
    let expected_string: String = "dataMapper".to_string();
    let asserted_string: String = to_camel_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn snake_case_dataMapper_as_data_mapper() {
    let mock_string: String = "DataMapper".to_string();
    let expected_string: String = "data_mapper".to_string();
    let asserted_string: String = to_snake_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn kebab_case_data_mapper_as_data_mapper() {
    let mock_string: String = "data_mapper".to_string();
    let expected_string: String = "data-mapper".to_string();
    let asserted_string: String = to_kebab_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn kebab_case_DataMapper_as_data_mapper() {
    let mock_string: String = "DataMapper".to_string();
    let expected_string: String = "data-mapper".to_string();
    let asserted_string: String = to_kebab_case(mock_string);
    assert!(asserted_string == expected_string);
}

#[test] #[allow(non_snake_case)]
fn kebab_case_dataMapper_as_data_mapper() {
    let mock_string: String = "dataMapper".to_string();
    let expected_string: String = "data-mapper".to_string();
    let asserted_string: String = to_kebab_case(mock_string);
    assert!(asserted_string == expected_string);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    let mut br = BotRouter {
        bots: HashMap::new(),
        output_bins: HashMap::new(),
    };

    for line in input.lines() {
        br.exec_command(line);
    }
    0
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum BotOrOutput {
    Bot,
    Output,
}

#[derive(PartialEq, Debug)]
pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
    low: Option<usize>,
    low_bot_or_output: Option<BotOrOutput>,
    high: Option<usize>,
    high_bot_or_output: Option<BotOrOutput>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
            low: None, high: None,
            low_bot_or_output: None,
            high_bot_or_output: None,
        }
    }

    pub fn receive_chip(&mut self, chip: usize)
           -> Vec<(usize, BotOrOutput, usize)> {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
            vec![]
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
            if let (Some(lo), Some(hi)) = (self.low, self.high) {
                println!("bot {} has 2 chips; low to {:?} {}, high to {:?} {}", self.key, self.low_bot_or_output, lo, self.high_bot_or_output, hi);
                let return_commands = if self.chip1 < self.chip2 {
                    println!("bot {} finds {:?} < {:?}", self.key, self.chip1, self.chip2);
                    if self.chip1 == Some(17) && self.chip2 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                    ]
                } else {
                    println!("bot {} finds {:?} < {:?}", self.key, self.chip2, self.chip1);
                    if self.chip2 == Some(17) && self.chip1 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                    ]
                };
                self.chip1 = None;
                self.chip2 = None;
                self.low = None;
                self.high = None;
                self.low_bot_or_output = None;
                self.high_bot_or_output = None;
                return_commands
            } else {
                vec![]
            }
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn receive_command(&mut self, low_bot_or_output: &str, low: usize,
                                      high_bot_or_output: &str, high: usize) {
        println!("bot {} storing command low to {} {}, high to {} {}", self.key, low_bot_or_output, low, high_bot_or_output, high);
        self.low = Some(low);
        if low_bot_or_output == "bot" {
            self.low_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.low_bot_or_output = Some(BotOrOutput::Output);
        }
        self.high = Some(high);
        if high_bot_or_output == "bot" {
            self.high_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.high_bot_or_output = Some(BotOrOutput::Output);
        }
    }
}

pub struct BotRouter {
    bots: HashMap<usize, Bot>,
    output_bins: HashMap<usize, Vec<usize>>,
}

impl BotRouter {
    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("ROUTER sending value {} to bot {}", value, bot_key);
        let return_commands = self.bots
                                  .entry(bot_key)
                                  .or_insert(Bot::new(bot_key))
                                  .receive_chip(value);
        for &(key, bot_or_output, chip_value) in return_commands.iter() {
            match bot_or_output {
                BotOrOutput::Bot => self.value_to_bot(key, chip_value),
                BotOrOutput::Output => self.value_to_output(key, chip_value),
            }
        }
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("ROUTER sending value {} to output {}", value, output_key);
        self.output_bins.entry(output_key).or_insert(Vec::new()).push(value);
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                          low_bot_or_output: &str, low_key: usize,
                          high_bot_or_output: &str, high_key: usize) {
        let bot = self.bots.entry(bot_key).or_insert(Bot::new(bot_key));
        bot.receive_command(
            low_bot_or_output,
            low_key,
            high_bot_or_output,
            high_key
        );
    }
}

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

    #[test]
    fn router_can_give_values() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            Some(5)
        );
    }

    #[test]
    fn router_can_give_commands_that_get_stored() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        assert_eq!(
            br.bots.get(&2).unwrap().low,
            Some(1)
        );
        assert_eq!(
            br.bots.get(&2).unwrap().high,
            Some(0)
        );
    }

    #[test]
    fn router_adds_two_values_so_commands_get_executed() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            None
        );
        assert_eq!(
            br.bots.get(&2).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&1).unwrap().chip1,
            Some(2)
        );
        assert_eq!(
            br.bots.get(&1).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&0).unwrap().chip1,
            Some(5)
        );
        assert_eq!(
            br.bots.get(&0).unwrap().chip2,
            None
        );
    }

    #[test]
    fn test_sample() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.output_bins.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.output_bins.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.output_bins.get(&2),
            Some(&vec![3])
        )
    }
}
<commit_msg>Revert "Remove test/fn not doing anything"<commit_after>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    let mut br = BotRouter {
        bots: HashMap::new(),
        output_bins: HashMap::new(),
    };

    for line in input.lines() {
        br.exec_command(line);
    }
    0
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum BotOrOutput {
    Bot,
    Output,
}

#[derive(PartialEq, Debug)]
pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
    low: Option<usize>,
    low_bot_or_output: Option<BotOrOutput>,
    high: Option<usize>,
    high_bot_or_output: Option<BotOrOutput>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
            low: None, high: None,
            low_bot_or_output: None,
            high_bot_or_output: None,
        }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }

    pub fn receive_chip(&mut self, chip: usize)
           -> Vec<(usize, BotOrOutput, usize)> {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
            vec![]
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
            if let (Some(lo), Some(hi)) = (self.low, self.high) {
                println!("bot {} has 2 chips; low to {:?} {}, high to {:?} {}", self.key, self.low_bot_or_output, lo, self.high_bot_or_output, hi);
                let return_commands = if self.chip1 < self.chip2 {
                    println!("bot {} finds {:?} < {:?}", self.key, self.chip1, self.chip2);
                    if self.chip1 == Some(17) && self.chip2 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                    ]
                } else {
                    println!("bot {} finds {:?} < {:?}", self.key, self.chip2, self.chip1);
                    if self.chip2 == Some(17) && self.chip1 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                    ]
                };
                self.chip1 = None;
                self.chip2 = None;
                self.low = None;
                self.high = None;
                self.low_bot_or_output = None;
                self.high_bot_or_output = None;
                return_commands
            } else {
                vec![]
            }
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn receive_command(&mut self, low_bot_or_output: &str, low: usize,
                                      high_bot_or_output: &str, high: usize) {
        println!("bot {} storing command low to {} {}, high to {} {}", self.key, low_bot_or_output, low, high_bot_or_output, high);
        self.low = Some(low);
        if low_bot_or_output == "bot" {
            self.low_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.low_bot_or_output = Some(BotOrOutput::Output);
        }
        self.high = Some(high);
        if high_bot_or_output == "bot" {
            self.high_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.high_bot_or_output = Some(BotOrOutput::Output);
        }
    }
}

pub struct BotRouter {
    bots: HashMap<usize, Bot>,
    output_bins: HashMap<usize, Vec<usize>>,
}

impl BotRouter {
    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("ROUTER sending value {} to bot {}", value, bot_key);
        let return_commands = self.bots
                                  .entry(bot_key)
                                  .or_insert(Bot::new(bot_key))
                                  .receive_chip(value);
        for &(key, bot_or_output, chip_value) in return_commands.iter() {
            match bot_or_output {
                BotOrOutput::Bot => self.value_to_bot(key, chip_value),
                BotOrOutput::Output => self.value_to_output(key, chip_value),
            }
        }
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("ROUTER sending value {} to output {}", value, output_key);
        self.output_bins.entry(output_key).or_insert(Vec::new()).push(value);
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                          low_bot_or_output: &str, low_key: usize,
                          high_bot_or_output: &str, high_key: usize) {
        let bot = self.bots.entry(bot_key).or_insert(Bot::new(bot_key));
        bot.receive_command(
            low_bot_or_output,
            low_key,
            high_bot_or_output,
            high_key
        );
    }
}

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

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new(0);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_a_chip_still_not_two() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        assert!( ! bot.has_two_chips() );
    }

    #[test]
    fn bot_gets_two_chips() {
        let mut bot = Bot::new(0);
        bot.receive_chip(1);
        bot.receive_chip(4);
        assert!(bot.has_two_chips());
    }

    #[test]
    fn router_can_give_values() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            Some(5)
        );
    }

    #[test]
    fn router_can_give_commands_that_get_stored() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        assert_eq!(
            br.bots.get(&2).unwrap().low,
            Some(1)
        );
        assert_eq!(
            br.bots.get(&2).unwrap().high,
            Some(0)
        );
    }

    #[test]
    fn router_adds_two_values_so_commands_get_executed() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            None
        );
        assert_eq!(
            br.bots.get(&2).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&1).unwrap().chip1,
            Some(2)
        );
        assert_eq!(
            br.bots.get(&1).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&0).unwrap().chip1,
            Some(5)
        );
        assert_eq!(
            br.bots.get(&0).unwrap().chip2,
            None
        );
    }

    #[test]
    fn test_sample() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.output_bins.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.output_bins.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.output_bins.get(&2),
            Some(&vec![3])
        )
    }
}
<|endoftext|>