<commit_before>pub use super::super::elf::rela::*;

// Stupid 32 bit binaries have Rel too, because 4 extra bytes for every relocation for an addend of 0 was prohibitive back in 1906.
// I think 32-bit binaries are stupid relics from the past in case that wasn't clear
#[repr(C)]
#[derive(Clone, PartialEq, Default)]
#[cfg_attr(not(feature = "pure"), derive(Debug))]
pub struct Rel {
    r_offset: u32, // address
    r_info: u32, // relocation type and symbol address
}

#[repr(C)]
#[derive(Clone, PartialEq, Default)]
#[cfg_attr(not(feature = "pure"), derive(Debug))]
pub struct Rela {
    pub r_offset: u32, // Address
    pub r_info: u32, // Relocation type and symbol index
    pub r_addend: i32, // Addend
}

pub const SIZEOF_RELA: usize = 4 + 4 + 4;

#[inline(always)]
pub fn r_sym(info: u32) -> u32 {
    info >> 8
}

#[inline(always)]
pub fn r_type(info: u32) -> u32 {
    info & 0xff
}

#[inline(always)]
pub fn r_info(sym: u32, typ: u32) -> u32 {
    (sym << 8) + (typ & 0xff)
}
<commit_msg>elf32: add pub to rel :]<commit_after>pub use super::super::elf::rela::*;

// Stupid 32 bit binaries have Rel too, because 4 extra bytes for every relocation for an addend of 0 was prohibitive back in 1906.
// I think 32-bit binaries are stupid relics from the past in case that wasn't clear
#[repr(C)]
#[derive(Clone, PartialEq, Default)]
#[cfg_attr(not(feature = "pure"), derive(Debug))]
pub struct Rel {
    pub r_offset: u32, // address
    pub r_info: u32, // relocation type and symbol address
}

#[repr(C)]
#[derive(Clone, PartialEq, Default)]
#[cfg_attr(not(feature = "pure"), derive(Debug))]
pub struct Rela {
    pub r_offset: u32, // Address
    pub r_info: u32, // Relocation type and symbol index
    pub r_addend: i32, // Addend
}

pub const SIZEOF_RELA: usize = 4 + 4 + 4;

#[inline(always)]
pub fn r_sym(info: u32) -> u32 {
    info >> 8
}

#[inline(always)]
pub fn r_type(info: u32) -> u32 {
    info & 0xff
}

#[inline(always)]
pub fn r_info(sym: u32, typ: u32) -> u32 {
    (sym << 8) + (typ & 0xff)
}
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

#[cfg(feature = "serde")]
#[doc(hidden)]
#[macro_export]
macro_rules! add_serde_if_enabled {
    ($(#[$attr:meta])* -- $i:item) => {
        $(#[$attr])*
        #[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
        $i
    }
}

#[cfg(not(feature = "serde"))]
#[doc(hidden)]
#[macro_export]
macro_rules! add_serde_if_enabled {
    ($(#[$attr:meta])* -- $i:item) => {
        $(#[$attr])*
        $i
    }
}

/// The main macro that creates RPC services.
///
/// Rpc methods are specified, mirroring trait syntax:
///
/// ```
/// # #![feature(await_macro, pin, arbitrary_self_types, async_await, futures_api, proc_macro_hygiene)]
/// # fn main() {}
/// # tarpc::service! {
/// /// Say hello
/// rpc hello(name: String) -> String;
/// # }
/// ```
///
/// Attributes can be attached to each rpc. These attributes
/// will then be attached to the generated service traits'
/// corresponding `fn`s, as well as to the client stubs' RPCs.
///
/// The following items are expanded in the enclosing module:
///
/// * `trait Service` -- defines the RPC service.
///   * `fn serve` -- turns a service impl into a request handler.
/// * `Client` -- a client stub with a fn for each RPC.
///   * `fn new_stub` -- creates a new Client stub.
///
#[macro_export]
macro_rules! service {
// Entry point
    (
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) $(-> $out:ty)*;
        )*
    ) => {
        $crate::service! {{
            $(
                $(#[$attr])*
                rpc $fn_name( $( $arg : $in_ ),* ) $(-> $out)*;
            )*
        }}
    };
// Pattern for when the next rpc has an implicit unit return type.
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* );

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        $crate::service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> ();
        }
    };
// Pattern for when the next rpc has an explicit return type.
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        $crate::service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out;
        }
    };
// Pattern for when all return types have been expanded
    (
        { } // none left to expand
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident ( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
        )*
    ) => {
        $crate::add_serde_if_enabled! {
            /// The request sent over the wire from the client to the server.
            #[derive(Debug)]
            #[allow(non_camel_case_types, unused)]
            --
            pub enum Request {
                $(
                    $(#[$attr])*
                    $fn_name{ $($arg: $in_,)* }
                ),*
            }
        }

        $crate::add_serde_if_enabled! {
            /// The response sent over the wire from the server to the client.
            #[derive(Debug)]
            #[allow(non_camel_case_types, unused)]
            --
            pub enum Response {
                $(
                    $(#[$attr])*
                    $fn_name($out)
                ),*
            }
        }

        // TODO: proc_macro can't currently parse $crate, so this needs to be imported for the
        // usage of snake_to_camel! to work.
        use $crate::futures::Future as Future__;

        /// Defines the RPC service. The additional trait bounds are required so that services can
        /// multiplex requests across multiple tasks, potentially on multiple threads.
        pub trait Service: Clone + Send + 'static {
            $(
                $crate::snake_to_camel! {
                    /// The type of future returned by `{}`.
                    type $fn_name: Future__<Output = $out> + Send;
                }

                $(#[$attr])*
                fn $fn_name(&self, ctx: $crate::context::Context, $($arg:$in_),*) -> $crate::ty_snake_to_camel!(Self::$fn_name);
            )*
        }

        // TODO: use an existential type instead of this when existential types work.
        /// A future resolving to a server [`Response`].
        #[allow(non_camel_case_types)]
        pub enum ResponseFut<S: Service> {
            $(
                $(#[$attr])*
                $fn_name($crate::ty_snake_to_camel!(<S as Service>::$fn_name)),
            )*
        }

        impl<S: Service> ::std::fmt::Debug for ResponseFut<S> {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                fmt.debug_struct("Response").finish()
            }
        }

        impl<S: Service> ::std::future::Future for ResponseFut<S> {
            type Output = ::std::io::Result<Response>;

            fn poll(self: ::std::pin::Pin<&mut Self>, waker: &::std::task::LocalWaker)
                -> ::std::task::Poll<::std::io::Result<Response>>
            {
                unsafe {
                    match ::std::pin::Pin::get_mut_unchecked(self) {
                        $(
                            ResponseFut::$fn_name(resp) =>
                                ::std::pin::Pin::new_unchecked(resp)
                                    .poll(waker)
                                    .map(Response::$fn_name)
                                    .map(Ok),
                        )*
                    }
                }
            }
        }

        /// Returns a serving function to use with rpc::server::Server.
        pub fn serve<S: Service>(service: S)
            -> impl FnMut($crate::context::Context, Request) -> ResponseFut<S> + Send + 'static + Clone {
                move |ctx, req| {
                    match req {
                        $(
                            Request::$fn_name{ $($arg,)* } => {
                                let resp = Service::$fn_name(&mut service.clone(), ctx, $($arg),*);
                                ResponseFut::$fn_name(resp)
                            }
                        )*
                    }
                }
            }

        #[allow(unused)]
        #[derive(Clone, Debug)]
        /// The client stub that makes RPC calls to the server. Exposes a Future interface.
        pub struct Client($crate::client::Client<Request, Response>);

        /// Returns a new client stub that sends requests over the given transport.
        pub async fn new_stub<T>(config: $crate::client::Config, transport: T)
            -> ::std::io::Result<Client>
        where
            T: $crate::Transport<
                    Item = $crate::Response<Response>,
                    SinkItem = $crate::ClientMessage<Request>> + Send,
        {
            Ok(Client(await!($crate::client::Client::new(config, transport))?))
        }

        impl Client {
            $(
                #[allow(unused)]
                $(#[$attr])*
                pub fn $fn_name(&mut self, ctx: $crate::context::Context, $($arg: $in_),*)
                    -> impl ::std::future::Future<Output = ::std::io::Result<$out>> + '_ {
                    let request__ = Request::$fn_name { $($arg,)* };
                    let resp = self.0.call(ctx, request__);
                    async move {
                        match await!(resp)? {
                            Response::$fn_name(msg__) => ::std::result::Result::Ok(msg__),
                            _ => unreachable!(),
                        }
                    }
                }
            )*
        }
    }
}

// allow dead code; we're just testing that the macro expansion compiles
#[allow(dead_code)]
#[cfg(test)]
mod syntax_test {
    service! {
        #[deny(warnings)]
        #[allow(non_snake_case)]
        rpc TestCamelCaseDoesntConflict();
        rpc hello() -> String;
        #[doc="attr"]
        rpc attr(s: String) -> String;
        rpc no_args_no_return();
        rpc no_args() -> ();
        rpc one_arg(foo: String) -> i32;
        rpc two_args_no_return(bar: String, baz: u64);
        rpc two_args(bar: String, baz: u64) -> String;
        rpc no_args_ret_error() -> i32;
        rpc one_arg_ret_error(foo: String) -> String;
        rpc no_arg_implicit_return_error();
        #[doc="attr"]
        rpc one_arg_implicit_return_error(foo: String);
    }
}

#[cfg(test)]
mod functional_test {
    use futures::{
        compat::TokioDefaultSpawner,
        future::{ready, Ready},
        prelude::*,
    };
    use rpc::{
        client, context,
        server::{self, Handler},
        transport::channel,
    };
    use std::io;
    use tokio::runtime::current_thread;

    service! {
        rpc add(x: i32, y: i32) -> i32;
        rpc hey(name: String) -> String;
    }

    #[derive(Clone)]
    struct Server;

    impl Service for Server {
        type AddFut = Ready<i32>;

        fn add(&self, _: context::Context, x: i32, y: i32) -> Self::AddFut {
            ready(x + y)
        }

        type HeyFut = Ready<String>;

        fn hey(&self, _: context::Context, name: String) -> Self::HeyFut {
            ready(format!("Hey, {}.", name))
        }
    }

    #[test]
    fn sequential() {
        let _ = env_logger::try_init();
        rpc::init(TokioDefaultSpawner);

        let test = async {
            let (tx, rx) = channel::unbounded();
            tokio_executor::spawn(
                rpc::Server::new(server::Config::default())
                    .incoming(stream::once(ready(Ok(rx))))
                    .respond_with(serve(Server))
                    .unit_error()
                    .boxed()
                    .compat()
            );

            let mut client = await!(new_stub(client::Config::default(), tx))?;
            assert_eq!(3, await!(client.add(context::current(), 1, 2))?);
            assert_eq!(
                "Hey, Tim.",
                await!(client.hey(context::current(), "Tim".to_string()))?
            );
            Ok::<_, io::Error>(())
        }
            .map_err(|e| panic!(e.to_string()));

        current_thread::block_on_all(test.boxed().compat()).unwrap();
    }

