<commit_before>use std::mem;

// FIXME: Come up with good names and finalize them.

#[repr(u8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum HandleType {
	Undefined     = 0,
	DIO           = 1,  // 1 bit
	Port          = 2,  // 2 bits
	Notifier      = 3,
	Interrupt     = 4,  // 3 bits
	AnalogOutput  = 5,
	AnalogInput   = 6,
	AnalogTrigger = 7,
	Relay         = 8,  // 4 bits
	PWM           = 9,
	DigitalPWM    = 10,
	Counter       = 11,
	FPGAEncoder   = 12,
	Encoder       = 13,
	Compressor    = 14,
	Solenoid      = 15,
	AnalogGyro    = 16, // 5 bits
	Vendor        = 17
}

impl HandleType {
    /// Converts a `u8` to a `HandleType`. This produces Undefined Behavior when `num > 17`.
    pub unsafe fn from_u8_unchecked(num: u8) -> HandleType {
        mem::transmute(num)
    }

    /// Converts a `u8` to a `HandleType`, returning `None` if none of the variants were matched.
    pub fn from_u8(num: u8) -> Option<HandleType> {
        if num <= 17 {
            Some(unsafe { mem::transmute(num) })
        } else {
            None
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct TypeByte(u8);

impl TypeByte {
    pub fn new(byte: u8) -> Option<TypeByte> {
        if byte & !(1 << 7) <= 17 {
            unsafe { Some(mem::transmute(byte)) }
        } else {
            None
        }
    }

    /// Set the error bit
    #[inline]
    pub fn set_error_bit(&mut self, error: bool) {
        self.0 = (self.0 & !(1 << 7)) | ((error as u8) << 7)
    }

    /// Get the error bit
    #[inline]
    pub fn error_bit(&self) -> bool {
        (self.0 >> 7) & 1 != 0
    }

    pub fn get_type(&self) -> HandleType {
        unsafe { mem::transmute(self.0 & !(1 << 7)) }
    }
}

impl From<HandleType> for TypeByte {
	// Handle type never has the error bit set by itself
	fn from(handle_type: HandleType) -> TypeByte {
		unsafe { mem::transmute(handle_type) }
	}
}

// TODO: Is there a better way to structure this?
/// A sort of "protocol" for handles.
///
/// | Bits  | Meaning     | Type |
/// |-------|-------------|:----:|
/// | 31    | Error       | bool |
/// | 24-30 | Handle Type |  u8  |
/// | 16-23 | Unused      |  u8  |
/// | 0-15  | Payload     |  u16 |
///
/// ### Payload
/// The `Data` type is what type the payload should be converted into.
/// For normal handles, this is just a `u16` representing the index.
/// For port handles, this is two `u8`s, representing the module and the channel, respectively.
pub trait HandleProtocol: Sized {
    /// The data derived from the last 16 bits of the struct
    type Data;

    /// Transform the last 16 bits into whatever data type was defined
    fn to_data(&self) -> Self::Data;
}

/// Struct representing some sort of indexed data.
///
/// General Handle Data Layout
///
/// * Bits 0-15:  Handle Index
/// * Bits 16-23: Unused
/// * Bits 24-30: Handle Type
/// * Bit  31:    1 if handle error, 0 if no error
///
/// Other specialized handles will use different formats, however Bits 24-31 are
/// always reserved for type and error handling.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct Handle {
    /// The type of the handle. This is the `HandleType` enum, only the top
    /// bit denotes an error status
    pub type_byte: TypeByte,
    /// 8 unused bits
    _padding: u8,
    /// TODO
    pub index: u16
}

impl Handle {
	/// Creates a new handle from its parts
	pub fn new(type_byte: HandleType, index: u16) -> Handle {
		Handle { type_byte: type_byte.into(), _padding: 0, index }
	}

	/// Convert an i32 to a Handle. Unsafe, as there is no associated variant of `HandleType` for `num > 17`
	pub unsafe fn from_i32_unchecked(num: i32) -> Handle {
		mem::transmute(num)
	}

    /// Convert an i32 to a Handle. Returns `None` if the type byte of `num` is out of bounds
    pub fn from_i32(num: i32) -> Option<Handle> {
        if (num >> 24) & !(1 << 7) <= 17 {
            Some(unsafe { mem::transmute(num) })
        } else {
            None
        }
    }
}

impl HandleProtocol for Handle {
    type Data = u16;

    fn to_data(&self) -> u16 {
        self.index
    }
}

impl From<Handle> for i32 {
	fn from(handle: Handle) -> i32 {
		// Our struct has the same memory layout as the i32 representation
		unsafe { mem::transmute(handle) }
	}
}

/// Struct representing some port/module on the robot
///
/// Port Handle Data Layout
///
/// * Bits 0-7:   Channel Number
/// * Bits 8-15:  Module Number
/// * Bits 16-23: Unused
/// * Bits 24-30: Handle Type
/// * Bit  31:    1 if handle error, 0 if no error
///
/// This struct is 32 bits wide.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct PortHandle {
	/// The type of the handle. This is the `HandleType` enum, only the top
	/// bit denotes an error status
	pub type_byte: TypeByte,
	/// 8 unused bits
	_padding: u8,
	/// The module ID (TODO: possibly from the cRIO days?)
	pub module: u8,
	/// The channel ID
	pub channel: u8
}

impl PortHandle {
	/// Creates a new handle from its parts
	pub fn new(module: u8, channel: u8) -> PortHandle {
        // A `PortHandle` always has a handle type of `Port`
		PortHandle { type_byte: HandleType::Port.into(), _padding: 0, module, channel }
	}

	/// Convert an i32 to a Handle. Unsafe, as there is no associated variant for `num > 17`
	pub unsafe fn from_i32_unchecked(num: i32) -> PortHandle {
		mem::transmute(num)
	}

    /// Convert an `i32` to a `PortHandle`
    pub fn from_i32(num: i32) -> Option<PortHandle> {
        if (num >> 24) & !(1 << 7) <= 17 {
            Some(unsafe { mem::transmute(num) })
        } else {
            None
        }
    }
}

impl HandleProtocol for PortHandle {
    type Data = (u8, u8);

    fn to_data(&self) -> (u8, u8) {
        (self.module, self.channel)
    }
}

impl From<PortHandle> for i32 {
	fn from(handle: PortHandle) -> i32 {
		// Our struct has the same memory layout as the i32 representation
		unsafe { mem::transmute(handle) }
	}
}

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

    const HANDLE_TYPES: [HandleType; 18] = [
        HandleType::Undefined,
        HandleType::DIO,
        HandleType::Port,
        HandleType::Notifier,
        HandleType::Interrupt,
        HandleType::AnalogOutput,
        HandleType::AnalogInput,
        HandleType::AnalogTrigger,
        HandleType::Relay,
        HandleType::PWM,
        HandleType::DigitalPWM,
        HandleType::Counter,
        HandleType::FPGAEncoder,
        HandleType::Encoder,
        HandleType::Compressor,
        HandleType::Solenoid,
        HandleType::AnalogGyro,
        HandleType::Vendor
    ];

    #[test]
    fn check_handle_type() {
        for (i, t) in HANDLE_TYPES.iter().enumerate() {
            assert_eq!(HandleType::from_u8(i as u8).unwrap(), *t);
        }
    }

    mod type_byte {
        use super::*;

        #[test]
        fn check_constructor_error() {
            let err = TypeByte::new(0b0011_1011);
            let normal = TypeByte::new(0b0000_1011);

            assert!(err.is_none());
            assert!(normal.is_some());
        }

        #[test]
        fn check_error_bit() {
            let mut byte = TypeByte::new(0b0000_1011).unwrap();

            assert_eq!(byte.error_bit(), false);
            byte.set_error_bit(true);
            assert_eq!(byte.error_bit(), true);
            byte.set_error_bit(false);
            assert_eq!(byte.error_bit(), false);
        }

        #[test]
        fn check_types() {
            for (i, t) in HANDLE_TYPES.iter().enumerate() {
                let byte = TypeByte(i as u8);
                let error_byte = TypeByte(i as u8 | (1 << 7));

                assert_eq!(byte.get_type(), *t);
                assert_eq!(error_byte.get_type(), *t);
            }
        }

        #[test]
        fn check_into_type_byte() {
            for (i, t) in HANDLE_TYPES.iter().enumerate() {
                let value: TypeByte = (*t).into();
                assert_eq!(value, TypeByte(i as u8));
            }
        }
    }

    mod handle {
        use super::*;

        #[test]
        fn check_constructor() {
            for (i, t) in HANDLE_TYPES.iter().enumerate() {
                let handle = Handle::new(*t, i as u16);
                assert_eq!(handle.index, i as u16);
                assert_eq!(handle.type_byte, (*t).into());
            }
        }

        #[test]
        fn check_from_i32() {
            let handle = Handle::from_i32(0b0000_0101_0000_0001_0000_0000_0000_1001).unwrap();
            assert_eq!(handle.type_byte.get_type(), HandleType::PWM);
            assert_eq!(handle.index, 0b0000_0101_0000_0001);
        }

        #[test]
        fn check_into_i32() {
            let handle = Handle::new(HandleType::PWM, 0b0000_0101_0000_0001);
            let handle_i32: i32 = handle.into();
            assert_eq!(handle_i32, 0b0000_0101_0000_0001_0000_0000_0000_1001)
        }
    }

    mod port_handle {
        use super::*;

        #[test]
        fn check_constructor() {
            let handle = PortHandle::new(7, 24);
            assert_eq!(handle.module, 7);
            assert_eq!(handle.channel, 24);
            assert_eq!(handle.type_byte, HandleType::Port.into());
        }

        #[test]
        fn check_from_i32() {
            let handle = PortHandle::from_i32(0b0000_0101_0000_0001_0000_0000_0000_0010).unwrap();
            assert_eq!(handle.type_byte.get_type(), HandleType::Port);
            assert_eq!(handle.channel, 0b0000_0101);
            assert_eq!(handle.module, 0b0000_0001);
        }

        #[test]
        fn check_into_i32() {
            let handle = PortHandle::new(0b0000_0001, 0b0000_0101);
            let handle_i32: i32 = handle.into();
            assert_eq!(handle_i32, 0b0000_0101_0000_0001_0000_0000_0000_0010)
        }
    }

}
<commit_msg>Made it build on stable<commit_after>use std::mem;