    #[test]
    fn concurrent() {
        let _ = env_logger::try_init();
        rpc::init(TokioDefaultSpawner);

        let test = async {
            let (tx, rx) = channel::unbounded();
            tokio_executor::spawn(
                rpc::Server::new(server::Config::default())
                    .incoming(stream::once(ready(Ok(rx))))
                    .respond_with(serve(Server))
                    .unit_error()
                    .boxed()
                    .compat()
            );

            let client = await!(new_stub(client::Config::default(), tx))?;
            let mut c = client.clone();
            let req1 = c.add(context::current(), 1, 2);
            let mut c = client.clone();
            let req2 = c.add(context::current(), 3, 4);
            let mut c = client.clone();
            let req3 = c.hey(context::current(), "Tim".to_string());

            assert_eq!(3, await!(req1)?);
            assert_eq!(7, await!(req2)?);
            assert_eq!("Hey, Tim.", await!(req3)?);
            Ok::<_, io::Error>(())
        }
            .map_err(|e| panic!("test failed: {}", e));

        current_thread::block_on_all(test.boxed().compat()).unwrap();
    }
}
<commit_msg>Don't allow empty service invocations<commit_after>// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

#[cfg(feature = "serde")]
#[doc(hidden)]
#[macro_export]
macro_rules! add_serde_if_enabled {
    ($(#[$attr:meta])* -- $i:item) => {
        $(#[$attr])*
        #[derive($crate::serde::Serialize, $crate::serde::Deserialize)]
        $i
    }
}

#[cfg(not(feature = "serde"))]
#[doc(hidden)]
#[macro_export]
macro_rules! add_serde_if_enabled {
    ($(#[$attr:meta])* -- $i:item) => {
        $(#[$attr])*
        $i
    }
}

/// The main macro that creates RPC services.
///
/// Rpc methods are specified, mirroring trait syntax:
///
/// ```
/// # #![feature(await_macro, pin, arbitrary_self_types, async_await, futures_api, proc_macro_hygiene)]
/// # fn main() {}
/// # tarpc::service! {
/// /// Say hello
/// rpc hello(name: String) -> String;
/// # }
/// ```
///
/// Attributes can be attached to each rpc. These attributes
/// will then be attached to the generated service traits'
/// corresponding `fn`s, as well as to the client stubs' RPCs.
///
/// The following items are expanded in the enclosing module:
///
/// * `trait Service` -- defines the RPC service.
///   * `fn serve` -- turns a service impl into a request handler.
/// * `Client` -- a client stub with a fn for each RPC.
///   * `fn new_stub` -- creates a new Client stub.
///
#[macro_export]
macro_rules! service {
    () => {
        compile_error!("Must define at least one RPC method.");
    };
// Entry point
    (
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) $(-> $out:ty)*;
        )*
    ) => {
        $crate::service! {{
            $(
                $(#[$attr])*
                rpc $fn_name( $( $arg : $in_ ),* ) $(-> $out)*;
            )*
        }}
    };
// Pattern for when the next rpc has an implicit unit return type.
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* );

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        $crate::service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> ();
        }
    };
// Pattern for when the next rpc has an explicit return type.
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        $crate::service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out;
        }
    };
// Pattern for when all return types have been expanded
    (
        { } // none left to expand
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident ( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
        )*
    ) => {
        $crate::add_serde_if_enabled! {
            /// The request sent over the wire from the client to the server.
            #[derive(Debug)]
            #[allow(non_camel_case_types, unused)]
            --
            pub enum Request {
                $(
                    $(#[$attr])*
                    $fn_name{ $($arg: $in_,)* }
                ),*
            }
        }

        $crate::add_serde_if_enabled! {
            /// The response sent over the wire from the server to the client.
            #[derive(Debug)]
            #[allow(non_camel_case_types, unused)]
            --
            pub enum Response {
                $(
                    $(#[$attr])*
                    $fn_name($out)
                ),*
            }
        }

        // TODO: proc_macro can't currently parse $crate, so this needs to be imported for the
        // usage of snake_to_camel! to work.
        use $crate::futures::Future as Future__;

        /// Defines the RPC service. The additional trait bounds are required so that services can
        /// multiplex requests across multiple tasks, potentially on multiple threads.
        pub trait Service: Clone + Send + 'static {
            $(
                $crate::snake_to_camel! {
                    /// The type of future returned by `{}`.
                    type $fn_name: Future__<Output = $out> + Send;
                }

                $(#[$attr])*
                fn $fn_name(&self, ctx: $crate::context::Context, $($arg:$in_),*) -> $crate::ty_snake_to_camel!(Self::$fn_name);
            )*
        }

        // TODO: use an existential type instead of this when existential types work.
        /// A future resolving to a server [`Response`].
        #[allow(non_camel_case_types)]
        pub enum ResponseFut<S: Service> {
            $(
                $(#[$attr])*
                $fn_name($crate::ty_snake_to_camel!(<S as Service>::$fn_name)),
            )*
        }

        impl<S: Service> ::std::fmt::Debug for ResponseFut<S> {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                fmt.debug_struct("Response").finish()
            }
        }

        impl<S: Service> ::std::future::Future for ResponseFut<S> {
            type Output = ::std::io::Result<Response>;

            fn poll(self: ::std::pin::Pin<&mut Self>, waker: &::std::task::LocalWaker)
                -> ::std::task::Poll<::std::io::Result<Response>>
            {
                unsafe {
                    match ::std::pin::Pin::get_mut_unchecked(self) {
                        $(
                            ResponseFut::$fn_name(resp) =>
                                ::std::pin::Pin::new_unchecked(resp)
                                    .poll(waker)
                                    .map(Response::$fn_name)
                                    .map(Ok),
                        )*
                    }
                }
            }
        }

        /// Returns a serving function to use with rpc::server::Server.
        pub fn serve<S: Service>(service: S)
            -> impl FnMut($crate::context::Context, Request) -> ResponseFut<S> + Send + 'static + Clone {
                move |ctx, req| {
                    match req {
                        $(
                            Request::$fn_name{ $($arg,)* } => {
                                let resp = Service::$fn_name(&mut service.clone(), ctx, $($arg),*);
                                ResponseFut::$fn_name(resp)
                            }
                        )*
                    }
                }
            }

        #[allow(unused)]
        #[derive(Clone, Debug)]
        /// The client stub that makes RPC calls to the server. Exposes a Future interface.
        pub struct Client($crate::client::Client<Request, Response>);

        /// Returns a new client stub that sends requests over the given transport.
        pub async fn new_stub<T>(config: $crate::client::Config, transport: T)
            -> ::std::io::Result<Client>
        where
            T: $crate::Transport<
                    Item = $crate::Response<Response>,
                    SinkItem = $crate::ClientMessage<Request>> + Send,
        {
            Ok(Client(await!($crate::client::Client::new(config, transport))?))
        }

        impl Client {
            $(
                #[allow(unused)]
                $(#[$attr])*
                pub fn $fn_name(&mut self, ctx: $crate::context::Context, $($arg: $in_),*)
                    -> impl ::std::future::Future<Output = ::std::io::Result<$out>> + '_ {
                    let request__ = Request::$fn_name { $($arg,)* };
                    let resp = self.0.call(ctx, request__);
                    async move {
                        match await!(resp)? {
                            Response::$fn_name(msg__) => ::std::result::Result::Ok(msg__),
                            _ => unreachable!(),
                        }
                    }
                }
            )*
        }
    }
}

// allow dead code; we're just testing that the macro expansion compiles
#[allow(dead_code)]
#[cfg(test)]
mod syntax_test {
    service! {
        #[deny(warnings)]
        #[allow(non_snake_case)]
        rpc TestCamelCaseDoesntConflict();
        rpc hello() -> String;
        #[doc="attr"]
        rpc attr(s: String) -> String;
        rpc no_args_no_return();
        rpc no_args() -> ();
        rpc one_arg(foo: String) -> i32;
        rpc two_args_no_return(bar: String, baz: u64);
        rpc two_args(bar: String, baz: u64) -> String;
        rpc no_args_ret_error() -> i32;
        rpc one_arg_ret_error(foo: String) -> String;
        rpc no_arg_implicit_return_error();
        #[doc="attr"]
        rpc one_arg_implicit_return_error(foo: String);
    }
}

#[cfg(test)]
mod functional_test {
    use futures::{
        compat::TokioDefaultSpawner,
        future::{ready, Ready},
        prelude::*,
    };
    use rpc::{
        client, context,
        server::{self, Handler},
        transport::channel,
    };
    use std::io;
    use tokio::runtime::current_thread;

    service! {
        rpc add(x: i32, y: i32) -> i32;
        rpc hey(name: String) -> String;
    }

    #[derive(Clone)]
    struct Server;

    impl Service for Server {
        type AddFut = Ready<i32>;

        fn add(&self, _: context::Context, x: i32, y: i32) -> Self::AddFut {
            ready(x + y)
        }

        type HeyFut = Ready<String>;

        fn hey(&self, _: context::Context, name: String) -> Self::HeyFut {
            ready(format!("Hey, {}.", name))
        }
    }

    #[test]
    fn sequential() {
        let _ = env_logger::try_init();
        rpc::init(TokioDefaultSpawner);

        let test = async {
            let (tx, rx) = channel::unbounded();
            tokio_executor::spawn(
                rpc::Server::new(server::Config::default())
                    .incoming(stream::once(ready(Ok(rx))))
                    .respond_with(serve(Server))
                    .unit_error()
                    .boxed()
                    .compat()
            );

            let mut client = await!(new_stub(client::Config::default(), tx))?;
            assert_eq!(3, await!(client.add(context::current(), 1, 2))?);
            assert_eq!(
                "Hey, Tim.",
                await!(client.hey(context::current(), "Tim".to_string()))?
            );
            Ok::<_, io::Error>(())
        }
            .map_err(|e| panic!(e.to_string()));

        current_thread::block_on_all(test.boxed().compat()).unwrap();
    }

    #[test]
    fn concurrent() {
        let _ = env_logger::try_init();
        rpc::init(TokioDefaultSpawner);

        let test = async {
            let (tx, rx) = channel::unbounded();
            tokio_executor::spawn(
                rpc::Server::new(server::Config::default())
                    .incoming(stream::once(ready(Ok(rx))))
                    .respond_with(serve(Server))
                    .unit_error()
                    .boxed()
                    .compat()
            );

            let client = await!(new_stub(client::Config::default(), tx))?;
            let mut c = client.clone();
            let req1 = c.add(context::current(), 1, 2);
            let mut c = client.clone();
            let req2 = c.add(context::current(), 3, 4);
            let mut c = client.clone();
            let req3 = c.hey(context::current(), "Tim".to_string());

            assert_eq!(3, await!(req1)?);
            assert_eq!(7, await!(req2)?);
            assert_eq!("Hey, Tim.", await!(req3)?);
            Ok::<_, io::Error>(())
        }
            .map_err(|e| panic!("test failed: {}", e));

        current_thread::block_on_all(test.boxed().compat()).unwrap();
    }
}
<|endoftext|>


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

//! The frame module provides a structred way to send and receive
//! message through streams.
//!
//! ## Data Framing
//!
//! ```ignore
//! 0                   1                   2                   3
//! 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//! | Frame Start   |  Payload Len                  |  Payload  |
//! +-----------------------------------------------------------+
//! |           Payload Data Continued          |   Frame End   |
//! +-----------------------------------------------------------+
//!
//! Start Frame:    8 bits (must be 0x01)
//! Payload Len:    16 bits
//! Payload Data:   Payload Len bytes
//! End Frame:      8 bits (must be 0x17)
//! ```