// FIXME: Come up with good names and finalize them.

#[repr(u8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum HandleType {
	Undefined     = 0,
	DIO           = 1,  // 1 bit
	Port          = 2,  // 2 bits
	Notifier      = 3,
	Interrupt     = 4,  // 3 bits
	AnalogOutput  = 5,
	AnalogInput   = 6,
	AnalogTrigger = 7,
	Relay         = 8,  // 4 bits
	PWM           = 9,
	DigitalPWM    = 10,
	Counter       = 11,
	FPGAEncoder   = 12,
	Encoder       = 13,
	Compressor    = 14,
	Solenoid      = 15,
	AnalogGyro    = 16, // 5 bits
	Vendor        = 17
}

impl HandleType {
    /// Converts a `u8` to a `HandleType`. This produces Undefined Behavior when `num > 17`.
    pub unsafe fn from_u8_unchecked(num: u8) -> HandleType {
        mem::transmute(num)
    }

    /// Converts a `u8` to a `HandleType`, returning `None` if none of the variants were matched.
    pub fn from_u8(num: u8) -> Option<HandleType> {
        if num <= 17 {
            Some(unsafe { mem::transmute(num) })
        } else {
            None
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct TypeByte(u8);

impl TypeByte {
    pub fn new(byte: u8) -> Option<TypeByte> {
        if byte & !(1 << 7) <= 17 {
            unsafe { Some(mem::transmute(byte)) }
        } else {
            None
        }
    }

    /// Set the error bit
    #[inline]
    pub fn set_error_bit(&mut self, error: bool) {
        self.0 = (self.0 & !(1 << 7)) | ((error as u8) << 7)
    }

    /// Get the error bit
    #[inline]
    pub fn error_bit(&self) -> bool {
        (self.0 >> 7) & 1 != 0
    }

    pub fn get_type(&self) -> HandleType {
        unsafe { mem::transmute(self.0 & !(1 << 7)) }
    }
}

impl From<HandleType> for TypeByte {
	// Handle type never has the error bit set by itself
	fn from(handle_type: HandleType) -> TypeByte {
		unsafe { mem::transmute(handle_type) }
	}
}

// TODO: Is there a better way to structure this?
/// A sort of "protocol" for handles.
///
/// | Bits  | Meaning     | Type |
/// |-------|-------------|:----:|
/// | 31    | Error       | bool |
/// | 24-30 | Handle Type |  u8  |
/// | 16-23 | Unused      |  u8  |
/// | 0-15  | Payload     |  u16 |
///
/// ### Payload
/// The `Data` type is what type the payload should be converted into.
/// For normal handles, this is just a `u16` representing the index.
/// For port handles, this is two `u8`s, representing the module and the channel, respectively.
pub trait HandleProtocol: Sized {
    /// The data derived from the last 16 bits of the struct
    type Data;

    /// Transform the last 16 bits into whatever data type was defined
    fn to_data(&self) -> Self::Data;
}

/// Struct representing some sort of indexed data.
///
/// General Handle Data Layout
///
/// * Bits 0-15:  Handle Index
/// * Bits 16-23: Unused
/// * Bits 24-30: Handle Type
/// * Bit  31:    1 if handle error, 0 if no error
///
/// Other specialized handles will use different formats, however Bits 24-31 are
/// always reserved for type and error handling.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct Handle {
    /// The type of the handle. This is the `HandleType` enum, only the top
    /// bit denotes an error status
    pub type_byte: TypeByte,
    /// 8 unused bits
    _padding: u8,
    /// TODO
    pub index: u16
}

impl Handle {
	/// Creates a new handle from its parts
	pub fn new(type_byte: HandleType, index: u16) -> Handle {
		Handle { type_byte: type_byte.into(), _padding: 0, index: index }
	}

	/// Convert an i32 to a Handle. Unsafe, as there is no associated variant of `HandleType` for `num > 17`
	pub unsafe fn from_i32_unchecked(num: i32) -> Handle {
		mem::transmute(num)
	}

    /// Convert an i32 to a Handle. Returns `None` if the type byte of `num` is out of bounds
    pub fn from_i32(num: i32) -> Option<Handle> {
        if (num >> 24) & !(1 << 7) <= 17 {
            Some(unsafe { mem::transmute(num) })
        } else {
            None
        }
    }
}

impl HandleProtocol for Handle {
    type Data = u16;

    fn to_data(&self) -> u16 {
        self.index
    }
}

impl From<Handle> for i32 {
	fn from(handle: Handle) -> i32 {
		// Our struct has the same memory layout as the i32 representation
		unsafe { mem::transmute(handle) }
	}
}

/// Struct representing some port/module on the robot
///
/// Port Handle Data Layout
///
/// * Bits 0-7:   Channel Number
/// * Bits 8-15:  Module Number
/// * Bits 16-23: Unused
/// * Bits 24-30: Handle Type
/// * Bit  31:    1 if handle error, 0 if no error
///
/// This struct is 32 bits wide.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct PortHandle {
	/// The type of the handle. This is the `HandleType` enum, only the top
	/// bit denotes an error status
	pub type_byte: TypeByte,
	/// 8 unused bits
	_padding: u8,
	/// The module ID (TODO: possibly from the cRIO days?)
	pub module: u8,
	/// The channel ID
	pub channel: u8
}

impl PortHandle {
	/// Creates a new handle from its parts
	pub fn new(module: u8, channel: u8) -> PortHandle {
        // A `PortHandle` always has a handle type of `Port`
		PortHandle {
            type_byte: HandleType::Port.into(),
            _padding: 0,
            module: module,
            channel: channel
        }
	}

	/// Convert an i32 to a Handle. Unsafe, as there is no associated variant for `num > 17`
	pub unsafe fn from_i32_unchecked(num: i32) -> PortHandle {
		mem::transmute(num)
	}

    /// Convert an `i32` to a `PortHandle`
    pub fn from_i32(num: i32) -> Option<PortHandle> {
        if (num >> 24) & !(1 << 7) <= 17 {
            Some(unsafe { mem::transmute(num) })
        } else {
            None
        }
    }
}

impl HandleProtocol for PortHandle {
    type Data = (u8, u8);

    fn to_data(&self) -> (u8, u8) {
        (self.module, self.channel)
    }
}

impl From<PortHandle> for i32 {
	fn from(handle: PortHandle) -> i32 {
		// Our struct has the same memory layout as the i32 representation
		unsafe { mem::transmute(handle) }
	}
}

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

    const HANDLE_TYPES: [HandleType; 18] = [
        HandleType::Undefined,
        HandleType::DIO,
        HandleType::Port,
        HandleType::Notifier,
        HandleType::Interrupt,
        HandleType::AnalogOutput,
        HandleType::AnalogInput,
        HandleType::AnalogTrigger,
        HandleType::Relay,
        HandleType::PWM,
        HandleType::DigitalPWM,
        HandleType::Counter,
        HandleType::FPGAEncoder,
        HandleType::Encoder,
        HandleType::Compressor,
        HandleType::Solenoid,
        HandleType::AnalogGyro,
        HandleType::Vendor
    ];

    #[test]
    fn check_handle_type() {
        for (i, t) in HANDLE_TYPES.iter().enumerate() {
            assert_eq!(HandleType::from_u8(i as u8).unwrap(), *t);
        }
    }

    mod type_byte {
        use super::*;

        #[test]
        fn check_constructor_error() {
            let err = TypeByte::new(0b0011_1011);
            let normal = TypeByte::new(0b0000_1011);

            assert!(err.is_none());
            assert!(normal.is_some());
        }

        #[test]
        fn check_error_bit() {
            let mut byte = TypeByte::new(0b0000_1011).unwrap();

            assert_eq!(byte.error_bit(), false);
            byte.set_error_bit(true);
            assert_eq!(byte.error_bit(), true);
            byte.set_error_bit(false);
            assert_eq!(byte.error_bit(), false);
        }

        #[test]
        fn check_types() {
            for (i, t) in HANDLE_TYPES.iter().enumerate() {
                let byte = TypeByte(i as u8);
                let error_byte = TypeByte(i as u8 | (1 << 7));

                assert_eq!(byte.get_type(), *t);
                assert_eq!(error_byte.get_type(), *t);
            }
        }

        #[test]
        fn check_into_type_byte() {
            for (i, t) in HANDLE_TYPES.iter().enumerate() {
                let value: TypeByte = (*t).into();
                assert_eq!(value, TypeByte(i as u8));
            }
        }
    }

    mod handle {
        use super::*;

        #[test]
        fn check_constructor() {
            for (i, t) in HANDLE_TYPES.iter().enumerate() {
                let handle = Handle::new(*t, i as u16);
                assert_eq!(handle.index, i as u16);
                assert_eq!(handle.type_byte, (*t).into());
            }
        }

        #[test]
        fn check_from_i32() {
            let handle = Handle::from_i32(0b0000_0101_0000_0001_0000_0000_0000_1001).unwrap();
            assert_eq!(handle.type_byte.get_type(), HandleType::PWM);
            assert_eq!(handle.index, 0b0000_0101_0000_0001);
        }

        #[test]
        fn check_into_i32() {
            let handle = Handle::new(HandleType::PWM, 0b0000_0101_0000_0001);
            let handle_i32: i32 = handle.into();
            assert_eq!(handle_i32, 0b0000_0101_0000_0001_0000_0000_0000_1001)
        }
    }

    mod port_handle {
        use super::*;

        #[test]
        fn check_constructor() {
            let handle = PortHandle::new(7, 24);
            assert_eq!(handle.module, 7);
            assert_eq!(handle.channel, 24);
            assert_eq!(handle.type_byte, HandleType::Port.into());
        }

        #[test]
        fn check_from_i32() {
            let handle = PortHandle::from_i32(0b0000_0101_0000_0001_0000_0000_0000_0010).unwrap();
            assert_eq!(handle.type_byte.get_type(), HandleType::Port);
            assert_eq!(handle.channel, 0b0000_0101);
            assert_eq!(handle.module, 0b0000_0001);
        }

        #[test]
        fn check_into_i32() {
            let handle = PortHandle::new(0b0000_0001, 0b0000_0101);
            let handle_i32: i32 = handle.into();
            assert_eq!(handle_i32, 0b0000_0101_0000_0001_0000_0000_0000_0010)
        }
    }

}
<|endoftext|>