use std::mem;
use std::any::Any;
use std::default::Default;

use super::Frame;

bitflags! {
    flags FrameGuard: u8 {
        const START     = 0b0000_0001,
        const END       = 0b0000_1111
    }
}

#[derive(Clone)]
pub struct SimpleFrame {
    start_guard: FrameGuard,
    payload_len: u16,
    payload: Vec<u8>,
    end_guard: FrameGuard
}

impl Frame for SimpleFrame {

    #[allow(unused_variables)]
    fn new<T: Any>(buf: &[u8], args: &Vec<T>) -> Self {
        SimpleFrame {
            start_guard: START,
            payload_len: buf.len() as u16,
            payload: buf.to_vec(),
            end_guard: END
        }
    }

    fn to_bytes(&self) -> Vec<u8> {
        let payload_len = self.payload_len as u16;
        let len: usize = self.payload_len as usize + 4;
        let mut buf = Vec::<u8>::with_capacity(len);

        buf.push(self.start_guard.bits());
        buf.push((payload_len >> 8) as u8);
        buf.push(payload_len as u8);
        buf.extend_from_slice(&self.payload[..]);
        buf.push(self.end_guard.bits());

        buf
    }

    fn from_bytes(buf: &mut Vec<u8>) -> Option<Box<Self>> {
        if buf.len() < 5 {
            return None;
        }

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

        // Starting frame guard
        match FrameGuard::from_bits(buf[0]) {
            Some(start_guard) => {
                frame.start_guard = start_guard;
            }
            None => {
                error!("First byte was not expected start byte. Buffer corrupted?: {}", buf[0]);
            }
        }

        // Payload length
        let mask = 0xFFFFu16;
        let mut payload_len = ((buf[1] as u16) << 8) & mask;
        payload_len |= buf[2] as u16;
        frame.payload_len = payload_len;

        let payload_len = payload_len as usize;
        if buf.len() - 4 < payload_len {
            return None;
        }

        // Payload data
        frame.payload.extend_from_slice(&buf[3..(payload_len + 3)]);

        // Ending frame guard
        match FrameGuard::from_bits(buf[payload_len + 3]) {
            Some(end_guard) => {
                frame.end_guard = end_guard;
            }
            None => {
                error!("Last byte was not expected end byte. Buffer corrupted? {}",
                       buf[payload_len + 3]);
                return None;
            }
        }

        // Remove frame from buffer
        let mut remainder = Vec::<u8>::with_capacity(buf.len() - frame.len_as_vec());
        remainder.extend_from_slice(&buf[frame.len_as_vec()..buf.len()]);
        mem::swap(buf, &mut remainder);

        Some(Box::new(frame))
    }

    fn len_as_vec(&self) -> usize {
        self.payload_len as usize + 4
    }
}

impl Default for SimpleFrame {
    fn default() -> SimpleFrame {
        SimpleFrame {
            start_guard: START,
            payload_len: 0u16,
            payload: Vec::<u8>::new(),
            end_guard: END
        }
    }
}
<commit_msg>Fixed bad end guard for simpleframe.<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

//! The frame module provides a structred way to send and receive
//! message through streams.
//!
//! ## Data Framing
//!
//! ```ignore
//! 0                   1                   2                   3
//! 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//! | Frame Start   |  Payload Len                  |  Payload  |
//! +-----------------------------------------------------------+
//! |           Payload Data Continued          |   Frame End   |
//! +-----------------------------------------------------------+
//!
//! Start Frame:    8 bits (must be 0x01)
//! Payload Len:    16 bits
//! Payload Data:   Payload Len bytes
//! End Frame:      8 bits (must be 0x17)
//! ```

use std::mem;
use std::any::Any;
use std::default::Default;

use super::Frame;

bitflags! {
    flags FrameGuard: u8 {
        const START     = 0b0000_0001,
        const END       = 0b0001_0111
    }
}

#[derive(Clone)]
pub struct SimpleFrame {
    start_guard: FrameGuard,
    payload_len: u16,
    payload: Vec<u8>,
    end_guard: FrameGuard
}

impl Frame for SimpleFrame {

    #[allow(unused_variables)]
    fn new<T: Any>(buf: &[u8], args: &Vec<T>) -> Self {
        SimpleFrame {
            start_guard: START,
            payload_len: buf.len() as u16,
            payload: buf.to_vec(),
            end_guard: END
        }
    }

    fn to_bytes(&self) -> Vec<u8> {
        let payload_len = self.payload_len as u16;
        let len: usize = self.payload_len as usize + 4;
        let mut buf = Vec::<u8>::with_capacity(len);

        buf.push(self.start_guard.bits());
        buf.push((payload_len >> 8) as u8);
        buf.push(payload_len as u8);
        buf.extend_from_slice(&self.payload[..]);
        buf.push(self.end_guard.bits());

        buf
    }

    fn from_bytes(buf: &mut Vec<u8>) -> Option<Box<Self>> {
        if buf.len() < 5 {
            return None;
        }

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

        // Starting frame guard
        match FrameGuard::from_bits(buf[0]) {
            Some(start_guard) => {
                frame.start_guard = start_guard;
            }
            None => {
                error!("First byte was not expected start byte. Buffer corrupted?: {}", buf[0]);
            }
        }

        // Payload length
        let mask = 0xFFFFu16;
        let mut payload_len = ((buf[1] as u16) << 8) & mask;
        payload_len |= buf[2] as u16;
        frame.payload_len = payload_len;

        let payload_len = payload_len as usize;
        if buf.len() - 4 < payload_len {
            return None;
        }

        // Payload data
        frame.payload.extend_from_slice(&buf[3..(payload_len + 3)]);

        // Ending frame guard
        match FrameGuard::from_bits(buf[payload_len + 3]) {
            Some(end_guard) => {
                frame.end_guard = end_guard;
            }
            None => {
                error!("Last byte was not expected end byte. Buffer corrupted? {}",
                       buf[payload_len + 3]);
                return None;
            }
        }

        // Remove frame from buffer
        let mut remainder = Vec::<u8>::with_capacity(buf.len() - frame.len_as_vec());
        remainder.extend_from_slice(&buf[frame.len_as_vec()..buf.len()]);
        mem::swap(buf, &mut remainder);

        Some(Box::new(frame))
    }

    fn len_as_vec(&self) -> usize {
        self.payload_len as usize + 4
    }
}

impl Default for SimpleFrame {
    fn default() -> SimpleFrame {
        SimpleFrame {
            start_guard: START,
            payload_len: 0u16,
            payload: Vec::<u8>::new(),
            end_guard: END
        }
    }
}
<|endoftext|>


<commit_before>#![feature(core, collections, old_io, libc, std_misc, plugin, unicode)]
#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

#![plugin(docopt_macros)]

extern crate docopt;
extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate "union-find" as union_find;
extern crate term;

use std::default::Default;
use std::old_io::stdio;
use board::Board;
use locale::Category;

mod board;
mod geom;
mod locale;
mod pprint;
mod solver;
mod util;

docopt! {
    Args derive Debug, "
Usage: slither [options]
       slither --help

Options:
  -h, --help       Show this message.
  --width WIDTH    Specify cell width.
  --height HEIGHT  Specify cell height.
  --mode MODE      Specify pretty print mode.
                   Valid values: ascii, unicode.
  --cjk CJK        Specify pretty print char width.
                   Valid values: auto, yes, no.
",
    flag_width: Option<Width>,
    flag_height: Option<Height>,
    flag_mode: Option<pprint::Mode>,
    flag_cjk: Option<YesNo>
}

#[derive(Debug)]
struct Width(usize);
impl rustc_serialize::Decodable for Width {
    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Width, D::Error> {
        let w = try!(d.read_usize());
        if w == 0 {
            Err(d.error(&format!("Could not decode '{}' as width.", w)))
        } else {
            Ok(Width(w))
        }
    }
}
impl Default for Width {
    fn default() -> Width { Width(2) }
}

#[derive(Debug)]
struct Height(usize);
impl rustc_serialize::Decodable for Height {
    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Height, D::Error> {
        let h = try!(d.read_usize());
        if h == 0 {
            Err(d.error(&format!("Could not decode '{}' as height.", h)))
        } else {
            Ok(Height(h))
        }
    }
}
impl Default for Height {
    fn default() -> Height { Height(1) }
}

#[derive(Copy, Debug, RustcDecodable, Eq, PartialEq)]
pub enum YesNo {
    Auto, Yes, No,
}
impl Default for YesNo {
    fn default() -> YesNo { YesNo::Auto }
}

fn main() {
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    let raw_input = stdio::stdin().read_to_end().unwrap();
    let input = String::from_utf8(raw_input).unwrap();
    let board = input.parse::<Board>().unwrap();
    let board = solver::solve(&board).unwrap();

    if stdio::stdout_raw().isatty() {
        let is_cjk = match args.flag_cjk.unwrap_or_default() {
            YesNo::Yes => true,
            YesNo::No => false,
            YesNo::Auto => {
                let loc = locale::setlocale(Category::CType, "");
                loc.starts_with("ja") || loc.starts_with("ko") || loc.starts_with("zh")
            }
        };

        let conf = pprint::Config {
            mode: args.flag_mode.unwrap_or_default(),
            is_cjk: is_cjk,
            cell_width: args.flag_width.unwrap_or_default().0,
            cell_height: args.flag_height.unwrap_or_default().0
        };
        let _ = pprint::print(&conf, &board);
    } else {
        print!("{}", board.to_string());
    }
}
<commit_msg>update to rustc 1.0.0-nightly (2fc8b1e7c 2015-03-07) (built 2015-03-08)<commit_after>#![feature(core, collections, old_io, libc, plugin, unicode)]
#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

#![plugin(docopt_macros)]

extern crate docopt;
extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate "union-find" as union_find;
extern crate term;

use std::default::Default;
use std::old_io::stdio;
use board::Board;
use locale::Category;

mod board;
mod geom;
mod locale;
mod pprint;
mod solver;
mod util;

docopt! {
    Args derive Debug, "
Usage: slither [options]
       slither --help

Options:
  -h, --help       Show this message.
  --width WIDTH    Specify cell width.
  --height HEIGHT  Specify cell height.
  --mode MODE      Specify pretty print mode.
                   Valid values: ascii, unicode.
  --cjk CJK        Specify pretty print char width.
                   Valid values: auto, yes, no.
",
    flag_width: Option<Width>,
    flag_height: Option<Height>,
    flag_mode: Option<pprint::Mode>,
    flag_cjk: Option<YesNo>
}

#[derive(Debug)]
struct Width(usize);
impl rustc_serialize::Decodable for Width {
    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Width, D::Error> {
        let w = try!(d.read_usize());
        if w == 0 {
            Err(d.error(&format!("Could not decode '{}' as width.", w)))
        } else {
            Ok(Width(w))
        }
    }
}
impl Default for Width {
    fn default() -> Width { Width(2) }
}

#[derive(Debug)]
struct Height(usize);
impl rustc_serialize::Decodable for Height {
    fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Height, D::Error> {
        let h = try!(d.read_usize());
        if h == 0 {
            Err(d.error(&format!("Could not decode '{}' as height.", h)))
        } else {
            Ok(Height(h))
        }
    }
}
impl Default for Height {
    fn default() -> Height { Height(1) }
}

#[derive(Copy, Debug, RustcDecodable, Eq, PartialEq)]
pub enum YesNo {
    Auto, Yes, No,
}
impl Default for YesNo {
    fn default() -> YesNo { YesNo::Auto }
}

fn main() {
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    let raw_input = stdio::stdin().read_to_end().unwrap();
    let input = String::from_utf8(raw_input).unwrap();
    let board = input.parse::<Board>().unwrap();
    let board = solver::solve(&board).unwrap();

    if stdio::stdout_raw().isatty() {
        let is_cjk = match args.flag_cjk.unwrap_or_default() {
            YesNo::Yes => true,
            YesNo::No => false,
            YesNo::Auto => {
                let loc = locale::setlocale(Category::CType, "");
                loc.starts_with("ja") || loc.starts_with("ko") || loc.starts_with("zh")
            }
        };

        let conf = pprint::Config {
            mode: args.flag_mode.unwrap_or_default(),
            is_cjk: is_cjk,
            cell_width: args.flag_width.unwrap_or_default().0,
            cell_height: args.flag_height.unwrap_or_default().0
        };
        let _ = pprint::print(&conf, &board);
    } else {
        print!("{}", board.to_string());
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

mod convert;

pub use convert::{FromLossy, IntoLossy};

use log::error;

pub fn convert<T, U>(item: T) -> U
where
    T: IntoLossy<U>,
{
    item.into_lossy()
}

include!(concat!(env!("OUT_DIR"), "/grr.rs"));

impl From<bool> for DataBlob {

    fn from(value: bool) -> DataBlob {
        DataBlob {
            boolean: Some(value),
            ..Default::default()
        }
    }
}

impl From<i64> for DataBlob {

    fn from(value: i64) -> DataBlob {
        DataBlob {
            integer: Some(value),
            ..Default::default()
        }
    }
}

impl From<f32> for DataBlob {

    fn from(value: f32) -> DataBlob {
        DataBlob {
            float: Some(value),
            ..Default::default()
        }
    }
}

impl From<Vec<u8>> for DataBlob {

    fn from(value: Vec<u8>) -> DataBlob {
        DataBlob {
            data: Some(value),
            ..Default::default()
        }
    }
}

impl From<String> for DataBlob {

    fn from(value: String) -> DataBlob  {
        DataBlob {
            string: Some(value),
            ..Default::default()
        }
    }
}

impl KeyValue {

    /// Creates an empty key-value.
    ///
    /// Both the key and the value are going to be equal to `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::empty();
    /// assert_eq!(entry.k, None);
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn empty() -> KeyValue {
        KeyValue {
            k: None,
            v: None,
        }
    }

    /// Creates a key-value pair.
    ///
    /// Both the key and the value are going to be equal to the given values.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::pair(String::from("foo"), 42i64);
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("foo")));
    /// assert_eq!(entry.v.unwrap().integer, Some(42));
    /// ```
    pub fn pair<K, V>(key: K, value: V) -> KeyValue
    where
        K: Into<DataBlob>,
        V: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: Some(value.into()),
        }
    }

    /// Creates a key-only key-value.
    ///
    /// The key is going to be equal to the given value and the key will be
    /// `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::key(String::from("quux"));
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("quux")));
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn key<K>(key: K) -> KeyValue
    where
        K: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: None,
        }
    }
}

impl std::iter::FromIterator<KeyValue> for AttributedDict {

    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = KeyValue>,
    {
        AttributedDict {
            dat: iter.into_iter().collect(),
        }
    }
}

impl<K, V> std::iter::FromIterator<(K, V)> for AttributedDict
where
    K: Into<DataBlob>,
    V: Into<DataBlob>,
{
    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let pair = |(key, value)| KeyValue::pair(key, value);
        iter.into_iter().map(pair).collect()
    }
}

impl FromLossy<std::fs::Metadata> for StatEntry {

    fn from_lossy(metadata: std::fs::Metadata) -> StatEntry {
        use std::convert::{TryFrom, TryInto};
        #[cfg(target_family = "unix")]
        use std::os::unix::fs::MetadataExt;

        // TODO: Fix definition of `StatEntry`.
        // `StatEntry` defines insufficient integer width for some fields. For
        // now we just ignore errors, but the definition should be improved.
        let some = |value: u64| Some(value.try_into().unwrap_or(0));

        let atime_secs = match metadata.accessed().ok().map(secs) {
            Some(Ok(atime_secs)) => Some(atime_secs),
            Some(Err(err)) => {
                error!("failed to convert access time: {}", err);
                None
            },
            None => None,
        };

        let mtime_secs = match metadata.modified().ok().map(secs) {
            Some(Ok(mtime_secs)) => Some(mtime_secs),
            Some(Err(err)) => {
                error!("failed to convert modification time: {}", err);
                None
            },
            None => None,
        };

        #[cfg(target_family = "unix")]
        let ctime_secs = match u64::try_from(metadata.ctime()) {
            Ok(ctime_secs) => Some(ctime_secs),
            Err(err) => {
                error!("negative inode change time: {}", err);
                None
            },
        };

        let crtime_secs = match metadata.created().ok().map(secs) {
            Some(Ok(crtime_secs)) => Some(crtime_secs),
            Some(Err(err)) => {
                error!("failed to convert creation time: {}", err);
                None
            },
            None => None,
        };

        StatEntry {
            #[cfg(target_family = "unix")]
            st_mode: Some(metadata.mode().into()),
            #[cfg(target_family = "unix")]
            st_ino: some(metadata.ino()),
            #[cfg(target_family = "unix")]
            st_dev: some(metadata.dev()),
            #[cfg(target_family = "unix")]
            st_rdev: some(metadata.rdev()),
            #[cfg(target_family = "unix")]
            st_nlink: some(metadata.nlink()),
            #[cfg(target_family = "unix")]
            st_uid: Some(metadata.uid()),
            #[cfg(target_family = "unix")]
            st_gid: Some(metadata.gid()),
            st_size: Some(metadata.len()),
            st_atime: atime_secs,
            st_mtime: mtime_secs,
            #[cfg(target_family = "unix")]
            st_ctime: ctime_secs,
            st_crtime: crtime_secs,
            #[cfg(target_family = "unix")]
            st_blocks: some(metadata.blocks()),
            #[cfg(target_family = "unix")]
            st_blksize: some(metadata.blksize()),
            ..Default::default()
        }
    }
}

/// An error type for failures of converting timestamps to microseconds.
#[derive(Clone, Debug)]
pub enum MicrosError {
    /// Attempted to convert pre-epoch system time.
    Epoch(std::time::SystemTimeError),
    /// Attempted to convert a value outside of 64-bit unsigned integer range.
    Overflow(std::num::TryFromIntError),
}

impl std::fmt::Display for MicrosError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => {
                write!(fmt, "pre-epoch system time: {}", error)
            }
            Overflow(ref error) => {
                write!(fmt, "system time value too big: {}", error)
            }
        }
    }
}

impl std::error::Error for MicrosError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => Some(error),
            Overflow(ref error) => Some(error),
        }
    }
}

impl From<std::time::SystemTimeError> for MicrosError {

    fn from(error: std::time::SystemTimeError) -> MicrosError {
        MicrosError::Epoch(error)
    }
}

impl From<std::num::TryFromIntError> for MicrosError {

    fn from(error: std::num::TryFromIntError) -> MicrosError {
        MicrosError::Overflow(error)
    }
}

/// An error type for failures of converting timestamps to seconds.
#[derive(Clone, Debug)]
pub struct SecsError {
    error: MicrosError,
}

impl std::fmt::Display for SecsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(fmt)
    }
}

impl From<MicrosError> for SecsError {

    fn from(error: MicrosError) -> SecsError {
        SecsError {
            error: error,
        }
    }
}

impl From<SecsError> for MicrosError {

    fn from(error: SecsError) -> MicrosError {
        error.error
    }
}

/// Converts system time into epoch microseconds.
///
/// Because most GRR messages use epoch microseconds for representing timestamps
/// this function be be useful to convert from more idiomatic representations.
///
/// # Examples
///
/// ```
/// use rrg_proto::micros;
///
/// assert_eq!(micros(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn micros(time: std::time::SystemTime) -> Result<u64, MicrosError> {
    let time_micros = time.duration_since(std::time::UNIX_EPOCH)?.as_micros();
    Ok(std::convert::TryInto::try_into(time_micros)?)
}

/// Converts system time into epoch seconds.
///
/// Some GRR messages use epoch seconds for representing timestamps. In such
/// cases this function can be useful to convert from more idiomatic types.
///
/// # Examples
///
/// ```
/// use rrg_proto::secs;
///
/// assert_eq!(secs(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn secs(time: std::time::SystemTime) -> Result<u64, SecsError> {
    Ok(micros(time)? / 1_000_000)
}
<commit_msg>Improve error handling for file timestamps.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

mod convert;

pub use convert::{FromLossy, IntoLossy};

use log::error;

pub fn convert<T, U>(item: T) -> U
where
    T: IntoLossy<U>,
{
    item.into_lossy()
}

include!(concat!(env!("OUT_DIR"), "/grr.rs"));

impl From<bool> for DataBlob {

    fn from(value: bool) -> DataBlob {
        DataBlob {
            boolean: Some(value),
            ..Default::default()
        }
    }
}

impl From<i64> for DataBlob {

    fn from(value: i64) -> DataBlob {
        DataBlob {
            integer: Some(value),
            ..Default::default()
        }
    }
}

impl From<f32> for DataBlob {

    fn from(value: f32) -> DataBlob {
        DataBlob {
            float: Some(value),
            ..Default::default()
        }
    }
}

impl From<Vec<u8>> for DataBlob {

    fn from(value: Vec<u8>) -> DataBlob {
        DataBlob {
            data: Some(value),
            ..Default::default()
        }
    }
}

impl From<String> for DataBlob {

    fn from(value: String) -> DataBlob  {
        DataBlob {
            string: Some(value),
            ..Default::default()
        }
    }
}

impl KeyValue {

    /// Creates an empty key-value.
    ///
    /// Both the key and the value are going to be equal to `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::empty();
    /// assert_eq!(entry.k, None);
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn empty() -> KeyValue {
        KeyValue {
            k: None,
            v: None,
        }
    }

    /// Creates a key-value pair.
    ///
    /// Both the key and the value are going to be equal to the given values.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::pair(String::from("foo"), 42i64);
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("foo")));
    /// assert_eq!(entry.v.unwrap().integer, Some(42));
    /// ```
    pub fn pair<K, V>(key: K, value: V) -> KeyValue
    where
        K: Into<DataBlob>,
        V: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: Some(value.into()),
        }
    }

    /// Creates a key-only key-value.
    ///
    /// The key is going to be equal to the given value and the key will be
    /// `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::key(String::from("quux"));
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("quux")));
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn key<K>(key: K) -> KeyValue
    where
        K: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: None,
        }
    }
}

impl std::iter::FromIterator<KeyValue> for AttributedDict {

    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = KeyValue>,
    {
        AttributedDict {
            dat: iter.into_iter().collect(),
        }
    }
}

impl<K, V> std::iter::FromIterator<(K, V)> for AttributedDict
where
    K: Into<DataBlob>,
    V: Into<DataBlob>,
{
    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let pair = |(key, value)| KeyValue::pair(key, value);
        iter.into_iter().map(pair).collect()
    }
}

impl FromLossy<std::fs::Metadata> for StatEntry {