<commit_before>//! Procedural macro for the `#[async]` attribute.
//!
//! This crate is an implementation of the `#[async]` attribute as a procedural
//! macro. This is nightly-only for now as it's using the unstable features of
//! procedural macros. Furthermore it's generating code that's using a new
//! keyword, `yield`, and a new construct, generators, both of which are also
//! unstable.
//!
//! Currently this crate depends on `syn` and `quote` to do all the heavy
//! lifting, this is just a very small shim around creating a closure/future out
//! of a generator.

#![feature(proc_macro)]
#![recursion_limit = "128"]

extern crate proc_macro2;
extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use proc_macro2::Span;
use proc_macro::{TokenStream, TokenTree, Delimiter, TokenNode};
use quote::{Tokens, ToTokens};
use syn::*;
use syn::fold::Folder;

#[proc_macro_attribute]
pub fn async(attribute: TokenStream, function: TokenStream) -> TokenStream {
    // Handle arguments to the #[async] attribute, if any
    let attribute = attribute.to_string();
    let boxed = if attribute == "( boxed )" {
        true
    } else if attribute == "" {
        false
    } else {
        panic!("the #[async] attribute currently only takes `boxed` as an arg");
    };

    // Parse our item, expecting a function. This function may be an actual
    // top-level function or it could be a method (typically dictated by the
    // arguments). We then extract everything we'd like to use.
    let Item { attrs, node } = syn::parse(function)
        .expect("failed to parse tokens as a function");
    let ItemFn {
        ident,
        vis,
        unsafety,
        constness,
        abi,
        block,
        decl,
        ..
    } = match node {
        ItemKind::Fn(item) => item,
        _ => panic!("#[async] can only be applied to functions"),
    };
    let FnDecl {
        inputs,
        output,
        variadic,
        generics,
        fn_token,
        ..
    } = { *decl };
    let where_clause = &generics.where_clause;
    assert!(!variadic, "variadic functions cannot be async");
    let (output, rarrow_token) = match output {
        FunctionRetTy::Ty(t, rarrow_token) => (t, rarrow_token),
        FunctionRetTy::Default => {
            (TyTup {
                tys: Default::default(),
                lone_comma: Default::default(),
                paren_token: Default::default(),
            }.into(), Default::default())
        }
    };

    // We've got to get a bit creative with our handling of arguments. For a
    // number of reasons we translate this:
    //
    //      fn foo(ref a: u32) -> Result<u32, u32> {
    //          // ...
    //      }
    //
    // into roughly:
    //
    //      fn foo(__arg_0: u32) -> impl Future<...> {
    //          gen(move || {
    //              let ref a = __arg0;
    //
    //              // ...
    //          })
    //      }
    //
    // The intention here is to ensure that all local function variables get
    // moved into the generator we're creating, and they're also all then bound
    // appropriately according to their patterns and whatnot.
    //
    // We notably skip everything related to `self` which typically doesn't have
    // many patterns with it and just gets captured naturally.
    let mut inputs_no_patterns = Vec::new();
    let mut patterns = Vec::new();
    let mut temp_bindings = Vec::new();
    for (i, input) in inputs.into_iter().enumerate() {
        let input = input.into_item();

        // `self: Box<Self>` will get captured naturally
        let mut is_input_no_pattern = false;
        if let FnArg::Captured(ref arg) = input {
            if let Pat::Ident(PatIdent { ref ident, ..}) = arg.pat {
                if ident == "self" {
                    is_input_no_pattern = true;
                }
            }
        }
        if is_input_no_pattern {
            inputs_no_patterns.push(input);
            continue
        }

        match input {
            FnArg::Captured(ArgCaptured {
                pat: syn::Pat::Ident(syn::PatIdent {
                    mode: BindingMode::ByValue(_),
                    ..
                }),
                ..
            }) => {
                inputs_no_patterns.push(input);
            }

            // `ref a: B` (or some similar pattern)
            FnArg::Captured(ArgCaptured { pat, ty, colon_token }) => {
                patterns.push(pat);
                let ident = Ident::from(format!("__arg_{}", i));
                temp_bindings.push(ident.clone());
                let pat = PatIdent {
                    mode: BindingMode::ByValue(Mutability::Immutable),
                    ident: ident,
                    at_token: None,
                    subpat: None,
                };
                inputs_no_patterns.push(ArgCaptured {
                    pat: pat.into(),
                    ty,
                    colon_token,
                }.into());
            }

            // Other `self`-related arguments get captured naturally
            _ => {
                inputs_no_patterns.push(input);
            }
        }
    }

    // This is the point where we handle
    //
    //      #[async]
    //      for x in y {
    //      }
    //
    // Basically just take all those expression and expand them.
    let block = ExpandAsyncFor.fold_block(*block);

    // TODO: can we lift the restriction that `futures` must be at the root of
    //       the crate?

    let output_span = first_last(&output);
    let return_ty = if boxed {
        quote! {
            Box<::futures::Future<
                Item = <! as ::futures::__rt::IsResult>::Ok,
                Error = <! as ::futures::__rt::IsResult>::Err,
            >>
        }
    } else {
        // Dunno why this is buggy, hits weird typecheck errors in tests
        //
        // quote! {
        //     impl ::futures::Future<
        //         Item = <#output as ::futures::__rt::MyTry>::MyOk,
        //         Error = <#output as ::futures::__rt::MyTry>::MyError,
        //     >
        // }
        quote! { impl ::futures::__rt::MyFuture<!> + 'static }
    };
    let return_ty = respan(return_ty.into(), &output_span);
    let return_ty = replace_bang(return_ty, &output);

    let block_inner = quote! {
        #( let #patterns = #temp_bindings; )*
        #block
    };
    let mut result = Tokens::new();
    block.brace_token.surround(&mut result, |tokens| {
        block_inner.to_tokens(tokens);
    });
    syn::tokens::Semi([block.brace_token.0]).to_tokens(&mut result);

    let gen_body_inner = quote! {
        let __e: ::std::result::Result<_,_> = #result

        // Ensure that this closure is a generator, even if it doesn't
        // have any `yield` statements.
        #[allow(unreachable_code)]
        {
            return __e;
            loop { yield }
        }
    };
    let mut gen_body = Tokens::new();
    block.brace_token.surround(&mut gen_body, |tokens| {
        gen_body_inner.to_tokens(tokens);
    });

    // Give the invocation of the `gen` function the same span as the output
    // as currently errors related to it being a result are targeted here. Not
    // sure if more errors will highlight this function call...
    let gen_function = quote! { ::futures::__rt::gen };
    let gen_function = respan(gen_function.into(), &output_span);
    let body_inner = quote! {
        #gen_function (move || #gen_body)
    };
    let body_inner = if boxed {
        let body = quote! { Box::new(#body_inner) };
        respan(body.into(), &output_span)
    } else {
        body_inner.into()
    };
    let mut body = Tokens::new();
    block.brace_token.surround(&mut body, |tokens| {
        body_inner.to_tokens(tokens);
    });

    let output = quote! {
        #(#attrs)*
        #vis #unsafety #abi #constness
        #fn_token #ident #generics(#(#inputs_no_patterns),*)
            #rarrow_token #return_ty
            #where_clause
        #body
    };

    // println!("{}", output);
    output.into()
}

#[proc_macro]
pub fn async_block(input: TokenStream) -> TokenStream {
    let input = TokenStream::from(TokenTree {
        kind: TokenNode::Group(Delimiter::Brace, input),
        span: Default::default(),
    });
    let expr = syn::parse(input)
        .expect("failed to parse tokens as an expression");
    let expr = ExpandAsyncFor.fold_expr(expr);

    (quote! {
        ::futures::__rt::gen(move || { #expr })
    }).into()
}

struct ExpandAsyncFor;

impl Folder for ExpandAsyncFor {
    fn fold_expr(&mut self, expr: Expr) -> Expr {
        let expr = fold::noop_fold_expr(self, expr);
        if expr.attrs.len() != 1 {
            return expr
        }
        // TODO: more validation here
        if expr.attrs[0].path.segments.get(0).item().ident != "async" {
            return expr
        }
        let all = match expr.node {
            ExprKind::ForLoop(item) => item,
            _ => panic!("only for expressions can have #[async]"),
        };
        let ExprForLoop { pat, expr, body, label, colon_token, .. } = all;

        // Basically just expand to a `poll` loop
        let tokens = quote! {{
            let mut __stream = #expr;
            #label
            #colon_token
            loop {
                let #pat = {
                    extern crate futures_await;
                    let r = futures_await::Stream::poll(&mut __stream)?;
                    match r {
                        futures_await::Async::Ready(e) => {
                            match e {
                                futures_await::__rt::Some(e) => e,
                                futures_await::__rt::None => break,
                            }
                        }
                        futures_await::Async::NotReady => {
                            yield;
                            continue
                        }
                    }
                };

                #body
            }
        }};
        syn::parse(tokens.into()).unwrap()
    }

    // Don't recurse into items
    fn fold_item(&mut self, item: Item) -> Item {
        item
    }
}

fn first_last(tokens: &ToTokens) -> (Span, Span) {
    let mut spans = Tokens::new();
    tokens.to_tokens(&mut spans);
    let good_tokens = proc_macro2::TokenStream::from(spans).into_iter().collect::<Vec<_>>();
    let first_span = good_tokens.first().map(|t| t.span).unwrap_or(Default::default());
    let last_span = good_tokens.last().map(|t| t.span).unwrap_or(first_span);
    (first_span, last_span)
}

fn respan(input: proc_macro2::TokenStream,
          &(first_span, last_span): &(Span, Span)) -> proc_macro2::TokenStream {
    let mut new_tokens = input.into_iter().collect::<Vec<_>>();
    if let Some(token) = new_tokens.first_mut() {
        token.span = first_span;
    }
    for token in new_tokens.iter_mut().skip(1) {
        token.span = last_span;
    }
    new_tokens.into_iter().collect()
}

fn replace_bang(input: proc_macro2::TokenStream, tokens: &ToTokens)
    -> proc_macro2::TokenStream
{
    let mut new_tokens = Tokens::new();
    for token in input.into_iter() {
        match token.kind {
            proc_macro2::TokenNode::Op('!', _) => tokens.to_tokens(&mut new_tokens),
            _ => token.to_tokens(&mut new_tokens),
        }
    }
    new_tokens.into()
}
<commit_msg>Use Result from the `futures-await` crate<commit_after>//! Procedural macro for the `#[async]` attribute.
//!
//! This crate is an implementation of the `#[async]` attribute as a procedural
//! macro. This is nightly-only for now as it's using the unstable features of
//! procedural macros. Furthermore it's generating code that's using a new
//! keyword, `yield`, and a new construct, generators, both of which are also
//! unstable.
//!
//! Currently this crate depends on `syn` and `quote` to do all the heavy
//! lifting, this is just a very small shim around creating a closure/future out
//! of a generator.

#![feature(proc_macro)]
#![recursion_limit = "128"]

extern crate proc_macro2;
extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use proc_macro2::Span;
use proc_macro::{TokenStream, TokenTree, Delimiter, TokenNode};
use quote::{Tokens, ToTokens};
use syn::*;
use syn::fold::Folder;

#[proc_macro_attribute]
pub fn async(attribute: TokenStream, function: TokenStream) -> TokenStream {
    // Handle arguments to the #[async] attribute, if any
    let attribute = attribute.to_string();
    let boxed = if attribute == "( boxed )" {
        true
    } else if attribute == "" {
        false
    } else {
        panic!("the #[async] attribute currently only takes `boxed` as an arg");
    };

    // Parse our item, expecting a function. This function may be an actual
    // top-level function or it could be a method (typically dictated by the
    // arguments). We then extract everything we'd like to use.
    let Item { attrs, node } = syn::parse(function)
        .expect("failed to parse tokens as a function");
    let ItemFn {
        ident,
        vis,
        unsafety,
        constness,
        abi,
        block,
        decl,
        ..
    } = match node {
        ItemKind::Fn(item) => item,
        _ => panic!("#[async] can only be applied to functions"),
    };
    let FnDecl {
        inputs,
        output,
        variadic,
        generics,
        fn_token,
        ..
    } = { *decl };
    let where_clause = &generics.where_clause;
    assert!(!variadic, "variadic functions cannot be async");
    let (output, rarrow_token) = match output {
        FunctionRetTy::Ty(t, rarrow_token) => (t, rarrow_token),
        FunctionRetTy::Default => {
            (TyTup {
                tys: Default::default(),
                lone_comma: Default::default(),
                paren_token: Default::default(),
            }.into(), Default::default())
        }
    };

    // We've got to get a bit creative with our handling of arguments. For a
    // number of reasons we translate this:
    //
    //      fn foo(ref a: u32) -> Result<u32, u32> {
    //          // ...
    //      }
    //
    // into roughly:
    //
    //      fn foo(__arg_0: u32) -> impl Future<...> {
    //          gen(move || {
    //              let ref a = __arg0;
    //
    //              // ...
    //          })
    //      }
    //
    // The intention here is to ensure that all local function variables get
    // moved into the generator we're creating, and they're also all then bound
    // appropriately according to their patterns and whatnot.
    //
    // We notably skip everything related to `self` which typically doesn't have
    // many patterns with it and just gets captured naturally.
    let mut inputs_no_patterns = Vec::new();
    let mut patterns = Vec::new();
    let mut temp_bindings = Vec::new();
    for (i, input) in inputs.into_iter().enumerate() {
        let input = input.into_item();

        // `self: Box<Self>` will get captured naturally
        let mut is_input_no_pattern = false;
        if let FnArg::Captured(ref arg) = input {
            if let Pat::Ident(PatIdent { ref ident, ..}) = arg.pat {
                if ident == "self" {
                    is_input_no_pattern = true;
                }
            }
        }
        if is_input_no_pattern {
            inputs_no_patterns.push(input);
            continue
        }

        match input {
            FnArg::Captured(ArgCaptured {
                pat: syn::Pat::Ident(syn::PatIdent {
                    mode: BindingMode::ByValue(_),
                    ..
                }),
                ..
            }) => {
                inputs_no_patterns.push(input);
            }

            // `ref a: B` (or some similar pattern)
            FnArg::Captured(ArgCaptured { pat, ty, colon_token }) => {
                patterns.push(pat);
                let ident = Ident::from(format!("__arg_{}", i));
                temp_bindings.push(ident.clone());
                let pat = PatIdent {
                    mode: BindingMode::ByValue(Mutability::Immutable),
                    ident: ident,
                    at_token: None,
                    subpat: None,
                };
                inputs_no_patterns.push(ArgCaptured {
                    pat: pat.into(),
                    ty,
                    colon_token,
                }.into());
            }

            // Other `self`-related arguments get captured naturally
            _ => {
                inputs_no_patterns.push(input);
            }
        }
    }

    // This is the point where we handle
    //
    //      #[async]
    //      for x in y {
    //      }
    //
    // Basically just take all those expression and expand them.
    let block = ExpandAsyncFor.fold_block(*block);

    // TODO: can we lift the restriction that `futures` must be at the root of
    //       the crate?

    let output_span = first_last(&output);
    let return_ty = if boxed {
        quote! {
            Box<::futures::Future<
                Item = <! as ::futures::__rt::IsResult>::Ok,
                Error = <! as ::futures::__rt::IsResult>::Err,
            >>
        }
    } else {
        // Dunno why this is buggy, hits weird typecheck errors in tests
        //
        // quote! {
        //     impl ::futures::Future<
        //         Item = <#output as ::futures::__rt::MyTry>::MyOk,
        //         Error = <#output as ::futures::__rt::MyTry>::MyError,
        //     >
        // }
        quote! { impl ::futures::__rt::MyFuture<!> + 'static }
    };
    let return_ty = respan(return_ty.into(), &output_span);
    let return_ty = replace_bang(return_ty, &output);

    let block_inner = quote! {
        #( let #patterns = #temp_bindings; )*
        #block
    };
    let mut result = Tokens::new();
    block.brace_token.surround(&mut result, |tokens| {
        block_inner.to_tokens(tokens);
    });
    syn::tokens::Semi([block.brace_token.0]).to_tokens(&mut result);

    let gen_body_inner = quote! {
        let __e: ::futures::__rt::Result<_,_> = #result

        // Ensure that this closure is a generator, even if it doesn't
        // have any `yield` statements.
        #[allow(unreachable_code)]
        {
            return __e;
            loop { yield }
        }
    };
    let mut gen_body = Tokens::new();
    block.brace_token.surround(&mut gen_body, |tokens| {
        gen_body_inner.to_tokens(tokens);
    });

    // Give the invocation of the `gen` function the same span as the output
    // as currently errors related to it being a result are targeted here. Not
    // sure if more errors will highlight this function call...
    let gen_function = quote! { ::futures::__rt::gen };
    let gen_function = respan(gen_function.into(), &output_span);
    let body_inner = quote! {
        #gen_function (move || #gen_body)
    };
    let body_inner = if boxed {
        let body = quote! { Box::new(#body_inner) };
        respan(body.into(), &output_span)
    } else {
        body_inner.into()
    };
    let mut body = Tokens::new();
    block.brace_token.surround(&mut body, |tokens| {
        body_inner.to_tokens(tokens);
    });

    let output = quote! {
        #(#attrs)*
        #vis #unsafety #abi #constness
        #fn_token #ident #generics(#(#inputs_no_patterns),*)
            #rarrow_token #return_ty
            #where_clause
        #body
    };

    // println!("{}", output);
    output.into()
}

#[proc_macro]
pub fn async_block(input: TokenStream) -> TokenStream {
    let input = TokenStream::from(TokenTree {
        kind: TokenNode::Group(Delimiter::Brace, input),
        span: Default::default(),
    });
    let expr = syn::parse(input)
        .expect("failed to parse tokens as an expression");
    let expr = ExpandAsyncFor.fold_expr(expr);

    (quote! {
        ::futures::__rt::gen(move || { #expr })
    }).into()
}

struct ExpandAsyncFor;

impl Folder for ExpandAsyncFor {
    fn fold_expr(&mut self, expr: Expr) -> Expr {
        let expr = fold::noop_fold_expr(self, expr);
        if expr.attrs.len() != 1 {
            return expr
        }
        // TODO: more validation here
        if expr.attrs[0].path.segments.get(0).item().ident != "async" {
            return expr
        }
        let all = match expr.node {
            ExprKind::ForLoop(item) => item,
            _ => panic!("only for expressions can have #[async]"),
        };
        let ExprForLoop { pat, expr, body, label, colon_token, .. } = all;

        // Basically just expand to a `poll` loop
        let tokens = quote! {{
            let mut __stream = #expr;
            #label
            #colon_token
            loop {
                let #pat = {
                    extern crate futures_await;
                    let r = futures_await::Stream::poll(&mut __stream)?;
                    match r {
                        futures_await::Async::Ready(e) => {
                            match e {
                                futures_await::__rt::Some(e) => e,
                                futures_await::__rt::None => break,
                            }
                        }
                        futures_await::Async::NotReady => {
                            yield;
                            continue
                        }
                    }
                };

                #body
            }
        }};
        syn::parse(tokens.into()).unwrap()
    }

    // Don't recurse into items
    fn fold_item(&mut self, item: Item) -> Item {
        item
    }
}

fn first_last(tokens: &ToTokens) -> (Span, Span) {
    let mut spans = Tokens::new();
    tokens.to_tokens(&mut spans);
    let good_tokens = proc_macro2::TokenStream::from(spans).into_iter().collect::<Vec<_>>();
    let first_span = good_tokens.first().map(|t| t.span).unwrap_or(Default::default());
    let last_span = good_tokens.last().map(|t| t.span).unwrap_or(first_span);
    (first_span, last_span)
}

fn respan(input: proc_macro2::TokenStream,
          &(first_span, last_span): &(Span, Span)) -> proc_macro2::TokenStream {
    let mut new_tokens = input.into_iter().collect::<Vec<_>>();
    if let Some(token) = new_tokens.first_mut() {
        token.span = first_span;
    }
    for token in new_tokens.iter_mut().skip(1) {
        token.span = last_span;
    }
    new_tokens.into_iter().collect()
}

fn replace_bang(input: proc_macro2::TokenStream, tokens: &ToTokens)
    -> proc_macro2::TokenStream
{
    let mut new_tokens = Tokens::new();
    for token in input.into_iter() {
        match token.kind {
            proc_macro2::TokenNode::Op('!', _) => tokens.to_tokens(&mut new_tokens),
            _ => token.to_tokens(&mut new_tokens),
        }
    }
    new_tokens.into()
}
<|endoftext|>


<commit_before>#![cfg_attr(all(feature="serde_type"), feature(proc_macro))]

extern crate iron;
extern crate router;
extern crate env_logger;
extern crate handlebars_iron as hbs;
#[cfg(not(feature = "serde_type"))]
extern crate rustc_serialize;
#[cfg(feature = "serde_type")]
extern crate serde;
#[cfg(feature = "serde_type")]
extern crate serde_json;
#[cfg(feature = "serde_type")]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate maplit;

use iron::prelude::*;
use iron::status;
use router::Router;
use hbs::{Template, HandlebarsEngine, DirectorySource, MemorySource};

#[cfg(not(feature = "serde_type"))]
mod data {
    use rustc_serialize::json::{ToJson, Json};
    use std::collections::BTreeMap;

    pub struct Team {
        name: String,
        pts: u16,
    }

    impl ToJson for Team {
        fn to_json(&self) -> Json {
            let mut m: BTreeMap<String, Json> = BTreeMap::new();
            m.insert("name".to_string(), self.name.to_json());
            m.insert("pts".to_string(), self.pts.to_json());
            m.to_json()
        }
    }

    pub fn make_data() -> BTreeMap<String, Json> {
        let mut data = BTreeMap::new();

        data.insert("year".to_string(), "2015".to_json());

        let teams = vec![Team {
                             name: "Jiangsu Sainty".to_string(),
                             pts: 43u16,
                         },
                         Team {
                             name: "Beijing Guoan".to_string(),
                             pts: 27u16,
                         },
                         Team {
                             name: "Guangzhou Evergrand".to_string(),
                             pts: 22u16,
                         },
                         Team {
                             name: "Shandong Luneng".to_string(),
                             pts: 12u16,
                         }];

        data.insert("teams".to_string(), teams.to_json());
        data.insert("engine".to_string(), "rustc_serialize".to_json());
        data
    }
}

#[cfg(feature = "serde_type")]
mod data {
    use serde_json::value::{self, Value};
    use std::collections::BTreeMap;

    #[derive(Serialize, Debug)]
    pub struct Team {
        name: String,
        pts: u16,
    }

    pub fn make_data() -> BTreeMap<String, Value> {
        let mut data = BTreeMap::new();

        data.insert("year".to_string(), value::to_value(&"2015"));

        let teams = vec![Team {
                             name: "Jiangsu Sainty".to_string(),
                             pts: 43u16,
                         },
                         Team {
                             name: "Beijing Guoan".to_string(),
                             pts: 27u16,
                         },
                         Team {
                             name: "Guangzhou Evergrand".to_string(),
                             pts: 22u16,
                         },
                         Team {
                             name: "Shandong Luneng".to_string(),
                             pts: 12u16,
                         }];

        data.insert("teams".to_string(), value::to_value(&teams));
        data.insert("engine".to_string(), value::to_value(&"serde_json"));
        data
    }
}

/// the handlers
fn index(_: &mut Request) -> IronResult<Response> {
    use data::*;

    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("some/path/hello", data)).set_mut(status::Ok);
    Ok(resp)
}

fn memory(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    resp.set_mut(Template::new("memory", ())).set_mut(status::Ok);
    Ok(resp)
}

fn temp(_: &mut Request) -> IronResult<Response> {
    use data::*;

    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::with("
{{engine}}
", data)).set_mut(status::Ok);
    Ok(resp)
}

fn main() {
    env_logger::init().unwrap();

    let mut hbse = HandlebarsEngine::new();

    // add a directory source, all files with .hbs suffix will be loaded as template
    hbse.add(Box::new(DirectorySource::new("./examples/templates/", ".hbs")));

    let mem_templates = btreemap! {
        "memory".to_owned() => "
Memory Template
".to_owned()
    };
    // add a memory based source
    hbse.add(Box::new(MemorySource(mem_templates)));

    // load templates from all registered sources
    if let Err(r) = hbse.reload() {
        panic!("{}", r);
    }

    let mut router = Router::new();
    router.get("/", index)
          .get("/mem", memory)
          .get("/temp", temp);
    let mut chain = Chain::new(router);
    chain.link_after(hbse);
    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<commit_msg>(test) improve example<commit_after>#![cfg_attr(all(feature="serde_type"), feature(proc_macro))]

extern crate iron;
extern crate router;
extern crate env_logger;
extern crate handlebars_iron as hbs;
#[cfg(not(feature = "serde_type"))]
extern crate rustc_serialize;
#[cfg(feature = "serde_type")]
extern crate serde;
#[cfg(feature = "serde_type")]
extern crate serde_json;
#[cfg(feature = "serde_type")]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate maplit;

use iron::prelude::*;
use iron::status;
use router::Router;
use hbs::{Template, HandlebarsEngine, DirectorySource, MemorySource};

#[cfg(not(feature = "serde_type"))]
mod data {
    use rustc_serialize::json::{ToJson, Json};
    use std::collections::BTreeMap;

    pub struct Team {
        name: String,
        pts: u16,
    }

    impl ToJson for Team {
        fn to_json(&self) -> Json {
            let mut m: BTreeMap<String, Json> = BTreeMap::new();
            m.insert("name".to_string(), self.name.to_json());
            m.insert("pts".to_string(), self.pts.to_json());
            m.to_json()
        }
    }

    pub fn make_data() -> BTreeMap<String, Json> {
        let mut data = BTreeMap::new();

        data.insert("year".to_string(), "2015".to_json());

        let teams = vec![Team {
                             name: "Jiangsu Sainty".to_string(),
                             pts: 43u16,
                         },
                         Team {
                             name: "Beijing Guoan".to_string(),
                             pts: 27u16,
                         },
                         Team {
                             name: "Guangzhou Evergrand".to_string(),
                             pts: 22u16,
                         },
                         Team {
                             name: "Shandong Luneng".to_string(),
                             pts: 12u16,
                         }];

        data.insert("teams".to_string(), teams.to_json());
        data.insert("engine".to_string(), "rustc_serialize".to_json());
        data
    }
}

#[cfg(feature = "serde_type")]
mod data {
    use serde_json::value::{self, Value};
    use std::collections::BTreeMap;

    #[derive(Serialize, Debug)]
    pub struct Team {
        name: String,
        pts: u16,
    }

    pub fn make_data() -> BTreeMap<String, Value> {
        let mut data = BTreeMap::new();

        data.insert("year".to_string(), value::to_value(&"2015"));

        let teams = vec![Team {
                             name: "Jiangsu Sainty".to_string(),
                             pts: 43u16,
                         },
                         Team {
                             name: "Beijing Guoan".to_string(),
                             pts: 27u16,
                         },
                         Team {
                             name: "Guangzhou Evergrand".to_string(),
                             pts: 22u16,
                         },
                         Team {
                             name: "Shandong Luneng".to_string(),
                             pts: 12u16,
                         }];

        data.insert("teams".to_string(), value::to_value(&teams));
        data.insert("engine".to_string(), value::to_value(&"serde_json"));
        data
    }
}

use data::*;

/// the handlers
fn index(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("some/path/hello", data)).set_mut(status::Ok);
    Ok(resp)
}

fn memory(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::new("memory", data)).set_mut(status::Ok);
    Ok(resp)
}

fn temp(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();
    let data = make_data();
    resp.set_mut(Template::with(include_str!("templates/some/path/hello.hbs"), data))
        .set_mut(status::Ok);
    Ok(resp)
}

fn plain(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "It works")))
}

fn main() {
    env_logger::init().unwrap();

    let mut hbse = HandlebarsEngine::new();

    // add a directory source, all files with .hbs suffix will be loaded as template
    hbse.add(Box::new(DirectorySource::new("./examples/templates/", ".hbs")));

    let mem_templates = btreemap! {
        "memory".to_owned() => include_str!("templates/some/path/hello.hbs").to_owned()
    };
    // add a memory based source
    hbse.add(Box::new(MemorySource(mem_templates)));

    // load templates from all registered sources
    if let Err(r) = hbse.reload() {
        panic!("{}", r);
    }

    let mut router = Router::new();
    router.get("/", index)
          .get("/mem", memory)
          .get("/temp", temp)
          .get("/plain", plain);
    let mut chain = Chain::new(router);
    chain.link_after(hbse);
    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<|endoftext|>


<commit_before>extern crate fruently;
use fruently::fluent::Fluent;
use std::thread;
use std::collections::HashMap;
use fruently::forwardable::JsonForwardable;

fn main() {
    let fruently = Fluent::new("0.0.0.0:24224", "test");
    let mut obj: HashMap<String, String> = HashMap::new();
    obj.insert("name".to_string(), "fruently".to_string());
    let child = thread::spawn(move || {
            let _ = fruently.post(&obj);
    });
    child.join().unwrap();
}
<commit_msg>example thread: Request parallel<commit_after>extern crate fruently;
use fruently::fluent::Fluent;
use std::thread;
use std::collections::HashMap;
use fruently::forwardable::JsonForwardable;

fn main() {
    let fruently = Fluent::new("0.0.0.0:24224", "test");
    let mut obj: HashMap<String, String> = HashMap::new();
    obj.insert("threaded".to_string(), "fruently".to_string());
    let threads: Vec<_> = (0..10).map(|_| {
        let obj = obj.clone();
        let fruently = fruently.clone();
        thread::spawn(move || {
            let _ = fruently.post(&obj);
        })
    }).collect();
    let _: Vec<_>  = threads.into_iter().map(|thread| thread.join()).collect();
}
<|endoftext|>


<commit_before>//! A chat server that broadcasts a message to all connections.
//!
//! This is a simple line-based server which accepts WebSocket connections,
//! reads lines from those connections, and broadcasts the lines to all other
//! connected clients.
//!
//! You can test this out by running:
//!
//!     cargo run --example server 127.0.0.1:12345
//!
//! And then in another window run:
//!
//!     cargo run --example client ws://127.0.0.1:12345/
//!
//! You can run the second command in multiple windows and then chat between the
//! two, seeing the messages from the other client as they're received. For all
//! connected clients they'll all join the same room and see everyone else's
//! messages.

use std::env;
use std::io::Error;

use futures::channel::mpsc::UnboundedSender;
use futures::stream::SplitStream;
use futures::{SinkExt, StreamExt};
use log::*;
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
use tokio::net::{TcpListener, TcpStream};
use tungstenite::protocol::Message;

type Tx = UnboundedSender<Message>;

type WsRx = SplitStream<tokio_tungstenite::WebSocketStream<TcpStream>>;

type PeerMap = Arc<Mutex<HashMap<SocketAddr, Tx>>>;

async fn handle_message(addr: SocketAddr, peer_map: PeerMap, ws_rx: WsRx) {
    let mut ws_rx = ws_rx;
    while let Some(msg) = ws_rx.next().await {
        let msg = msg.expect("Failed to get response");
        info!(
            "Received a message from {}: {}",
            addr,
            msg.to_text().unwrap()
        );

        for peer in peer_map.lock().unwrap().iter_mut() {
            let _ = peer.1.unbounded_send(msg.clone());
        }
    }
}

async fn accept_connection(peer_map: PeerMap, raw_stream: TcpStream) {
    let addr = raw_stream
        .peer_addr()
        .expect("connected streams should have a peer address");
    info!("Peer address: {}", addr);

    let ws_stream = tokio_tungstenite::accept_async(raw_stream)
        .await
        .expect("Error during the websocket handshake occurred");

    info!("New WebSocket connection: {}", addr);

    let (mut ws_tx, ws_rx) = ws_stream.split();
    let (msg_tx, mut msg_rx) = futures::channel::mpsc::unbounded();

    //We want to be able to send data to a specific peer, use this tx.
    peer_map.lock().unwrap().insert(addr, msg_tx);

    //Handle incoming messages
    tokio::spawn(handle_message(addr, peer_map.clone(), ws_rx));

    //If msg_rx get's some data, send it on the websocket.
    while let Some(msg) = msg_rx.next().await {
        info!("Sending message to {}", addr);
        ws_tx.send(msg).await.expect("Failed to send request");
    }
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let _ = env_logger::try_init();
    let addr = env::args()
        .nth(1)
        .unwrap_or_else(|| "127.0.0.1:8080".to_string());

    let hm: HashMap<SocketAddr, Tx> = HashMap::new();
    let state = PeerMap::new(Mutex::new(hm));

    // Create the event loop and TCP listener we'll accept connections on.
    let try_socket = TcpListener::bind(&addr).await;
    let mut listener = try_socket.expect("Failed to bind");
    info!("Listening on: {}", addr);

    while let Ok((stream, _)) = listener.accept().await {
        tokio::spawn(accept_connection(state.clone(), stream));
    }

    Ok(())
}
<commit_msg>examples: improve server example<commit_after>//! A chat server that broadcasts a message to all connections.
//!
//! This is a simple line-based server which accepts WebSocket connections,
//! reads lines from those connections, and broadcasts the lines to all other
//! connected clients.
//!
//! You can test this out by running:
//!
//!     cargo run --example server 127.0.0.1:12345
//!
//! And then in another window run:
//!
//!     cargo run --example client ws://127.0.0.1:12345/
//!
//! You can run the second command in multiple windows and then chat between the
//! two, seeing the messages from the other client as they're received. For all
//! connected clients they'll all join the same room and see everyone else's
//! messages.

use std::{
    collections::HashMap,
    env,
    io::Error as IoError,
    net::SocketAddr,
    sync::{Arc, Mutex},
};

use futures::{
    channel::mpsc::{unbounded, UnboundedSender},
    future, pin_mut,
    stream::TryStreamExt,
    StreamExt,
};

use tokio::net::{TcpListener, TcpStream};
use tungstenite::protocol::Message;

type Tx = UnboundedSender<Message>;
type PeerMap = Arc<Mutex<HashMap<SocketAddr, Tx>>>;

async fn handle_connection(peer_map: PeerMap, raw_stream: TcpStream, addr: SocketAddr) {
    println!("Incoming TCP connection from: {}", addr);

    let ws_stream = tokio_tungstenite::accept_async(raw_stream)
        .await
        .expect("Error during the websocket handshake occurred");
    println!("WebSocket connection established: {}", addr);

    // Insert the write part of this peer to the peer map.
    let (tx, rx) = unbounded();
    peer_map.lock().unwrap().insert(addr, tx);

    let (outgoing, incoming) = ws_stream.split();

    let broadcast_incoming = incoming.try_for_each(|msg| {
        println!(
            "Received a message from {}: {}",
            addr,
            msg.to_text().unwrap()
        );
        let peers = peer_map.lock().unwrap();

        // We want to broadcast the message to everyone except ourselves.
        let broadcast_recipients = peers
            .iter()
            .filter(|(peer_addr, _)| peer_addr != &&addr)
            .map(|(_, ws_sink)| ws_sink);

        for recp in broadcast_recipients {
            recp.unbounded_send(msg.clone()).unwrap();
        }

        future::ok(())
    });

    let receive_from_others = rx.map(Ok).forward(outgoing);

    pin_mut!(broadcast_incoming, receive_from_others);
    future::select(broadcast_incoming, receive_from_others).await;

    println!("{} disconnected", &addr);
    peer_map.lock().unwrap().remove(&addr);
}

#[tokio::main]
async fn main() -> Result<(), IoError> {
    let addr = env::args()
        .nth(1)
        .unwrap_or_else(|| "127.0.0.1:8080".to_string());

    let state = PeerMap::new(Mutex::new(HashMap::new()));

    // Create the event loop and TCP listener we'll accept connections on.
    let try_socket = TcpListener::bind(&addr).await;
    let mut listener = try_socket.expect("Failed to bind");
    println!("Listening on: {}", addr);

    // Let's spawn the handling of each connection in a separate task.
    while let Ok((stream, addr)) = listener.accept().await {
        tokio::spawn(handle_connection(state.clone(), stream, addr));
    }

    Ok(())
}
<|endoftext|>


<commit_before>extern crate irc;
extern crate tokio_timer;

use std::default::Default;
use std::time::Duration;
use irc::client::prelude::*;
use irc::error::IrcError;

// NOTE: this example is a conversion of `tweeter.rs` to an asynchronous style with `IrcReactor`.
fn main() {
    let config = Config {
        nickname: Some("mastodon".to_owned()),
        server: Some("irc.fyrechat.net".to_owned()),
        channels: Some(vec!["#irc-crate".to_owned()]),
        ..Default::default()
    };

    // We need to create a reactor first and foremost
    let mut reactor = IrcReactor::new().unwrap();
    // and then create a client via its API.
    let client = reactor.prepare_client_and_connect(&config).unwrap();
    // Then, we identify
    client.identify().unwrap();
    // and clone just as before.
    let send_client = client.clone();

    // Rather than spawn a thread that reads the messages separately, we register a handler with the
    // reactor. just as in the original version, we don't do any real handling and instead just print
    // the messages that are received.
    reactor.register_client_with_handler(client, |_, message| {
        print!("{}", message);
        Ok(())
    });

    // We construct an interval using a wheel timer from tokio_timer. This interval will fire
    // every 10 seconds (and is roughly accurate to the second).
    let send_interval = tokio_timer::wheel()
        .tick_duration(Duration::from_secs(1))
        .num_slots(256)
        .build()
        .interval(Duration::from_secs(10));

    // And then spawn a new future that performs the given action each time it fires.
    reactor.register_future(send_interval.map_err(IrcError::Timer).for_each(move |()| {
        // Anything in here will happen every 10 seconds!
        send_client.send_privmsg("#irc-crate", "TOOT TOOT")
    }));

    // Then, on the main thread, we finally run the reactor which blocks the program indefinitely.
    reactor.run().unwrap();
}
<commit_msg>Rewrapped comments in tooter.rs.<commit_after>extern crate irc;
extern crate tokio_timer;

use std::default::Default;
use std::time::Duration;
use irc::client::prelude::*;
use irc::error::IrcError;

// NOTE: this example is a conversion of `tweeter.rs` to an asynchronous style with `IrcReactor`.
fn main() {
    let config = Config {
        nickname: Some("mastodon".to_owned()),
        server: Some("irc.fyrechat.net".to_owned()),
        channels: Some(vec!["#irc-crate".to_owned()]),
        ..Default::default()
    };

    // We need to create a reactor first and foremost
    let mut reactor = IrcReactor::new().unwrap();
    // and then create a client via its API.
    let client = reactor.prepare_client_and_connect(&config).unwrap();
    // Then, we identify
    client.identify().unwrap();
    // and clone just as before.
    let send_client = client.clone();

    // Rather than spawn a thread that reads the messages separately, we register a handler with the
    // reactor. just as in the original version, we don't do any real handling and instead just
    // print the messages that are received.
    reactor.register_client_with_handler(client, |_, message| {
        print!("{}", message);
        Ok(())
    });

    // We construct an interval using a wheel timer from tokio_timer. This interval will fire every
    // ten seconds (and is roughly accurate to the second).
    let send_interval = tokio_timer::wheel()
        .tick_duration(Duration::from_secs(1))
        .num_slots(256)
        .build()
        .interval(Duration::from_secs(10));

    // And then spawn a new future that performs the given action each time it fires.
    reactor.register_future(send_interval.map_err(IrcError::Timer).for_each(move |()| {
        // Anything in here will happen every 10 seconds!
        send_client.send_privmsg("#irc-crate", "TOOT TOOT")
    }));

    // Then, on the main thread, we finally run the reactor which blocks the program indefinitely.
    reactor.run().unwrap();
}
<|endoftext|>


<commit_before>extern crate init = "gl-init-rs";
extern crate libc;
extern crate gl;

fn main() {
    use std::default::Default;

    let window = init::Window::new(None, "Hello world!", &Default::default()).unwrap();

    window.make_current();

    gl::load_with(|symbol| window.get_proc_address(symbol) as *const libc::c_void);

    gl::ClearColor(0.0, 1.0, 0.0, 1.0);

    while !window.should_close() {
        window.wait_events();

        gl::Clear(gl::COLOR_BUFFER_BIT);

        window.swap_buffers();
    }
}
<commit_msg>Example now displays windows events<commit_after>extern crate init = "gl-init-rs";
extern crate libc;
extern crate gl;

fn main() {
    use std::default::Default;

    let window = init::Window::new(None, "Hello world!", &Default::default()).unwrap();

    window.make_current();

    gl::load_with(|symbol| window.get_proc_address(symbol) as *const libc::c_void);

    gl::ClearColor(0.0, 1.0, 0.0, 1.0);

    while !window.should_close() {
        println!("{}", window.wait_events());

        gl::Clear(gl::COLOR_BUFFER_BIT);

        window.swap_buffers();
    }
}
<|endoftext|>


<commit_before>extern crate polydraw;
extern crate time;

mod common;

use polydraw::os::win;
use polydraw::os::wgl;
use polydraw::os::gl;

use common::{rand_u8, create_data, update_data};

fn main() {
   let width: usize = 1280;
   let height: usize = 720;

   let window = win::Window::create(width, height, "Win Min", "WinMinClass");
   window.show_normal();

   let dc = window.dc();
   println!("DC: {:?}", dc);

   match wgl::init_pixel_format(dc) {
      Ok(_) => {},
      Err(e) => {
         panic!(e.description);
      }
   };

   let context = match wgl::Context::create(dc) {
      Ok(context) => context,
      Err(e) => {
         panic!(e.description);
      }
   };

   println!("RC: {:?}", context.rc);

   gl::load(wgl::Loader::new());

   let mut counter: u64 = 0;
   let mut data = create_data(width, height);

   let texture = gl::Texture::new(width, height);

   println!("GL texture ................ : {:?}", texture.name);

   let framebuffer = gl::Framebuffer::new(&texture);

   println!("GL framebuffer ............ : {:?}", framebuffer.name);

   let start_time = time::precise_time_ns();

   let mut exit = false;
   let mut seed = 0;

   loop {
      loop {
         let message = match win::Message::peek() {
            Some(message) => message,
            None => break
         };

         if message.is_quit() {
            exit = true;
         }

         message.translate();
         message.dispatch();
      }

      if exit {
         break;
      }

      counter += 1;
      seed = counter;

      update_data(&mut data, width, height, &mut seed);

      texture.update(width, height, &data);

      framebuffer.blit(width, height);

      gl::flush();

      wgl::swap_buffers(dc);
   }

   let end_time = time::precise_time_ns();

   println!("Time ns ................... : {:?}", end_time - start_time);
   println!("Cycles .................... : {:?}", counter);
   println!("FPS ....................... : {:?}", counter * 1000000000 / (end_time - start_time) );
}
<commit_msg>Changing the title of the Windows example<commit_after>extern crate polydraw;
extern crate time;

mod common;

use polydraw::os::win;
use polydraw::os::wgl;
use polydraw::os::gl;

use common::{rand_u8, create_data, update_data};

fn main() {
   let width: usize = 1280;
   let height: usize = 720;

   let window = win::Window::create(width, height, "PolyDraw", "WinMinClass");
   window.show_normal();

   let dc = window.dc();
   println!("DC: {:?}", dc);

   match wgl::init_pixel_format(dc) {
      Ok(_) => {},
      Err(e) => {
         panic!(e.description);
      }
   };

   let context = match wgl::Context::create(dc) {
      Ok(context) => context,
      Err(e) => {
         panic!(e.description);
      }
   };

   println!("RC: {:?}", context.rc);

   gl::load(wgl::Loader::new());

   let mut counter: u64 = 0;
   let mut data = create_data(width, height);

   let texture = gl::Texture::new(width, height);

   println!("GL texture ................ : {:?}", texture.name);

   let framebuffer = gl::Framebuffer::new(&texture);

   println!("GL framebuffer ............ : {:?}", framebuffer.name);

   let start_time = time::precise_time_ns();

   let mut exit = false;
   let mut seed = 0;

   loop {
      loop {
         let message = match win::Message::peek() {
            Some(message) => message,
            None => break
         };

         if message.is_quit() {
            exit = true;
         }

         message.translate();
         message.dispatch();
      }

      if exit {
         break;
      }

      counter += 1;
      seed = counter;

      update_data(&mut data, width, height, &mut seed);

      texture.update(width, height, &data);

      framebuffer.blit(width, height);

      gl::flush();

      wgl::swap_buffers(dc);
   }

   let end_time = time::precise_time_ns();

   println!("Time ns ................... : {:?}", end_time - start_time);
   println!("Cycles .................... : {:?}", counter);
   println!("FPS ....................... : {:?}", counter * 1000000000 / (end_time - start_time) );
}
<|endoftext|>


<commit_before>// test1.rs
// This is a test for the following sections:
// - Variables
// - Functions

// Mary is buying apples. One apple usually costs 2 dollars, but if you buy
// more than 40 at once, each apple only costs 1! Write a function that calculates
// the price of an order of apples given the order amount. No hints this time!

// Put your function here!
// fn ..... {

// Don't modify this function!
#[test]
fn verify_test() {
    let price1 = calculate_price(55);
    let price2 = calculate_price(40);

    assert_eq!(price1, 55);
    assert_eq!(price2, 80);
}
<commit_msg>Auto merge of #192 - petemcfarlane:patch-2, r=komaeda<commit_after>// test1.rs
// This is a test for the following sections:
// - Variables
// - Functions

// Mary is buying apples. One apple usually costs 2 dollars, but if you buy
// more than 40 at once, each apple only costs 1! Write a function that calculates
// the price of an order of apples given the order amount. No hints this time!

// Put your function here!
// fn ..... {

// Don't modify this function!
#[test]
fn verify_test() {
    let price1 = calculate_price(55);
    let price2 = calculate_price(40);

    assert_eq!(55, price1);
    assert_eq!(80, price2);
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Active_object
#![feature(associated_types, default_type_params)]
extern crate time;

use std::num::{Float, FloatMath};
use std::f64::consts::PI;
use std::io::timer::Timer;
use std::sync::{Arc, Mutex};
use std::time::duration::Duration;
use std::thread::Thread;
use std::sync::mpsc::{channel, Sender, SendError};
use std::ops::Mul;

// Rust supports both shared-memory and actor models of concurrency, and the Integrator utilizes
// both.  We use a Sender (actor model) to send the Integrator new functions, while we use a Mutex
// (shared-memory concurrency) to hold the result of the integration.
//
// Note that these are not the only options here--there are many, many ways you can deal with
// concurrent access.  But when in doubt, a plain old Mutex is often a good bet.  For example, this
// might look like a good situation for a RwLock--after all, there's no reason for a read in the
// main task to block writes.  Unfortunately, unless you have significantly more reads than
// writes (which is certainly not the case here), a Mutex will usually outperform a RwLock.
pub struct Integrator<S, T> {
    input: Sender<|i64|: Send -> S>,
    output: Arc<Mutex<T>>,
}

// In Rust, time durations are strongly typed.  This is usually exactly what you want, but for a
// problem like this--where the integrated value has unusual (unspecified?) units--it can actually
// be a bit tricky.  Right now, Durations can only be multiplied or divided by i32s, so in order to
// be able to actually do math with them we say that the type parameter S (the result of the
// function being integrated) must yield T (the type of the integrated value) when multiplied by
// f64.  We could possibly replace f64 with a generic as well, but it would make things a bit more
// complex.
impl<S: Mul<f64, Output=T> + Float,
     T: Clone + Send + Float> Integrator<S, T> {
    pub fn new(frequency: Duration) -> Integrator<S, T> {
        // We create a pipe allowing functions to be sent from tx (the sending end) to input (the
        // receiving end).  In order to change the function we are integrating from the task in
        // which the Integrator lives, we simply send the function through tx.
        let (tx, input) = channel();
        // The easiest way to do shared-memory concurrency in Rust is to use atomic reference
        // counting, or Arc, around a synchronized type (like Mutex<T>).  Arc gives you a guarantee
        // that memory will not be freed as long as there is at least one reference to it.
        // It is similar to C++'s shared_ptr, but it is guaranteed to be safe and is never
        // incremented unless explicitly cloned (by default, it is moved).
        let s: Arc<Mutex<T>> = Arc::new(Mutex::new(Float::zero()));
        let integrator = Integrator {
            input: tx,
            // Here is the aforementioned clone.  We have to do it before s enters the closure,
            // because once that happens it is moved into the closure (and later, the new task) and
            // becomes inaccessible to the outside world.
            output: s.clone(),
        };
        Thread::spawn(move || -> () {
            // There is a reasonable argument for failure on failure to initialize the Timer, but
            // it's essentially certain that if we return from the spawn this early main will
            // detect that something is amiss.
            let mut timer = match Timer::new() {
                Ok(timer) => timer,
                Err(_) => return
            };
            // The frequency is how often we want to "tick" as we update our integrated total.  In
            // Rust, timers can yield Receivers that are periodically notified with an empty
            // message (where the period is the frequency).  This is useful because it lets us wait
            // on either a tick or another type of message (in this case, a request to change the
            // function we are integrating).
            let periodic = timer.periodic(frequency);
            let frequency_ms = frequency.num_milliseconds();
            let mut t = 0;
            let mut k = |_| Float::zero();
            let mut k_0: S = Float::zero();
            loop {
                // Here's the selection we talked about above.  Note that we are careful to call
                // the *non*-failing function, recv(), here.  The reason we do this is because
                // recv() will return Err when the sending end of a channel is dropped.  While
                // this is unlikely to happen for the timer (so again, you could argue for failure
                // there), it's normal behavior for the sending end of input to be dropped, since
                // it just happens when the Integrator falls out of scope.  So we handle it cleanly
                // and break out of the loop, rather than failing.
                select! {
                    res = periodic.recv() => match res {
                        Ok(_) => {
                            t += frequency_ms;
                            let k_1: S = k(t);
                            // Rust Mutexes are a bit different from Mutexes in many other
                            // languages, in that the protected data is actually encapsulated by
                            // the Mutex.  The reason for this is that Rust is actually capable of
                            // enforcing (via its borrow checker) the invariant that the contents
                            // of a Mutex may only be read when you have acquired its lock.  This
                            // is enforced by way of a MutexGuard, the return value of lock(),
                            // which implements some special traits (Deref and DerefMut) that allow
                            // access to the inner element "through" the guard.  The element so
                            // acquired has a lifetime bounded by that of the MutexGuard, the
                            // MutexGuard can only be acquired by taking a lock, and the only way
                            // to release the lock is by letting the MutexGuard fall out of scope,
                            // so it's impossible to access the data incorrectly.  There are some
                            // additional subtleties around the actual implementation, but that's
                            // the basic idea.
                            let mut s = s.lock().unwrap();
                            *s = *s + (k_1 + k_0) * (frequency_ms as f64 / 2.);
                            k_0 = k_1;
                        }
                        Err(_) => break,
                    },
                    res = input.recv() => match res {
                        Ok(k_new) => k = k_new,
                        Err(_) => break,
                    }
                }
            }
        }).detach();
        integrator
    }

    pub fn input(&self, k: |i64|: Send -> S) -> Result<(), SendError<|i64|:Send -> S>> {
        // The meat of the work is done in the other thread, so to set the input we just send along
        // the Sender we set earlier...
        self.input.send(k)
    }

    pub fn output(&self) -> T {
        // ...and to read the input, we simply acquire a lock on the output Mutex and return a
        // clone.  Why do we have to clone it?  Because, as mentioned above, Rust won't let us
        // retain access to the interior of the Mutex unless we have possession of its lock.  There
        // are ways and circumstances in which one can avoid this (e.g. by using atomic types) but
        // clone() is a perfectly reasonable solution as well, and a lot easier to reason about :)
        self.output.lock().unwrap().clone()
    }
}

// This function is fairly straightforward.  We create the integrator, set its input function k(t)
// to 2pi * f * t, and then wait as described in the Rosetta stone problem.
#[cfg(not(test))]
fn integrate() -> f64 {
    let object = Integrator::new(Duration::milliseconds(10));
    let mut timer = Timer::new().unwrap();
    object.input(|t| {
        let f = 1. / Duration::seconds(2).num_milliseconds() as f64;
        (2. * PI * f * t as f64).sin()
    }).ok().expect("Failed to set input");
    timer.sleep(Duration::seconds(2));
    object.input(|_| 0.).ok().expect("Failed to set input");
    timer.sleep(Duration::seconds(1) / 2);
    object.output()
}

#[cfg(not(test))]
fn main() {
    println!("{}", integrate());
}

#[test]
#[ignore] // Will fail on a heavily loaded machine
fn solution() {
    // We should just be able to call integrate, but can't represent the closure properly due to
    // rust-lang/rust issue #17060 if we make frequency or period a variable.
    // FIXME(pythonesque): When unboxed closures are fixed, fix integrate() to take two arguments.
    let object = Integrator::new(Duration::milliseconds(10));
    let mut timer = Timer::new().unwrap();
    object.input(|t| {
        let f = 1. / (Duration::seconds(2) / 10).num_milliseconds() as f64;
        (2. * PI * f * t as f64).sin()
    }).ok().expect("Failed to set input");
    timer.sleep(Duration::seconds(2) / 10);
    object.input(|_| 0.).ok().expect("Failed to set input");
    timer.sleep(Duration::seconds(1) / 10);
    assert_eq!(object.output() as i64, 0)
}
<commit_msg>Fixed active_object.rs<commit_after>// Implements http://rosettacode.org/wiki/Active_object
extern crate time;

use std::num::Float;
use std::f64::consts::PI;
use std::io::timer::Timer;
use std::sync::{Arc, Mutex};
use std::time::duration::Duration;
use std::thread::Thread;
use std::sync::mpsc::{channel, Sender, SendError};
use std::ops::Mul;

// Rust supports both shared-memory and actor models of concurrency, and the Integrator utilizes
// both.  We use a Sender (actor model) to send the Integrator new functions, while we use a Mutex
// (shared-memory concurrency) to hold the result of the integration.
//
// Note that these are not the only options here--there are many, many ways you can deal with
// concurrent access.  But when in doubt, a plain old Mutex is often a good bet.  For example, this
// might look like a good situation for a RwLock--after all, there's no reason for a read in the
// main task to block writes.  Unfortunately, unless you have significantly more reads than
// writes (which is certainly not the case here), a Mutex will usually outperform a RwLock.
pub struct Integrator<S: 'static, T> {
    input: Sender<Box<Fn(i64) -> S + Send>>,
    output: Arc<Mutex<T>>,
}

// In Rust, time durations are strongly typed.  This is usually exactly what you want, but for a
// problem like this--where the integrated value has unusual (unspecified?) units--it can actually
// be a bit tricky.  Right now, Durations can only be multiplied or divided by i32s, so in order to
// be able to actually do math with them we say that the type parameter S (the result of the
// function being integrated) must yield T (the type of the integrated value) when multiplied by
// f64.  We could possibly replace f64 with a generic as well, but it would make things a bit more
// complex.
impl<S: Mul<f64, Output=T> + Float,
     T: Clone + Send + Float> Integrator<S, T> {
    pub fn new(frequency: Duration) -> Integrator<S, T> {
        // We create a pipe allowing functions to be sent from tx (the sending end) to input (the
        // receiving end).  In order to change the function we are integrating from the task in
        // which the Integrator lives, we simply send the function through tx.
        let (tx, input) = channel();
        // The easiest way to do shared-memory concurrency in Rust is to use atomic reference
        // counting, or Arc, around a synchronized type (like Mutex<T>).  Arc gives you a guarantee
        // that memory will not be freed as long as there is at least one reference to it.
        // It is similar to C++'s shared_ptr, but it is guaranteed to be safe and is never
        // incremented unless explicitly cloned (by default, it is moved).
        let s: Arc<Mutex<T>> = Arc::new(Mutex::new(Float::zero()));
        let integrator = Integrator {
            input: tx,
            // Here is the aforementioned clone.  We have to do it before s enters the closure,
            // because once that happens it is moved into the closure (and later, the new task) and
            // becomes inaccessible to the outside world.
            output: s.clone(),
        };
        Thread::spawn(move || -> () {
            // There is a reasonable argument for failure on failure to initialize the Timer, but
            // it's essentially certain that if we return from the spawn this early main will
            // detect that something is amiss.
            let mut timer = match Timer::new() {
                Ok(timer) => timer,
                Err(_) => return
            };
            // The frequency is how often we want to "tick" as we update our integrated total.  In
            // Rust, timers can yield Receivers that are periodically notified with an empty
            // message (where the period is the frequency).  This is useful because it lets us wait
            // on either a tick or another type of message (in this case, a request to change the
            // function we are integrating).
            let periodic = timer.periodic(frequency);
            let frequency_ms = frequency.num_milliseconds();
            let mut t = 0;
            let mut k: Box<Fn(i64) -> S + Send> = Box::new(|&: _| Float::zero());
            let mut k_0: S = Float::zero();
            loop {
                // Here's the selection we talked about above.  Note that we are careful to call
                // the *non*-failing function, recv(), here.  The reason we do this is because
                // recv() will return Err when the sending end of a channel is dropped.  While
                // this is unlikely to happen for the timer (so again, you could argue for failure
                // there), it's normal behavior for the sending end of input to be dropped, since
                // it just happens when the Integrator falls out of scope.  So we handle it cleanly
                // and break out of the loop, rather than failing.
                select! {
                    res = periodic.recv() => match res {
                        Ok(_) => {
                            t += frequency_ms;
                            let k_1: S = k(t);
                            // Rust Mutexes are a bit different from Mutexes in many other
                            // languages, in that the protected data is actually encapsulated by
                            // the Mutex.  The reason for this is that Rust is actually capable of
                            // enforcing (via its borrow checker) the invariant that the contents
                            // of a Mutex may only be read when you have acquired its lock.  This
                            // is enforced by way of a MutexGuard, the return value of lock(),
                            // which implements some special traits (Deref and DerefMut) that allow
                            // access to the inner element "through" the guard.  The element so
                            // acquired has a lifetime bounded by that of the MutexGuard, the
                            // MutexGuard can only be acquired by taking a lock, and the only way
                            // to release the lock is by letting the MutexGuard fall out of scope,
                            // so it's impossible to access the data incorrectly.  There are some
                            // additional subtleties around the actual implementation, but that's
                            // the basic idea.
                            let mut s = s.lock().unwrap();
                            *s = *s + (k_1 + k_0) * (frequency_ms as f64 / 2.);
                            k_0 = k_1;
                        }
                        Err(_) => break,
                    },
                    res = input.recv() => match res {
                        Ok(k_new) => k = k_new,
                        Err(_) => break,
                    }
                }
            }
        });
        integrator
    }

    pub fn input(&self, k: Box<Fn(i64) -> S + Send>) -> Result<(), SendError< Box<Fn(i64) -> S + Send>>> {
        // The meat of the work is done in the other thread, so to set the input we just send along
        // the Sender we set earlier...
        self.input.send(k)
    }

    pub fn output(&self) -> T {
        // ...and to read the input, we simply acquire a lock on the output Mutex and return a
        // clone.  Why do we have to clone it?  Because, as mentioned above, Rust won't let us
        // retain access to the interior of the Mutex unless we have possession of its lock.  There
        // are ways and circumstances in which one can avoid this (e.g. by using atomic types) but
        // clone() is a perfectly reasonable solution as well, and a lot easier to reason about :)
        self.output.lock().unwrap().clone()
    }
}

// This function is fairly straightforward.  We create the integrator, set its input function k(t)
// to 2pi * f * t, and then wait as described in the Rosetta stone problem.
#[cfg(not(test))]
fn integrate() -> f64 {
    let object = Integrator::new(Duration::milliseconds(10));
    let mut timer = Timer::new().unwrap();
    object.input(Box::new(|&: t: i64| {
        let f = 1. / Duration::seconds(2).num_milliseconds() as f64;
        (2. * PI * f * t as f64).sin()
    })).ok().expect("Failed to set input");
    timer.sleep(Duration::seconds(2));
    object.input(Box::new(|&:_| 0.)).ok().expect("Failed to set input");
    timer.sleep(Duration::seconds(1) / 2);
    object.output()
}

#[cfg(not(test))]
fn main() {
    println!("{}", integrate());
}

#[test]
#[ignore] // Will fail on a heavily loaded machine
fn solution() {
    // We should just be able to call integrate, but can't represent the closure properly due to
    // rust-lang/rust issue #17060 if we make frequency or period a variable.
    // FIXME(pythonesque): When unboxed closures are fixed, fix integrate() to take two arguments.
    let object = Integrator::new(Duration::milliseconds(10));
    let mut timer = Timer::new().unwrap();
    object.input(Box::new(|&: t: i64| {
        let f = 1. / (Duration::seconds(2) / 10).num_milliseconds() as f64;
        (2. * PI * f * t as f64).sin()
    })).ok().expect("Failed to set input");
    timer.sleep(Duration::seconds(2) / 10);
    object.input(Box::new(|&: _| 0.)).ok().expect("Failed to set input");
    timer.sleep(Duration::seconds(1) / 10);
    assert_eq!(object.output() as i64, 0)
}
<|endoftext|>