    fn from_lossy(metadata: std::fs::Metadata) -> StatEntry {
        use std::convert::{TryFrom, TryInto};
        #[cfg(target_family = "unix")]
        use std::os::unix::fs::MetadataExt;

        // TODO: Fix definition of `StatEntry`.
        // `StatEntry` defines insufficient integer width for some fields. For
        // now we just ignore errors, but the definition should be improved.
        let some = |value: u64| Some(value.try_into().unwrap_or(0));

        // TODO: Move this into some utility module.
        // TODO: Add support for other log types.
        macro_rules! ack {
            { $expr:expr, error: $message:literal } => {
                match $expr {
                    Ok(value) => Some(value),
                    Err(err) => {
                        ::log::error!(concat!($message, ": {}"), err);
                        None
                    },
                }
            };
        }

        let atime_secs = ack! {
            metadata.accessed(),
            error: "failed to obtain file access time"
        }.and_then(|atime| ack! {
            secs(atime),
            error: "failed to convert access time to seconds"
        });

        let mtime_secs = ack! {
            metadata.modified(),
            error: "failed to obtain file modification time"
        }.and_then(|mtime| ack! {
            secs(mtime),
            error: "failed to convert modification time to seconds"
        });

        let crtime_secs = ack! {
            metadata.created(),
            error: "failed to obtain file creation time"
        }.and_then(|crtime| ack! {
            secs(crtime),
            error: "failed to convert creation time to seconds"
        });

        #[cfg(target_family = "unix")]
        let ctime_secs = match u64::try_from(metadata.ctime()) {
            Ok(ctime_secs) => Some(ctime_secs),
            Err(err) => {
                error!("negative inode change time: {}", err);
                None
            },
        };

        StatEntry {
            #[cfg(target_family = "unix")]
            st_mode: Some(metadata.mode().into()),
            #[cfg(target_family = "unix")]
            st_ino: some(metadata.ino()),
            #[cfg(target_family = "unix")]
            st_dev: some(metadata.dev()),
            #[cfg(target_family = "unix")]
            st_rdev: some(metadata.rdev()),
            #[cfg(target_family = "unix")]
            st_nlink: some(metadata.nlink()),
            #[cfg(target_family = "unix")]
            st_uid: Some(metadata.uid()),
            #[cfg(target_family = "unix")]
            st_gid: Some(metadata.gid()),
            st_size: Some(metadata.len()),
            st_atime: atime_secs,
            st_mtime: mtime_secs,
            #[cfg(target_family = "unix")]
            st_ctime: ctime_secs,
            st_crtime: crtime_secs,
            #[cfg(target_family = "unix")]
            st_blocks: some(metadata.blocks()),
            #[cfg(target_family = "unix")]
            st_blksize: some(metadata.blksize()),
            ..Default::default()
        }
    }
}

/// An error type for failures of converting timestamps to microseconds.
#[derive(Clone, Debug)]
pub enum MicrosError {
    /// Attempted to convert pre-epoch system time.
    Epoch(std::time::SystemTimeError),
    /// Attempted to convert a value outside of 64-bit unsigned integer range.
    Overflow(std::num::TryFromIntError),
}

impl std::fmt::Display for MicrosError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => {
                write!(fmt, "pre-epoch system time: {}", error)
            }
            Overflow(ref error) => {
                write!(fmt, "system time value too big: {}", error)
            }
        }
    }
}

impl std::error::Error for MicrosError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => Some(error),
            Overflow(ref error) => Some(error),
        }
    }
}

impl From<std::time::SystemTimeError> for MicrosError {

    fn from(error: std::time::SystemTimeError) -> MicrosError {
        MicrosError::Epoch(error)
    }
}

impl From<std::num::TryFromIntError> for MicrosError {

    fn from(error: std::num::TryFromIntError) -> MicrosError {
        MicrosError::Overflow(error)
    }
}

/// An error type for failures of converting timestamps to seconds.
#[derive(Clone, Debug)]
pub struct SecsError {
    error: MicrosError,
}

impl std::fmt::Display for SecsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(fmt)
    }
}

impl From<MicrosError> for SecsError {

    fn from(error: MicrosError) -> SecsError {
        SecsError {
            error: error,
        }
    }
}

impl From<SecsError> for MicrosError {

    fn from(error: SecsError) -> MicrosError {
        error.error
    }
}

/// Converts system time into epoch microseconds.
///
/// Because most GRR messages use epoch microseconds for representing timestamps
/// this function be be useful to convert from more idiomatic representations.
///
/// # Examples
///
/// ```
/// use rrg_proto::micros;
///
/// assert_eq!(micros(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn micros(time: std::time::SystemTime) -> Result<u64, MicrosError> {
    let time_micros = time.duration_since(std::time::UNIX_EPOCH)?.as_micros();
    Ok(std::convert::TryInto::try_into(time_micros)?)
}

/// Converts system time into epoch seconds.
///
/// Some GRR messages use epoch seconds for representing timestamps. In such
/// cases this function can be useful to convert from more idiomatic types.
///
/// # Examples
///
/// ```
/// use rrg_proto::secs;
///
/// assert_eq!(secs(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn secs(time: std::time::SystemTime) -> Result<u64, SecsError> {
    Ok(micros(time)? / 1_000_000)
}
<|endoftext|>


<commit_before>fn main() {
    let x = 3;

    if x < 4 {
        println!("Number less than 4!");
    } else {
        println!("Number equal to or greater than 4!");
    }
}
<commit_msg>Multiple if statements example<commit_after>fn main() {
    let x = 9;

    if x < 4 {
        println!("Number less than 4!");
    } else if x > 10 {
        println!("Number greater than 10!");
    } else {
        println!("Number between 4 and 10!");
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io::{self, Cursor};
use std::net::TcpStream;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};

const MAX_CHUNK_SIZE: usize = 65535;

pub struct ChunkedStream {
    socket: TcpStream,
    raw: Cursor<Vec<u8>>,
    output_buffer: Vec<u8>,
    output_size: usize,
}

impl ChunkedStream {
    pub fn new(socket: TcpStream) -> Self {
        ChunkedStream {
            socket: socket,
            raw: Cursor::new(Vec::new()),
            output_buffer: Vec::new(),
            output_size: 0,
        }
    }
}

// based on https://github.com/neo4j/neo4j-python-driver/blob/1.0/neo4j/v1/connection.py
impl Write for ChunkedStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut b = buf;

        loop {
            let size = b.len();
            let future_size = self.output_size + size;

            if future_size >= MAX_CHUNK_SIZE {
                let end = MAX_CHUNK_SIZE - self.output_size;
                for i in b[0..end].iter() {
                    self.output_buffer.push(*i);
                }
                self.output_size = MAX_CHUNK_SIZE;
                b = &b[end..size];
                try!(self.flush());
            } else {
                for i in b.iter() {
                    self.output_buffer.push(*i);
                    self.output_size = future_size;
                }
                break
            }
        }

        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        if self.output_buffer.len() > 0 {
            let mut buf: Cursor<Vec<u8>> = Cursor::new(Vec::new());
            try!(buf.write_u16::<BigEndian>(self.output_size as u16));
            try!(buf.write_all(self.output_buffer.as_ref()));

            try!(self.raw.write_all(buf.into_inner().as_ref()));
            try!(self.raw.flush());

            self.output_buffer.clear();
            self.output_size = 0;
        }

        Ok(())
    }
}
<commit_msg>change `v1::transport` to match python lib used as reference<commit_after>use std::io::prelude::*;
use std::io::{self, Cursor};
use std::net::TcpStream;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};

const MAX_CHUNK_SIZE: usize = 65535;

pub struct ChunkedStream {
    socket: TcpStream,
    raw: Cursor<Vec<u8>>,
    output_buffer: Vec<u8>,
    output_size: usize,
}

// based on https://github.com/neo4j/neo4j-python-driver/blob/1.0/neo4j/v1/connection.py
impl ChunkedStream {
    pub fn new(socket: TcpStream) -> Self {
        ChunkedStream {
            socket: socket,
            raw: Cursor::new(Vec::new()),
            output_buffer: Vec::new(),
            output_size: 0,
        }
    }

    pub fn write(&mut self, buf: &[u8]) -> io::Result<()> {
        let mut b = buf;

        loop {
            let size = b.len();
            let future_size = self.output_size + size;

            if future_size >= MAX_CHUNK_SIZE {
                let end = MAX_CHUNK_SIZE - self.output_size;
                for i in b[0..end].iter() {
                    self.output_buffer.push(*i);
                }
                self.output_size = MAX_CHUNK_SIZE;
                b = &b[end..size];
                try!(self.flush(false));
            } else {
                for i in b.iter() {
                    self.output_buffer.push(*i);
                    self.output_size = future_size;
                }
                break
            }
        }

        Ok(())
    }

    pub fn flush(&mut self, end_of_message: bool) -> io::Result<()> {
        let mut buf: Cursor<Vec<u8>> = Cursor::new(Vec::new());

        if self.output_buffer.len() > 0 {
            try!(buf.write_u16::<BigEndian>(self.output_size as u16));
            try!(buf.write_all(self.output_buffer.as_ref()));
        }

        if end_of_message {
            try!(buf.write(&[0x00, 0x00]));
        }

        if buf.get_ref().len() > 0 {
            try!(self.raw.write_all(buf.into_inner().as_ref()));
            try!(self.raw.flush());

            self.output_buffer.clear();
            self.output_size = 0;
        }

        Ok(())
    }

    pub fn send(&mut self) -> io::Result<()> {
        try!(self.socket.write_all(self.raw.get_ref()));

        debug!("C:{}", self.raw.get_ref().iter().fold(
            String::new(), |acc, i| format!("{} {}", acc, i)
        ));

        self.raw.get_mut().clear();
        self.raw.set_position(0);
        Ok(())
    }
}
<|endoftext|>


<commit_before>use llvm_sys::core::{LLVMTypeOf, LLVMGetTypeKind};
use llvm_sys::LLVMTypeKind;
use llvm_sys::prelude::LLVMValueRef;

use types::{AnyTypeEnum, BasicTypeEnum};
use values::traits::AsValueRef;
use values::{IntValue, FunctionValue, PointerValue, VectorValue, ArrayValue, StructValue, FloatValue, PhiValue, InstructionValue, MetadataValue};

macro_rules! enum_value_set {
    ($enum_name:ident: $($args:ident),*) => (
        #[derive(Debug, EnumAsGetters, EnumIntoGetters, EnumIsA, Clone, Copy)]
        pub enum $enum_name {
            $(
                $args($args),
            )*
        }

        impl AsValueRef for $enum_name {
            fn as_value_ref(&self) -> LLVMValueRef {
                match *self {
                    $(
                        $enum_name::$args(ref t) => t.as_value_ref(),
                    )*
                }
            }
        }

        $(
            impl From<$args> for $enum_name {
                fn from(value: $args) -> $enum_name {
                    $enum_name::$args(value)
                }
            }
        )*

        // REVIEW: Possible encompassing methods to implement:
        // as_instruction, is_sized, get/set metadata
    );
}

enum_value_set! {AggregateValueEnum: ArrayValue, StructValue}
enum_value_set! {AnyValueEnum: ArrayValue, IntValue, FloatValue, PhiValue, FunctionValue, PointerValue, StructValue, VectorValue}
enum_value_set! {BasicValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue}
enum_value_set! {BasicMetadataValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue, MetadataValue}

impl AnyValueEnum {
    pub(crate) fn new(value: LLVMValueRef) -> AnyValueEnum {
        let type_kind = unsafe {
            LLVMGetTypeKind(LLVMTypeOf(value))
        };

        match type_kind {
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => AnyValueEnum::FloatValue(FloatValue::new(value)),
            LLVMTypeKind::LLVMIntegerTypeKind => AnyValueEnum::IntValue(IntValue::new(value)),
            LLVMTypeKind::LLVMStructTypeKind => AnyValueEnum::StructValue(StructValue::new(value)),
            LLVMTypeKind::LLVMPointerTypeKind => AnyValueEnum::PointerValue(PointerValue::new(value)),
            LLVMTypeKind::LLVMArrayTypeKind => AnyValueEnum::ArrayValue(ArrayValue::new(value)),
            LLVMTypeKind::LLVMVectorTypeKind => AnyValueEnum::VectorValue(VectorValue::new(value)),
            LLVMTypeKind::LLVMFunctionTypeKind => AnyValueEnum::FunctionValue(FunctionValue::new(value).unwrap()),
            LLVMTypeKind::LLVMVoidTypeKind => panic!("Void values shouldn't exist."),
            LLVMTypeKind::LLVMMetadataTypeKind => panic!("Metadata values are not supported as AnyValue's."),
            _ => panic!("The given type is not supported.")
        }
    }

    pub fn get_type(&self) -> AnyTypeEnum {
        let type_ = unsafe {
            LLVMTypeOf(self.as_value_ref())
        };

        AnyTypeEnum::new(type_)
    }
}

impl BasicValueEnum {
    pub(crate) fn new(value: LLVMValueRef) -> BasicValueEnum {
        let type_kind = unsafe {
            LLVMGetTypeKind(LLVMTypeOf(value))
        };

        match type_kind {
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicValueEnum::FloatValue(FloatValue::new(value)),
            LLVMTypeKind::LLVMIntegerTypeKind => BasicValueEnum::IntValue(IntValue::new(value)),
            LLVMTypeKind::LLVMStructTypeKind => BasicValueEnum::StructValue(StructValue::new(value)),
            LLVMTypeKind::LLVMPointerTypeKind => BasicValueEnum::PointerValue(PointerValue::new(value)),
            LLVMTypeKind::LLVMArrayTypeKind => BasicValueEnum::ArrayValue(ArrayValue::new(value)),
            LLVMTypeKind::LLVMVectorTypeKind => BasicValueEnum::VectorValue(VectorValue::new(value)),
            _ => unreachable!("The given type is not a basic type."),
        }
    }

    pub fn get_type(&self) -> BasicTypeEnum {
        let type_ = unsafe {
            LLVMTypeOf(self.as_value_ref())
        };

        BasicTypeEnum::new(type_)
    }

    pub fn as_instruction(&self) -> Option<InstructionValue> {
        match *self {
            BasicValueEnum::ArrayValue(ref val) => val.as_instruction(),
            BasicValueEnum::IntValue(ref val) => val.as_instruction(),
            BasicValueEnum::FloatValue(ref val) => val.as_instruction(),
            BasicValueEnum::StructValue(ref val) => val.as_instruction(),
            BasicValueEnum::PointerValue(ref val) => val.as_instruction(),
            BasicValueEnum::VectorValue(ref val) => val.as_instruction(),
        }
    }
}

impl AggregateValueEnum {
    pub(crate) fn new(value: LLVMValueRef) -> AggregateValueEnum {
        let type_kind = unsafe {
            LLVMGetTypeKind(LLVMTypeOf(value))
        };

        match type_kind {
            LLVMTypeKind::LLVMArrayTypeKind => AggregateValueEnum::ArrayValue(ArrayValue::new(value)),
            LLVMTypeKind::LLVMStructTypeKind => AggregateValueEnum::StructValue(StructValue::new(value)),
            _ => unreachable!("The given type is not an aggregate type."),
        }
    }
}

impl BasicMetadataValueEnum {
    pub(crate) fn new(value: LLVMValueRef) -> BasicMetadataValueEnum {
        let type_kind = unsafe {
            LLVMGetTypeKind(LLVMTypeOf(value))
        };

        match type_kind {
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicMetadataValueEnum::FloatValue(FloatValue::new(value)),
            LLVMTypeKind::LLVMIntegerTypeKind => BasicMetadataValueEnum::IntValue(IntValue::new(value)),
            LLVMTypeKind::LLVMStructTypeKind => BasicMetadataValueEnum::StructValue(StructValue::new(value)),
            LLVMTypeKind::LLVMPointerTypeKind => BasicMetadataValueEnum::PointerValue(PointerValue::new(value)),
            LLVMTypeKind::LLVMArrayTypeKind => BasicMetadataValueEnum::ArrayValue(ArrayValue::new(value)),
            LLVMTypeKind::LLVMVectorTypeKind => BasicMetadataValueEnum::VectorValue(VectorValue::new(value)),
            LLVMTypeKind::LLVMMetadataTypeKind => BasicMetadataValueEnum::MetadataValue(MetadataValue::new(value)),
            _ => unreachable!("Unsupported type"),
        }
    }
}
<commit_msg>Added some conversion impls<commit_after>use llvm_sys::core::{LLVMTypeOf, LLVMGetTypeKind};
use llvm_sys::LLVMTypeKind;
use llvm_sys::prelude::LLVMValueRef;

use types::{AnyTypeEnum, BasicTypeEnum};
use values::traits::AsValueRef;
use values::{IntValue, FunctionValue, PointerValue, VectorValue, ArrayValue, StructValue, FloatValue, PhiValue, InstructionValue, MetadataValue};

macro_rules! enum_value_set {
    ($enum_name:ident: $($args:ident),*) => (
        #[derive(Debug, EnumAsGetters, EnumIntoGetters, EnumIsA, Clone, Copy)]
        pub enum $enum_name {
            $(
                $args($args),
            )*
        }

        impl AsValueRef for $enum_name {
            fn as_value_ref(&self) -> LLVMValueRef {
                match *self {
                    $(
                        $enum_name::$args(ref t) => t.as_value_ref(),
                    )*
                }
            }
        }

        $(
            impl From<$args> for $enum_name {
                fn from(value: $args) -> $enum_name {
                    $enum_name::$args(value)
                }
            }
        )*

        // REVIEW: Possible encompassing methods to implement:
        // as_instruction, is_sized, get/set metadata
    );
}

enum_value_set! {AggregateValueEnum: ArrayValue, StructValue}
enum_value_set! {AnyValueEnum: ArrayValue, IntValue, FloatValue, PhiValue, FunctionValue, PointerValue, StructValue, VectorValue, InstructionValue}
enum_value_set! {BasicValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue}
enum_value_set! {BasicMetadataValueEnum: ArrayValue, IntValue, FloatValue, PointerValue, StructValue, VectorValue, MetadataValue}

impl AnyValueEnum {
    pub(crate) fn new(value: LLVMValueRef) -> AnyValueEnum {
        let type_kind = unsafe {
            LLVMGetTypeKind(LLVMTypeOf(value))
        };

        match type_kind {
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => AnyValueEnum::FloatValue(FloatValue::new(value)),
            LLVMTypeKind::LLVMIntegerTypeKind => AnyValueEnum::IntValue(IntValue::new(value)),
            LLVMTypeKind::LLVMStructTypeKind => AnyValueEnum::StructValue(StructValue::new(value)),
            LLVMTypeKind::LLVMPointerTypeKind => AnyValueEnum::PointerValue(PointerValue::new(value)),
            LLVMTypeKind::LLVMArrayTypeKind => AnyValueEnum::ArrayValue(ArrayValue::new(value)),
            LLVMTypeKind::LLVMVectorTypeKind => AnyValueEnum::VectorValue(VectorValue::new(value)),
            LLVMTypeKind::LLVMFunctionTypeKind => AnyValueEnum::FunctionValue(FunctionValue::new(value).unwrap()),
            LLVMTypeKind::LLVMVoidTypeKind => panic!("Void values shouldn't exist."),
            LLVMTypeKind::LLVMMetadataTypeKind => panic!("Metadata values are not supported as AnyValue's."),
            _ => panic!("The given type is not supported.")
        }
    }

    pub fn get_type(&self) -> AnyTypeEnum {
        let type_ = unsafe {
            LLVMTypeOf(self.as_value_ref())
        };

        AnyTypeEnum::new(type_)
    }
}

impl BasicValueEnum {
    pub(crate) fn new(value: LLVMValueRef) -> BasicValueEnum {
        let type_kind = unsafe {
            LLVMGetTypeKind(LLVMTypeOf(value))
        };

        match type_kind {
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicValueEnum::FloatValue(FloatValue::new(value)),
            LLVMTypeKind::LLVMIntegerTypeKind => BasicValueEnum::IntValue(IntValue::new(value)),
            LLVMTypeKind::LLVMStructTypeKind => BasicValueEnum::StructValue(StructValue::new(value)),
            LLVMTypeKind::LLVMPointerTypeKind => BasicValueEnum::PointerValue(PointerValue::new(value)),
            LLVMTypeKind::LLVMArrayTypeKind => BasicValueEnum::ArrayValue(ArrayValue::new(value)),
            LLVMTypeKind::LLVMVectorTypeKind => BasicValueEnum::VectorValue(VectorValue::new(value)),
            _ => unreachable!("The given type is not a basic type."),
        }
    }

    pub fn get_type(&self) -> BasicTypeEnum {
        let type_ = unsafe {
            LLVMTypeOf(self.as_value_ref())
        };

        BasicTypeEnum::new(type_)
    }

    pub fn as_instruction(&self) -> Option<InstructionValue> {
        match *self {
            BasicValueEnum::ArrayValue(ref val) => val.as_instruction(),
            BasicValueEnum::IntValue(ref val) => val.as_instruction(),
            BasicValueEnum::FloatValue(ref val) => val.as_instruction(),
            BasicValueEnum::StructValue(ref val) => val.as_instruction(),
            BasicValueEnum::PointerValue(ref val) => val.as_instruction(),
            BasicValueEnum::VectorValue(ref val) => val.as_instruction(),
        }
    }
}

impl AggregateValueEnum {
    pub(crate) fn new(value: LLVMValueRef) -> AggregateValueEnum {
        let type_kind = unsafe {
            LLVMGetTypeKind(LLVMTypeOf(value))
        };

        match type_kind {
            LLVMTypeKind::LLVMArrayTypeKind => AggregateValueEnum::ArrayValue(ArrayValue::new(value)),
            LLVMTypeKind::LLVMStructTypeKind => AggregateValueEnum::StructValue(StructValue::new(value)),
            _ => unreachable!("The given type is not an aggregate type."),
        }
    }
}

impl BasicMetadataValueEnum {
    pub(crate) fn new(value: LLVMValueRef) -> BasicMetadataValueEnum {
        let type_kind = unsafe {
            LLVMGetTypeKind(LLVMTypeOf(value))
        };

        match type_kind {
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicMetadataValueEnum::FloatValue(FloatValue::new(value)),
            LLVMTypeKind::LLVMIntegerTypeKind => BasicMetadataValueEnum::IntValue(IntValue::new(value)),
            LLVMTypeKind::LLVMStructTypeKind => BasicMetadataValueEnum::StructValue(StructValue::new(value)),
            LLVMTypeKind::LLVMPointerTypeKind => BasicMetadataValueEnum::PointerValue(PointerValue::new(value)),
            LLVMTypeKind::LLVMArrayTypeKind => BasicMetadataValueEnum::ArrayValue(ArrayValue::new(value)),
            LLVMTypeKind::LLVMVectorTypeKind => BasicMetadataValueEnum::VectorValue(VectorValue::new(value)),
            LLVMTypeKind::LLVMMetadataTypeKind => BasicMetadataValueEnum::MetadataValue(MetadataValue::new(value)),
            _ => unreachable!("Unsupported type"),
        }
    }
}

impl From<BasicValueEnum> for AnyValueEnum {
    fn from(value: BasicValueEnum) -> AnyValueEnum {
        AnyValueEnum::new(value.as_value_ref())
    }
}
<|endoftext|>


<commit_before>// void_pointer.rs
// Aldaron's Memory Interface ( ami )
// Copyright 2017 (c) Aldaron's Tech
// Copyright 2017 (c) Jeron Lau
// Licensed under the MIT LICENSE

//! This module is for repurposing memory returned from or sent to FFI.

/// A type that represents a void* in C.
#[repr(C)]
#[derive(Copy, Clone, PartialEq)]
pub struct VoidPointer {
	#[cfg(target_pointer_width = "32")]
	native: u32,
	#[cfg(target_pointer_width = "64")]
	native: u64,
}

/// Equivalent of NULL in C.
pub const NULL : VoidPointer = VoidPointer { native: 0 };

/// A trait used for casting the void pointer to other pointer types.
pub trait VoidPointerCast<T> {
	/// Cast a VoidPointer to a native pointer of any type.
	#[inline(always)]
	fn cast(&self) -> *mut T;
	/// Cast a native pointer of any type to a VoidPointer.
	#[inline(always)]
	fn from(pointer: *mut T) -> VoidPointer;
}

impl<T> VoidPointerCast<T> for VoidPointer {
	#[inline(always)]
	fn from(pointer: *mut T) -> VoidPointer {
		unsafe {
			*(&pointer as *const *mut _ as *const _)
		}
	}

	#[inline(always)]
	fn cast(&self) -> *mut T {
		unsafe {
			*(&self as *const _ as *const *mut _)
		}
	}
}
<commit_msg>Implemented ops for pointer math on VoidPointer.<commit_after>// void_pointer.rs
// Aldaron's Memory Interface ( ami )
// Copyright 2017 (c) Aldaron's Tech
// Copyright 2017 (c) Jeron Lau
// Licensed under the MIT LICENSE

//! This module is for repurposing memory returned from or sent to FFI.

use core::ops::{Add, Sub, Not, BitAnd, BitOr, BitXor, Shr, Shl};

#[cfg(target_pointer_width = "32")]
type NativePtr = u32;

#[cfg(target_pointer_width = "64")]
type NativePtr = u64;

/// A type that represents a void* in C.
#[repr(C)]
#[derive(Copy, Clone, PartialEq)]
pub struct VoidPointer {
	native: NativePtr,
}

/// Equivalent of NULL in C.
pub const NULL : VoidPointer = VoidPointer { native: 0 };

impl VoidPointer {
	/// Return the pointer as an integer.
	#[inline(always)]
	pub fn as_int(&self) -> NativePtr {
		self.native
	}
}
/*
/// A trait used for casting the void pointer to other pointer types.
pub trait VoidPointerCast<T> {
	/// Cast a VoidPointer to a native pointer of any type.
	#[inline(always)]
	fn cast(&self) -> *mut T;
	/// Cast a native pointer of any type to a VoidPointer.
	#[inline(always)]
	fn from(pointer: *mut T) -> VoidPointer;
}

impl<T> VoidPointerCast<T> for VoidPointer {
	#[inline(always)]
	fn from(pointer: *mut T) -> VoidPointer {
		unsafe {
			*(&pointer as *const *mut _ as *const _)
		}
	}

	#[inline(always)]
	fn cast(&self) -> *mut T {
		unsafe {
			*(&self as *const _ as *const *mut _)
		}
	}
}*/

impl Add<u32> for VoidPointer {
	type Output = VoidPointer;

	fn add(self, other: u32) -> VoidPointer {
		VoidPointer {
			native: self.native + (other as NativePtr)
		}
	}
}

impl Sub<u32> for VoidPointer {
	type Output = VoidPointer;

	fn sub(self, other: u32) -> VoidPointer {
		VoidPointer {
			native: self.native - (other as NativePtr)
		}
	}
}

impl BitAnd<u32> for VoidPointer {
	type Output = VoidPointer;

	fn bitand(self, other: u32) -> VoidPointer {
		VoidPointer {
			native: (self.native as u32 & other) as NativePtr
		}
	}
}

impl BitOr<u32> for VoidPointer {
	type Output = VoidPointer;

	fn bitor(self, other: u32) -> VoidPointer {
		VoidPointer {
			native: (self.native as u32 | other) as NativePtr
		}
	}
}

impl BitXor<u32> for VoidPointer {
	type Output = VoidPointer;

	fn bitxor(self, other: u32) -> VoidPointer {
		VoidPointer {
			native: (self.native as u32 ^ other) as NativePtr
		}
	}
}

impl Shr<usize> for VoidPointer {
	type Output = VoidPointer;

	fn shr(self, rhs: usize) -> VoidPointer {
		VoidPointer {
			native: self.native >> rhs
		}
	}
}

impl Shl<usize> for VoidPointer {
	type Output = VoidPointer;

	fn shl(self, rhs: usize) -> VoidPointer {
		VoidPointer {
			native: self.native << rhs
		}
	}
}

impl Not for VoidPointer {
	type Output = VoidPointer;

	fn not(self) -> VoidPointer {
		VoidPointer {
			native: !self.native
		}
	}
}<|endoftext|>


<commit_before>//! Contains result and error type for FBX reader.

extern crate byteorder;

use std::io;

/// A specialized `std::result::Result` type for FBX exporting.
pub type Result<T> = ::std::result::Result<T, Error>;

/// An FBX parsing error.
#[derive(Debug)]
pub enum Error {
    /// I/O error.
    Io(io::Error),
    /// `EndNode` event is given but there's no node to close.
    ExtraEndNode,
    /// FBX not started but an event other than `StartFbx` is given.
    FbxNotStarted,
    /// FBX is already started but `StartFbx` is given.
    FbxAlreadyStarted,
    /// Unsupported FBX version.
    UnsupportedFbxVersion,
    /// Given event is not writable in current format.
    UnwritableEvent,
    /// Unimplemented feature.
    Unimplemented(String),
}

impl Clone for Error {
    fn clone(&self) -> Self {
        use self::Error::*;
        use std::error::Error;
        match *self {
            Io(ref e) => Io(io::Error::new(e.kind(), e.description())),
            Unimplemented(ref e) => Unimplemented(e.clone()),
            ref e => e.clone(),
        }
    }
}

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

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        match err {
            byteorder::Error::UnexpectedEOF => panic!("byteorder::Error::UnexpectedEOF shouldn't happen on write"),
            byteorder::Error::Io(err) => Error::Io(err),
        }
    }
}
<commit_msg>Implement `Error` and `Display` trait for `writer::error::Error`<commit_after>//! Contains result and error type for FBX reader.

extern crate byteorder;

use std::io;
use std::fmt;
use std::error;

/// A specialized `std::result::Result` type for FBX exporting.
pub type Result<T> = ::std::result::Result<T, Error>;

/// An FBX parsing error.
#[derive(Debug)]
pub enum Error {
    /// I/O error.
    Io(io::Error),
    /// `EndNode` event is given but there's no node to close.
    ExtraEndNode,
    /// FBX not started but an event other than `StartFbx` is given.
    FbxNotStarted,
    /// FBX is already started but `StartFbx` is given.
    FbxAlreadyStarted,
    /// Unsupported FBX version.
    UnsupportedFbxVersion,
    /// Given event is not writable in current format.
    UnwritableEvent,
    /// Unimplemented feature.
    Unimplemented(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref err) => write!(f, "I/O error: {}", err),
            Error::ExtraEndNode => write!(f, "Extra end-of-node marker detected"),
            Error::FbxNotStarted => write!(f, "An writer event is given, but FBX data is not started yet"),
            Error::FbxAlreadyStarted => write!(f, "Got a writer event to start FBX, but FBX data is already started"),
            Error::UnsupportedFbxVersion => write!(f, "Unsupported FBX version"),
            Error::UnwritableEvent => write!(f, "A given event is not writable in current format"),
            Error::Unimplemented(ref err) => write!(f, "Unimplemented feature: {}", err),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::ExtraEndNode => "Extra end-of-node marker detected",
            Error::FbxNotStarted => "An writer event is given, but FBX data is not started yet",
            Error::FbxAlreadyStarted => "Got a writer event to start FBX, but FBX data is already started",
            Error::UnsupportedFbxVersion => "Unsupported FBX version",
            Error::UnwritableEvent => "A given event is not writable in current format",
            Error::Unimplemented(_) => "Attempt to use unimplemented feature",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref err) => Some(err as &error::Error),
            _ => None,
        }
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        use self::Error::*;
        use std::error::Error;
        match *self {
            Io(ref e) => Io(io::Error::new(e.kind(), e.description())),
            Unimplemented(ref e) => Unimplemented(e.clone()),
            ref e => e.clone(),
        }
    }
}

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

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        match err {
            byteorder::Error::UnexpectedEOF => panic!("byteorder::Error::UnexpectedEOF shouldn't happen on write"),
            byteorder::Error::Io(err) => Error::Io(err),
        }
    }
}
<|endoftext|>


<commit_before>extern crate rosc;<commit_msg>Remove old and unused test<commit_after><|endoftext|>


<commit_before><commit_msg>Change 'and with' -> 'with' in some docs<commit_after><|endoftext|>


<commit_before>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! YAML Serialization
//!
//! This module provides YAML serialization with the type `Serializer`.

use std::fmt;
use std::io;

use yaml_rust::{Yaml, YamlEmitter};
use yaml_rust::yaml;

use serde::ser;

use super::error::{Error, Result};

/// A structure for serializing a Rust value into a YAML value.
pub struct Serializer<'a> {
    /// The YAML value to hold the result.
    doc: &'a mut Yaml,
}

impl<'a> Serializer<'a> {
    pub fn new(doc: &'a mut Yaml) -> Self {
        Serializer {
            doc: doc,
        }
    }
}

impl<'a> ser::Serializer for Serializer<'a> {
    type Error = Error;

    fn serialize_bool(&mut self, v: bool) -> Result<()> {
        *self.doc = Yaml::Boolean(v);
        Ok(())
    }

    fn serialize_i64(&mut self, v: i64) -> Result<()> {
        *self.doc = Yaml::Integer(v);
        Ok(())
    }

    fn serialize_u64(&mut self, v: u64) -> Result<()> {
        self.serialize_i64(v as i64)
    }

    fn serialize_f64(&mut self, v: f64) -> Result<()> {
        *self.doc = Yaml::Real(v.to_string());
        Ok(())
    }

    fn serialize_str(&mut self, value: &str) -> Result<()> {
        *self.doc = Yaml::String(String::from(value));
        Ok(())
    }

    fn serialize_unit(&mut self) -> Result<()> {
        *self.doc = Yaml::Null;
        Ok(())
    }

    fn serialize_none(&mut self) -> Result<()> {
        self.serialize_unit()
    }

    fn serialize_some<V>(&mut self, value: V) -> Result<()>
        where V: ser::Serialize,
    {
        value.serialize(self)
    }

    fn serialize_seq<V>(&mut self, mut visitor: V) -> Result<()>
        where V: ser::SeqVisitor,
    {
        let vec = match visitor.len() {
            None => yaml::Array::new(),
            Some(len) => yaml::Array::with_capacity(len),
        };
        *self.doc = Yaml::Array(vec);
        while try!(visitor.visit(self)).is_some() {
        }
        Ok(())
    }

    fn serialize_seq_elt<T>(&mut self, elem: T) -> Result<()>
        where T: ser::Serialize,
    {
        if let Yaml::Array(ref mut vec) = *self.doc {
            vec.push(try!(to_yaml(elem)));
        } else {
            panic!("bad call to serialize_seq_elt");
        }
        Ok(())
    }

    fn serialize_map<V>(&mut self, mut visitor: V) -> Result<()>
        where V: ser::MapVisitor,
    {
        *self.doc = Yaml::Hash(yaml::Hash::new());
        while try!(visitor.visit(self)).is_some() {
        }
        Ok(())
    }

    fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<()>
        where K: ser::Serialize,
              V: ser::Serialize,
    {
        if let Yaml::Hash(ref mut map) = *self.doc {
            map.insert(try!(to_yaml(key)), try!(to_yaml(value)));
        } else {
            panic!("bad call to serialize_map_elt");
        }
        Ok(())
    }

    fn serialize_unit_variant(
        &mut self,
        _name: &str,
        _variant_index: usize,
        variant: &str
    ) -> Result<()> {
        *self.doc = Yaml::String(String::from(variant));
        Ok(())
    }

    /// Override `serialize_newtype_struct` to serialize newtypes without an object wrapper.
    fn serialize_newtype_struct<T>(
        &mut self,
        _name: &'static str,
        value: T
    ) -> Result<()>
        where T: ser::Serialize,
    {
        value.serialize(self)
    }

    fn serialize_newtype_variant<T>(
        &mut self,
        _name: &str,
        _variant_index: usize,
        variant: &str,
        value: T
    ) -> Result<()>
        where T: ser::Serialize,
    {
        *self.doc = singleton_hash(try!(to_yaml(variant)),
                                   try!(to_yaml(value)));
        Ok(())
    }

    fn serialize_tuple_variant<V>(
        &mut self,
        _name: &str,
        _variant_index: usize,
        variant: &str,
        visitor: V
    ) -> Result<()>
        where V: ser::SeqVisitor,
    {
        let mut values = Yaml::Null;
        try!(Serializer::new(&mut values).serialize_seq(visitor));
        *self.doc = singleton_hash(try!(to_yaml(variant)), values);
        Ok(())
    }

    fn serialize_struct_variant<V>(
        &mut self,
        _name: &str,
        _variant_index: usize,
        variant: &str,
        visitor: V
    ) -> Result<()>
        where V: ser::MapVisitor,
    {
        let mut values = Yaml::Null;
        try!(Serializer::new(&mut values).serialize_map(visitor));
        *self.doc = singleton_hash(try!(to_yaml(variant)), values);
        Ok(())
    }
}

pub fn to_writer<W, T>(writer: &mut W, value: &T) -> Result<()>
    where W: io::Write,
          T: ser::Serialize,
{
    let doc = try!(to_yaml(value));
    let mut writer_adapter = FmtToIoWriter {
        writer: writer,
    };
    try!(YamlEmitter::new(&mut writer_adapter).dump(&doc));
    Ok(())
}

pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
    where T: ser::Serialize,
{
    let mut vec = Vec::with_capacity(128);
    try!(to_writer(&mut vec, value));
    Ok(vec)
}

pub fn to_string<T>(value: &T) -> Result<String>
    where T: ser::Serialize,
{
    Ok(try!(String::from_utf8(try!(to_vec(value)))))
}

/// The yaml-rust library uses `fmt.Write` intead of `io.Write` so this is a
/// simple adapter.
struct FmtToIoWriter<'a, W>
    where W: io::Write + 'a,
{
    writer: &'a mut W,
}

impl<'a, W> fmt::Write for FmtToIoWriter<'a, W>
    where W: io::Write + 'a,
{
    fn write_str(&mut self, s: &str) -> fmt::Result {
        if self.writer.write(s.as_bytes()).is_err() {
            return Err(fmt::Error);
        }
        if self.writer.flush().is_err() {
            return Err(fmt::Error);
        }
        Ok(())
    }
}

fn to_yaml<T>(elem: T) -> Result<Yaml>
    where T: ser::Serialize,
{
    let mut result = Yaml::Null;
    try!(elem.serialize(&mut Serializer::new(&mut result)));
    Ok(result)
}

fn singleton_hash(k: Yaml, v: Yaml) -> Yaml {
    let mut hash = yaml::Hash::new();
    hash.insert(k, v);
    Yaml::Hash(hash)
}
<commit_msg>serde push-serialization <commit_after>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! YAML Serialization
//!
//! This module provides YAML serialization with the type `Serializer`.

use std::fmt;
use std::io;

use yaml_rust::{Yaml, YamlEmitter};
use yaml_rust::yaml;

use serde::ser;

use super::error::{Error, Result};

/// A structure for serializing a Rust value into a YAML value.
pub struct Serializer<'a> {
    /// The YAML value to hold the result.
    doc: &'a mut Yaml,
}

impl<'a> Serializer<'a> {
    pub fn new(doc: &'a mut Yaml) -> Self {
        Serializer {
            doc: doc,
        }
    }
}

impl<'a> ser::Serializer for Serializer<'a> {
    type Error = Error;

    fn serialize_bool(&mut self, v: bool) -> Result<()> {
        *self.doc = Yaml::Boolean(v);
        Ok(())
    }

    fn serialize_i64(&mut self, v: i64) -> Result<()> {
        *self.doc = Yaml::Integer(v);
        Ok(())
    }

    fn serialize_u64(&mut self, v: u64) -> Result<()> {
        self.serialize_i64(v as i64)
    }

    fn serialize_f64(&mut self, v: f64) -> Result<()> {
        *self.doc = Yaml::Real(v.to_string());
        Ok(())
    }

    fn serialize_str(&mut self, value: &str) -> Result<()> {
        *self.doc = Yaml::String(String::from(value));
        Ok(())
    }

    fn serialize_unit(&mut self) -> Result<()> {
        *self.doc = Yaml::Null;
        Ok(())
    }

    fn serialize_none(&mut self) -> Result<()> {
        self.serialize_unit()
    }

    fn serialize_some<V>(&mut self, value: V) -> Result<()>
        where V: ser::Serialize,
    {
        value.serialize(self)
    }

    fn serialize_seq(&mut self, len: Option<usize>) -> Result<()> {
        let vec = match len {
            None => yaml::Array::new(),
            Some(len) => yaml::Array::with_capacity(len),
        };
        *self.doc = Yaml::Array(vec);
        Ok(())
    }

    fn serialize_seq_end(&mut self, _len: Option<usize>) -> Result<()> {
        Ok(())
    }

    fn serialize_seq_elt<T>(&mut self, elem: T) -> Result<()>
        where T: ser::Serialize,
    {
        if let Yaml::Array(ref mut vec) = *self.doc {
            vec.push(try!(to_yaml(elem)));
        } else {
            panic!("bad call to serialize_seq_elt");
        }
        Ok(())
    }

    fn serialize_map(&mut self, _len: Option<usize>) -> Result<()>
    {
        *self.doc = Yaml::Hash(yaml::Hash::new());
        Ok(())
    }

    fn serialize_map_end(&mut self, _len: Option<usize>) -> Result<()> {
        Ok(())
    }

    fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<()>
        where K: ser::Serialize,
              V: ser::Serialize,
    {
        if let Yaml::Hash(ref mut map) = *self.doc {
            map.insert(try!(to_yaml(key)), try!(to_yaml(value)));
        } else {
            panic!("bad call to serialize_map_elt");
        }
        Ok(())
    }

    fn serialize_unit_variant(
        &mut self,
        _name: &str,
        _variant_index: usize,
        variant: &str
    ) -> Result<()> {
        *self.doc = Yaml::String(String::from(variant));
        Ok(())
    }

    /// Override `serialize_newtype_struct` to serialize newtypes without an object wrapper.
    fn serialize_newtype_struct<T>(
        &mut self,
        _name: &'static str,
        value: T
    ) -> Result<()>
        where T: ser::Serialize,
    {
        value.serialize(self)
    }

    fn serialize_newtype_variant<T>(
        &mut self,
        _name: &str,
        _variant_index: usize,
        variant: &str,
        value: T
    ) -> Result<()>
        where T: ser::Serialize,
    {
        *self.doc = singleton_hash(try!(to_yaml(variant)),
                                   try!(to_yaml(value)));
        Ok(())
    }

    fn serialize_tuple_variant_end(
        &mut self,
        _name: &str,
        _variant_index: usize,
        variant: &str,
        _len: usize,
    ) -> Result<()> {
        *self.doc = singleton_hash(try!(to_yaml(variant)), ::std::mem::replace(&mut self.doc, Yaml::Null));
        Ok(())
    }

    fn serialize_struct_variant_end(
        &mut self,
        _name: &str,
        _variant_index: usize,
        variant: &str,
        _len: usize,
    ) -> Result<()> {
        *self.doc = singleton_hash(try!(to_yaml(variant)), ::std::mem::replace(&mut self.doc, Yaml::Null));
        Ok(())
    }
}

pub fn to_writer<W, T>(writer: &mut W, value: &T) -> Result<()>
    where W: io::Write,
          T: ser::Serialize,
{
    let doc = try!(to_yaml(value));
    let mut writer_adapter = FmtToIoWriter {
        writer: writer,
    };
    try!(YamlEmitter::new(&mut writer_adapter).dump(&doc));
    Ok(())
}

pub fn to_vec<T>(value: &T) -> Result<Vec<u8>>
    where T: ser::Serialize,
{
    let mut vec = Vec::with_capacity(128);
    try!(to_writer(&mut vec, value));
    Ok(vec)
}

pub fn to_string<T>(value: &T) -> Result<String>
    where T: ser::Serialize,
{
    Ok(try!(String::from_utf8(try!(to_vec(value)))))
}

/// The yaml-rust library uses `fmt.Write` intead of `io.Write` so this is a
/// simple adapter.
struct FmtToIoWriter<'a, W>
    where W: io::Write + 'a,
{
    writer: &'a mut W,
}

impl<'a, W> fmt::Write for FmtToIoWriter<'a, W>
    where W: io::Write + 'a,
{
    fn write_str(&mut self, s: &str) -> fmt::Result {
        if self.writer.write(s.as_bytes()).is_err() {
            return Err(fmt::Error);
        }
        if self.writer.flush().is_err() {
            return Err(fmt::Error);
        }
        Ok(())
    }
}

fn to_yaml<T>(elem: T) -> Result<Yaml>
    where T: ser::Serialize,
{
    let mut result = Yaml::Null;
    try!(elem.serialize(&mut Serializer::new(&mut result)));
    Ok(result)
}

fn singleton_hash(k: Yaml, v: Yaml) -> Yaml {
    let mut hash = yaml::Hash::new();
    hash.insert(k, v);
    Yaml::Hash(hash)
}
<|endoftext|>