<commit_before>use serial_support::messages::{SerialResponse, SerialRequest};

error_chain! {

  foreign_links {
    Fmt(::std::fmt::Error);
    Io(::std::io::Error) #[cfg(unix)];
    Serialport(::serialport::Error) #[cfg(unix)];
    Utf8(::std::string::FromUtf8Error);
    Json(::serde_json::error::Error);
    SendResponse(::std::sync::mpsc::SendError<SerialResponse>);
    Base64(::base64::DecodeError);
    SendRequest(::std::sync::mpsc::SendError<(String,SerialRequest)>);
    SendWsMessage(::websocket::result::WebSocketError);
  }

  errors{
    UnknownRequest{
      description("Unknown request")
      display("Unknown request,")
    }
    OpenPortNotFound(port:String){
      description("Open serial port not found")
      display("Serial port '{}' not found, try opening it first", port)
    }
    SubscriptionNotFound(sub_id:String){
      description("Subscription not found")
      display("Subscription for id '{}' not found", sub_id)
    }
    AlreadyWriteLocked(port:String){
      description("Port already write locked")
      display("Open serial port '{}' is already write locked", port)
    }
    NeedWriteLock(port:String){
      description("Need write lock")
      display("Write to open port '{}' failed, you need to write lock first", port)
    }
    PortReadError(port:String){
      description("Error reading serial port")
      display("Read from port '{}' failed", port)
    }
    PortEOFError(port:String){
      description("Encountered EOF reading serial port")
      display("Encountered EOF reading serial port {}", port)
    }
    PortWriteError(port:String){
      description("Error writing serial port")
      display("Writing to port '{}' failed", port)
    }
    SubscriberSendError(sub_id:String){
      description("Error sending message to subscriber")
      display("Send to subscriber '{}' failed", sub_id)
    }
  }
}

pub fn to_serial_response_error(err: Error) -> SerialResponse {
  SerialResponse::Error {
    description: err.description().to_string(),
    display: format!("{}", err),
  }
}
<commit_msg>Improve error message for already write locked<commit_after>use serial_support::messages::{SerialResponse, SerialRequest};

error_chain! {

  foreign_links {
    Fmt(::std::fmt::Error);
    Io(::std::io::Error) #[cfg(unix)];
    Serialport(::serialport::Error) #[cfg(unix)];
    Utf8(::std::string::FromUtf8Error);
    Json(::serde_json::error::Error);
    SendResponse(::std::sync::mpsc::SendError<SerialResponse>);
    Base64(::base64::DecodeError);
    SendRequest(::std::sync::mpsc::SendError<(String,SerialRequest)>);
    SendWsMessage(::websocket::result::WebSocketError);
  }

  errors{
    UnknownRequest{
      description("Unknown request")
      display("Unknown request,")
    }
    OpenPortNotFound(port:String){
      description("Open serial port not found")
      display("Serial port '{}' not found, try opening it first", port)
    }
    SubscriptionNotFound(sub_id:String){
      description("Subscription not found")
      display("Subscription for id '{}' not found", sub_id)
    }
    AlreadyWriteLocked(port:String){
      description("Port already write locked by another client")
      display("Open serial port '{}' is already write locked by another client", port)
    }
    NeedWriteLock(port:String){
      description("Need write lock")
      display("Write to open port '{}' failed, you need to write lock first", port)
    }
    PortReadError(port:String){
      description("Error reading serial port")
      display("Read from port '{}' failed", port)
    }
    PortEOFError(port:String){
      description("Encountered EOF reading serial port")
      display("Encountered EOF reading serial port {}", port)
    }
    PortWriteError(port:String){
      description("Error writing serial port")
      display("Writing to port '{}' failed", port)
    }
    SubscriberSendError(sub_id:String){
      description("Error sending message to subscriber")
      display("Send to subscriber '{}' failed", sub_id)
    }
  }
}

pub fn to_serial_response_error(err: Error) -> SerialResponse {
  SerialResponse::Error {
    description: err.description().to_string(),
    display: format!("{}", err),
  }
}
<|endoftext|>


<commit_before>use serial_support::messages::SerialResponse;

error_chain! {

  foreign_links {
    Fmt(::std::fmt::Error);
    Io(::std::io::Error) #[cfg(unix)];
    Serialport(::serialport::Error) #[cfg(unix)];
    Utf8(::std::string::FromUtf8Error);
    Json(::serde_json::error::Error);
    SendResponse(::std::sync::mpsc::SendError<SerialResponse>);
    Base64(::base64::DecodeError);
  }

  errors{
    UnknownRequest{
      description("Unknown request")
      display("Unknown request,")
    }
    OpenPortNotFound(port:String){
      description("Open serial port not found")
      display("Serial port '{}' not found, try opening it first", port)
    }
    SubscriptionNotFound(sub_id:String){
      description("Subscription not found")
      display("Subscription for id '{}' not found", sub_id)
    }
    AlreadyWriteLocked(port:String){
      description("Port already write locked")
      display("Open serial port '{}' is already write locked", port)
    }
    NeedWriteLock(port:String){
      description("Need write lock")
      display("Write to open port '{}' failed, you need to write lock first", port)
    }
    PortReadError(port:String){
      description("Error reading serial port")
      display("Write to port '{}' failed", port)
    }
    PortWriteError(port:String){
      description("Error writing serial port")
      display("Read from port '{}' failed", port)
    }
    SubscriberSendError(sub_id:String){
      description("Error sending message to subscriber")
      display("Send to subscriber '{}' failed", sub_id)
    }
  }
}

pub fn to_serial_response_error(err: Error) -> SerialResponse {
  SerialResponse::Error {
    description: err.description().to_string(),
    display: format!("{}", err),
  }
}
<commit_msg>Added more errors for Websocket send error, SerialRequest send error<commit_after>use serial_support::messages::{SerialResponse, SerialRequest};

error_chain! {

  foreign_links {
    Fmt(::std::fmt::Error);
    Io(::std::io::Error) #[cfg(unix)];
    Serialport(::serialport::Error) #[cfg(unix)];
    Utf8(::std::string::FromUtf8Error);
    Json(::serde_json::error::Error);
    SendResponse(::std::sync::mpsc::SendError<SerialResponse>);
    Base64(::base64::DecodeError);
    SendRequest(::std::sync::mpsc::SendError<SerialRequest>);
    SendWsMessage(::websocket::result::WebSocketError);
  }

  errors{
    UnknownRequest{
      description("Unknown request")
      display("Unknown request,")
    }
    OpenPortNotFound(port:String){
      description("Open serial port not found")
      display("Serial port '{}' not found, try opening it first", port)
    }
    SubscriptionNotFound(sub_id:String){
      description("Subscription not found")
      display("Subscription for id '{}' not found", sub_id)
    }
    AlreadyWriteLocked(port:String){
      description("Port already write locked")
      display("Open serial port '{}' is already write locked", port)
    }
    NeedWriteLock(port:String){
      description("Need write lock")
      display("Write to open port '{}' failed, you need to write lock first", port)
    }
    PortReadError(port:String){
      description("Error reading serial port")
      display("Write to port '{}' failed", port)
    }
    PortWriteError(port:String){
      description("Error writing serial port")
      display("Read from port '{}' failed", port)
    }
    SubscriberSendError(sub_id:String){
      description("Error sending message to subscriber")
      display("Send to subscriber '{}' failed", sub_id)
    }
  }
}

pub fn to_serial_response_error(err: Error) -> SerialResponse {
  SerialResponse::Error {
    description: err.description().to_string(),
    display: format!("{}", err),
  }
}
<|endoftext|>


<commit_before>//! Stack slots.
//!
//! The `StackSlotData` struct keeps track of a single stack slot in a function.
//!

use entity_map::{EntityMap, PrimaryEntityData, Keys};
use ir::{Type, StackSlot};
use std::fmt;
use std::ops::Index;
use std::str::FromStr;

/// The kind of a stack slot.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StackSlotKind {
    /// A spill slot. This is a stack slot created by the register allocator.
    SpillSlot,

    /// A local variable. This is a chunk of local stack memory for use by the `stack_load` and
    /// `stack_store` instructions.
    Local,

    /// An incoming function argument.
    ///
    /// If the current function has more arguments than fits in registers, the remaining arguments
    /// are passed on the stack by the caller. These incoming arguments are represented as SSA
    /// values assigned to incoming stack slots.
    IncomingArg,

    /// An outgoing function argument.
    ///
    /// When preparing to call a function whose arguments don't fit in registers, outgoing argument
    /// stack slots are used to represent individual arguments in the outgoing call frame. These
    /// stack slots are only valid while setting up a call.
    OutgoingArg,
}

impl FromStr for StackSlotKind {
    type Err = ();

    fn from_str(s: &str) -> Result<StackSlotKind, ()> {
        use self::StackSlotKind::*;
        match s {
            "local" => Ok(Local),
            "spill_slot" => Ok(SpillSlot),
            "incoming_arg" => Ok(IncomingArg),
            "outgoing_arg" => Ok(OutgoingArg),
            _ => Err(()),
        }
    }
}

impl fmt::Display for StackSlotKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::StackSlotKind::*;
        f.write_str(match *self {
                        Local => "local",
                        SpillSlot => "spill_slot",
                        IncomingArg => "incoming_arg",
                        OutgoingArg => "outgoing_arg",
                    })
    }
}

/// Contents of a stack slot.
#[derive(Clone, Debug)]
pub struct StackSlotData {
    /// The kind of stack slot.
    pub kind: StackSlotKind,

    /// Size of stack slot in bytes.
    pub size: u32,

    /// Offset of stack slot relative to the stack pointer in the caller.
    ///
    /// On Intel ISAs, the base address is the stack pointer *before* the return address was
    /// pushed. On RISC ISAs, the base address is the value of the stack pointer on entry to the
    /// function.
    ///
    /// For `OutgoingArg` stack slots, the offset is relative to the current function's stack
    /// pointer immediately before the call.
    pub offset: i32,
}

impl StackSlotData {
    /// Create a stack slot with the specified byte size.
    pub fn new(kind: StackSlotKind, size: u32) -> StackSlotData {
        StackSlotData {
            kind,
            size,
            offset: 0,
        }
    }
}

impl fmt::Display for StackSlotData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.kind, self.size)?;
        if self.offset != 0 {
            write!(f, ", offset {}", self.offset)?;
        }
        Ok(())
    }
}

impl PrimaryEntityData for StackSlotData {}

/// Stack frame manager.
///
/// Keep track of all the stack slots used by a function.
#[derive(Clone, Debug)]
pub struct StackSlots {
    /// All allocated stack slots.
    slots: EntityMap<StackSlot, StackSlotData>,

    /// All the outgoing stack slots, ordered by offset.
    outgoing: Vec<StackSlot>,
}

/// Stack slot manager functions that behave mostly like an entity map.
impl StackSlots {
    /// Create an empty stack slot manager.
    pub fn new() -> StackSlots {
        StackSlots {
            slots: EntityMap::new(),
            outgoing: Vec::new(),
        }
    }

    /// Clear out everything.
    pub fn clear(&mut self) {
        self.slots.clear();
        self.outgoing.clear();
    }

    /// Allocate a new stack slot.
    ///
    /// This function should be primarily used by the text format parser. There are more convenient
    /// functions for creating specific kinds of stack slots below.
    pub fn push(&mut self, data: StackSlotData) -> StackSlot {
        self.slots.push(data)
    }

    /// Check if `ss` is a valid stack slot reference.
    pub fn is_valid(&self, ss: StackSlot) -> bool {
        self.slots.is_valid(ss)
    }

    /// Get an iterator over all the stack slot keys.
    pub fn keys(&self) -> Keys<StackSlot> {
        self.slots.keys()
    }

    /// Get a reference to the next stack slot that would be created by `push()`.
    ///
    /// This should just be used by the parser.
    pub fn next_key(&self) -> StackSlot {
        self.slots.next_key()
    }
}

/// Higher-level stack frame manipulation functions.
impl StackSlots {
    /// Create a new spill slot for spilling values of type `ty`.
    pub fn make_spill_slot(&mut self, ty: Type) -> StackSlot {
        self.push(StackSlotData::new(StackSlotKind::SpillSlot, ty.bytes()))
    }

    /// Create a stack slot representing an incoming function argument.
    pub fn make_incoming_arg(&mut self, ty: Type, offset: i32) -> StackSlot {
        let mut data = StackSlotData::new(StackSlotKind::IncomingArg, ty.bytes());
        assert!(offset <= i32::max_value() - data.size as i32);
        data.offset = offset;
        self.push(data)
    }

    /// Get a stack slot representing an outgoing argument.
    ///
    /// This may create a new stack slot, or reuse an existing outgoing stack slot with the
    /// requested offset and size.
    ///
    /// The requested offset is relative to this function's stack pointer immediately before making
    /// the call.
    pub fn get_outgoing_arg(&mut self, ty: Type, offset: i32) -> StackSlot {
        let size = ty.bytes();

        // Look for an existing outgoing stack slot with the same offset and size.
        let inspos = match self.outgoing
                  .binary_search_by_key(&(offset, size),
                                        |&ss| (self[ss].offset, self[ss].size)) {
            Ok(idx) => return self.outgoing[idx],
            Err(idx) => idx,
        };

        // No existing slot found. Make one and insert it into `outgoing`.
        let mut data = StackSlotData::new(StackSlotKind::OutgoingArg, size);
        assert!(offset <= i32::max_value() - size as i32);
        data.offset = offset;
        let ss = self.slots.push(data);
        self.outgoing.insert(inspos, ss);
        ss
    }
}

impl Index<StackSlot> for StackSlots {
    type Output = StackSlotData;

    fn index(&self, ss: StackSlot) -> &StackSlotData {
        &self.slots[ss]
    }
}

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

    #[test]
    fn stack_slot() {
        let mut func = Function::new();

        let ss0 = func.stack_slots
            .push(StackSlotData::new(StackSlotKind::IncomingArg, 4));
        let ss1 = func.stack_slots
            .push(StackSlotData::new(StackSlotKind::SpillSlot, 8));
        assert_eq!(ss0.to_string(), "ss0");
        assert_eq!(ss1.to_string(), "ss1");

        assert_eq!(func.stack_slots[ss0].size, 4);
        assert_eq!(func.stack_slots[ss1].size, 8);

        assert_eq!(func.stack_slots[ss0].to_string(), "incoming_arg 4");
        assert_eq!(func.stack_slots[ss1].to_string(), "spill_slot 8");
    }

    #[test]
    fn outgoing() {
        let mut sss = StackSlots::new();

        let ss0 = sss.get_outgoing_arg(types::I32, 8);
        let ss1 = sss.get_outgoing_arg(types::I32, 4);
        let ss2 = sss.get_outgoing_arg(types::I64, 8);

        assert_eq!(sss[ss0].offset, 8);
        assert_eq!(sss[ss0].size, 4);

        assert_eq!(sss[ss1].offset, 4);
        assert_eq!(sss[ss1].size, 4);

        assert_eq!(sss[ss2].offset, 8);
        assert_eq!(sss[ss2].size, 8);

        assert_eq!(sss.get_outgoing_arg(types::I32, 8), ss0);
        assert_eq!(sss.get_outgoing_arg(types::I32, 4), ss1);
        assert_eq!(sss.get_outgoing_arg(types::I64, 8), ss2);
    }
}
<commit_msg>Compute the stack frame layout.<commit_after>//! Stack slots.
//!
//! The `StackSlotData` struct keeps track of a single stack slot in a function.
//!

use entity_map::{EntityMap, PrimaryEntityData, Keys};
use ir::{Type, StackSlot};
use std::cmp::{min, max};
use std::fmt;
use std::ops::Index;
use std::str::FromStr;

/// The size of an object on the stack, or the size of a stack frame.
///
/// We don't use `usize` to represent object sizes on the target platform because Cretonne supports
/// cross-compilation, and `usize` is a type that depends on the host platform, not the target
/// platform.
type StackSize = u32;

/// A stack offset.
///
/// The location of a stack offset relative to a stack pointer or frame pointer.
type StackOffset = i32;

/// The kind of a stack slot.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StackSlotKind {
    /// A spill slot. This is a stack slot created by the register allocator.
    SpillSlot,

    /// A local variable. This is a chunk of local stack memory for use by the `stack_load` and
    /// `stack_store` instructions.
    Local,

    /// An incoming function argument.
    ///
    /// If the current function has more arguments than fits in registers, the remaining arguments
    /// are passed on the stack by the caller. These incoming arguments are represented as SSA
    /// values assigned to incoming stack slots.
    IncomingArg,

    /// An outgoing function argument.
    ///
    /// When preparing to call a function whose arguments don't fit in registers, outgoing argument
    /// stack slots are used to represent individual arguments in the outgoing call frame. These
    /// stack slots are only valid while setting up a call.
    OutgoingArg,
}

impl FromStr for StackSlotKind {
    type Err = ();

    fn from_str(s: &str) -> Result<StackSlotKind, ()> {
        use self::StackSlotKind::*;
        match s {
            "local" => Ok(Local),
            "spill_slot" => Ok(SpillSlot),
            "incoming_arg" => Ok(IncomingArg),
            "outgoing_arg" => Ok(OutgoingArg),
            _ => Err(()),
        }
    }
}

impl fmt::Display for StackSlotKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::StackSlotKind::*;
        f.write_str(match *self {
                        Local => "local",
                        SpillSlot => "spill_slot",
                        IncomingArg => "incoming_arg",
                        OutgoingArg => "outgoing_arg",
                    })
    }
}

/// Contents of a stack slot.
#[derive(Clone, Debug)]
pub struct StackSlotData {
    /// The kind of stack slot.
    pub kind: StackSlotKind,

    /// Size of stack slot in bytes.
    pub size: StackSize,

    /// Offset of stack slot relative to the stack pointer in the caller.
    ///
    /// On Intel ISAs, the base address is the stack pointer *before* the return address was
    /// pushed. On RISC ISAs, the base address is the value of the stack pointer on entry to the
    /// function.
    ///
    /// For `OutgoingArg` stack slots, the offset is relative to the current function's stack
    /// pointer immediately before the call.
    pub offset: StackOffset,
}

impl StackSlotData {
    /// Create a stack slot with the specified byte size.
    pub fn new(kind: StackSlotKind, size: StackSize) -> StackSlotData {
        StackSlotData {
            kind,
            size,
            offset: 0,
        }
    }

    /// Get the alignment in bytes of this stack slot given the stack pointer alignment.
    pub fn alignment(&self, max_align: StackSize) -> StackSize {
        debug_assert!(max_align.is_power_of_two());
        // We want to find the largest power of two that divides both `self.size` and `max_align`.
        // That is the same as isolating the rightmost bit in `x`.
        let x = self.size | max_align;
        // C.f. Hacker's delight.
        x & x.wrapping_neg()
    }
}

impl fmt::Display for StackSlotData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.kind, self.size)?;
        if self.offset != 0 {
            write!(f, ", offset {}", self.offset)?;
        }
        Ok(())
    }
}

impl PrimaryEntityData for StackSlotData {}

/// Stack frame manager.
///
/// Keep track of all the stack slots used by a function.
#[derive(Clone, Debug)]
pub struct StackSlots {
    /// All allocated stack slots.
    slots: EntityMap<StackSlot, StackSlotData>,

    /// All the outgoing stack slots, ordered by offset.
    outgoing: Vec<StackSlot>,

    /// The total size of the stack frame.
    ///
    /// This is the distance from the stack pointer in the current function to the stack pointer in
    /// the calling function, so it includes a pushed return address as well as space for outgoing
    /// call arguments.
    ///
    /// This is computed by the `layout()` method.
    pub frame_size: Option<StackSize>,
}

/// Stack slot manager functions that behave mostly like an entity map.
impl StackSlots {
    /// Create an empty stack slot manager.
    pub fn new() -> StackSlots {
        StackSlots {
            slots: EntityMap::new(),
            outgoing: Vec::new(),
            frame_size: None,
        }
    }

    /// Clear out everything.
    pub fn clear(&mut self) {
        self.slots.clear();
        self.outgoing.clear();
        self.frame_size = None;
    }

    /// Allocate a new stack slot.
    ///
    /// This function should be primarily used by the text format parser. There are more convenient
    /// functions for creating specific kinds of stack slots below.
    pub fn push(&mut self, data: StackSlotData) -> StackSlot {
        self.slots.push(data)
    }

    /// Check if `ss` is a valid stack slot reference.
    pub fn is_valid(&self, ss: StackSlot) -> bool {
        self.slots.is_valid(ss)
    }

    /// Get an iterator over all the stack slot keys.
    pub fn keys(&self) -> Keys<StackSlot> {
        self.slots.keys()
    }

    /// Get a reference to the next stack slot that would be created by `push()`.
    ///
    /// This should just be used by the parser.
    pub fn next_key(&self) -> StackSlot {
        self.slots.next_key()
    }
}

impl Index<StackSlot> for StackSlots {
    type Output = StackSlotData;

    fn index(&self, ss: StackSlot) -> &StackSlotData {
        &self.slots[ss]
    }
}

/// Higher-level stack frame manipulation functions.
impl StackSlots {
    /// Create a new spill slot for spilling values of type `ty`.
    pub fn make_spill_slot(&mut self, ty: Type) -> StackSlot {
        self.push(StackSlotData::new(StackSlotKind::SpillSlot, ty.bytes()))
    }

    /// Create a stack slot representing an incoming function argument.
    pub fn make_incoming_arg(&mut self, ty: Type, offset: StackOffset) -> StackSlot {
        let mut data = StackSlotData::new(StackSlotKind::IncomingArg, ty.bytes());
        assert!(offset <= StackOffset::max_value() - data.size as StackOffset);
        data.offset = offset;
        self.push(data)
    }

    /// Get a stack slot representing an outgoing argument.
    ///
    /// This may create a new stack slot, or reuse an existing outgoing stack slot with the
    /// requested offset and size.
    ///
    /// The requested offset is relative to this function's stack pointer immediately before making
    /// the call.
    pub fn get_outgoing_arg(&mut self, ty: Type, offset: StackOffset) -> StackSlot {
        let size = ty.bytes();

        // Look for an existing outgoing stack slot with the same offset and size.
        let inspos = match self.outgoing
                  .binary_search_by_key(&(offset, size),
                                        |&ss| (self[ss].offset, self[ss].size)) {
            Ok(idx) => return self.outgoing[idx],
            Err(idx) => idx,
        };

        // No existing slot found. Make one and insert it into `outgoing`.
        let mut data = StackSlotData::new(StackSlotKind::OutgoingArg, size);
        assert!(offset <= StackOffset::max_value() - size as StackOffset);
        data.offset = offset;
        let ss = self.slots.push(data);
        self.outgoing.insert(inspos, ss);
        ss
    }

    /// Compute the stack frame layout.
    ///
    /// Determine the total size of this function's stack frame and assign offsets to all `Spill`
    /// and `Local` stack slots.
    ///
    /// The total frame size will be a multiple of `alignment` which must be a power of two.
    ///
    /// Returns the total stack frame size which is also saved in `self.frame_size`.
    pub fn layout(&mut self, alignment: StackSize) -> StackSize {
        assert!(alignment.is_power_of_two() && alignment <= StackOffset::max_value() as StackSize,
                "Invalid stack alignment {}",
                alignment);

        // We assume a stack that grows toward lower addresses as implemented by modern ISAs. The
        // stack layout from high to low addresses will be:
        //
        // 1. incoming arguments.
        // 2. spills + locals.
        // 3. outgoing arguments.
        //
        // The incoming arguments can have both positive and negative offsets. A negative offset
        // incoming arguments is usually the x86 return address pushed by the call instruction, but
        // it can also be fixed stack slots pushed by an externally generated prologue.
        //
        // Both incoming and outgoing argument slots have fixed offsets that are treated as
        // reserved zones by the layout algorithm.

        let mut incoming_min = 0;
        let mut outgoing_max = 0;
        let mut min_align = alignment;

        for ss in self.keys() {
            let slot = &self[ss];
            assert!(slot.size <= StackOffset::max_value() as StackSize);
            match slot.kind {
                StackSlotKind::IncomingArg => {
                    incoming_min = min(incoming_min, slot.offset);
                }
                StackSlotKind::OutgoingArg => {
                    let offset = slot.offset
                        .checked_add(slot.size as StackOffset)
                        .expect("Outgoing call argument overflows stack");
                    outgoing_max = max(outgoing_max, offset);
                }
                StackSlotKind::SpillSlot | StackSlotKind::Local => {
                    // Determine the smallest alignment of any local or spill slot.
                    min_align = slot.alignment(min_align);
                }
            }
        }

        // Lay out spill slots and locals below the incoming arguments.
        // The offset is negative, growing downwards.
        // Start with the smallest alignments for better packing.
        let mut offset = incoming_min;
        assert!(min_align.is_power_of_two());
        while min_align <= alignment {
            for ss in self.keys() {
                let slot = &mut self.slots[ss];

                // Pick out locals and spill slots with exact alignment `min_align`.
                match slot.kind {
                    StackSlotKind::SpillSlot | StackSlotKind::Local => {
                        if slot.alignment(alignment) != min_align {
                            continue;
                        }
                    }
                    _ => continue,
                }

                // These limits should never be exceeded by spill slots, but locals can be
                // arbitrarily large.
                assert!(slot.size <= StackOffset::max_value() as StackSize);
                offset = offset
                    .checked_sub(slot.size as StackOffset)
                    .expect("Stack frame larger than 2 GB");

                // Aligning the negative offset can never cause overflow. We're only clearing bits.
                offset &= -(min_align as StackOffset);
                slot.offset = offset;
            }

            // Move on to the next higher alignment.
            min_align *= 2;
        }

        // Finally, make room for the outgoing arguments.
        offset = offset
            .checked_sub(outgoing_max)
            .expect("Stack frame larger than 2 GB");
        offset &= -(alignment as StackOffset);

        let frame_size = (offset as StackSize).wrapping_neg();
        self.frame_size = Some(frame_size);
        frame_size
    }
}

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

    #[test]
    fn stack_slot() {
        let mut func = Function::new();

        let ss0 = func.stack_slots
            .push(StackSlotData::new(StackSlotKind::IncomingArg, 4));
        let ss1 = func.stack_slots
            .push(StackSlotData::new(StackSlotKind::SpillSlot, 8));
        assert_eq!(ss0.to_string(), "ss0");
        assert_eq!(ss1.to_string(), "ss1");

        assert_eq!(func.stack_slots[ss0].size, 4);
        assert_eq!(func.stack_slots[ss1].size, 8);

        assert_eq!(func.stack_slots[ss0].to_string(), "incoming_arg 4");
        assert_eq!(func.stack_slots[ss1].to_string(), "spill_slot 8");
    }

    #[test]
    fn outgoing() {
        let mut sss = StackSlots::new();

        let ss0 = sss.get_outgoing_arg(types::I32, 8);
        let ss1 = sss.get_outgoing_arg(types::I32, 4);
        let ss2 = sss.get_outgoing_arg(types::I64, 8);

        assert_eq!(sss[ss0].offset, 8);
        assert_eq!(sss[ss0].size, 4);

        assert_eq!(sss[ss1].offset, 4);
        assert_eq!(sss[ss1].size, 4);

        assert_eq!(sss[ss2].offset, 8);
        assert_eq!(sss[ss2].size, 8);

        assert_eq!(sss.get_outgoing_arg(types::I32, 8), ss0);
        assert_eq!(sss.get_outgoing_arg(types::I32, 4), ss1);
        assert_eq!(sss.get_outgoing_arg(types::I64, 8), ss2);
    }

    #[test]
    fn alignment() {
        let slot = StackSlotData::new(StackSlotKind::SpillSlot, 8);

        assert_eq!(slot.alignment(4), 4);
        assert_eq!(slot.alignment(8), 8);
        assert_eq!(slot.alignment(16), 8);

        let slot2 = StackSlotData::new(StackSlotKind::Local, 24);

        assert_eq!(slot2.alignment(4), 4);
        assert_eq!(slot2.alignment(8), 8);
        assert_eq!(slot2.alignment(16), 8);
        assert_eq!(slot2.alignment(32), 8);
    }

    #[test]
    fn layout() {
        let mut sss = StackSlots::new();

        // An empty layout should have 0-sized stack frame.
        assert_eq!(sss.layout(1), 0);
        assert_eq!(sss.layout(16), 0);

        // Same for incoming arguments with non-negative offsets.
        let in0 = sss.make_incoming_arg(types::I64, 0);
        let in1 = sss.make_incoming_arg(types::I64, 8);

        assert_eq!(sss.layout(1), 0);
        assert_eq!(sss.layout(16), 0);
        assert_eq!(sss[in0].offset, 0);
        assert_eq!(sss[in1].offset, 8);

        // Add some spill slots.
        let ss0 = sss.make_spill_slot(types::I64);
        let ss1 = sss.make_spill_slot(types::I32);

        assert_eq!(sss.layout(1), 12);
        assert_eq!(sss[in0].offset, 0);
        assert_eq!(sss[in1].offset, 8);
        assert_eq!(sss[ss0].offset, -8);
        assert_eq!(sss[ss1].offset, -12);

        assert_eq!(sss.layout(16), 16);
        assert_eq!(sss[in0].offset, 0);
        assert_eq!(sss[in1].offset, 8);
        assert_eq!(sss[ss0].offset, -16);
        assert_eq!(sss[ss1].offset, -4);

        // An incoming argument with negative offset counts towards the total frame size, but it
        // should still pack nicely with the spill slots.
        let in2 = sss.make_incoming_arg(types::I32, -4);

        assert_eq!(sss.layout(1), 16);
        assert_eq!(sss[in0].offset, 0);
        assert_eq!(sss[in1].offset, 8);
        assert_eq!(sss[in2].offset, -4);
        assert_eq!(sss[ss0].offset, -12);
        assert_eq!(sss[ss1].offset, -16);

        assert_eq!(sss.layout(16), 16);
        assert_eq!(sss[in0].offset, 0);
        assert_eq!(sss[in1].offset, 8);
        assert_eq!(sss[in2].offset, -4);
        assert_eq!(sss[ss0].offset, -16);
        assert_eq!(sss[ss1].offset, -8);

        // Finally, make sure there is room for the outgoing args.
        let out0 = sss.get_outgoing_arg(types::I32, 0);

        assert_eq!(sss.layout(1), 20);
        assert_eq!(sss[in0].offset, 0);
        assert_eq!(sss[in1].offset, 8);
        assert_eq!(sss[in2].offset, -4);
        assert_eq!(sss[ss0].offset, -12);
        assert_eq!(sss[ss1].offset, -16);
        assert_eq!(sss[out0].offset, 0);

        assert_eq!(sss.layout(16), 32);
        assert_eq!(sss[in0].offset, 0);
        assert_eq!(sss[in1].offset, 8);
        assert_eq!(sss[in2].offset, -4);
        assert_eq!(sss[ss0].offset, -16);
        assert_eq!(sss[ss1].offset, -8);
        assert_eq!(sss[out0].offset, 0);
    }
}
<|endoftext|>


<commit_before>extern crate walkdir;

use self::walkdir::{DirEntry as WalkDirEntry, WalkDir, WalkDirIterator};

use constant::{WORKING_DIR_NAME, KEEPED_FILE_NAME};
use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
use std::io::Error as IoError;
use std::path::Path;
use std::result::Result;

macro_rules! path_buf {
    ($($x: expr),+) => {
        PathBuf::new()
            $(.join($x))+
    };
}

pub fn ls<P: AsRef<Path>>(path: P) -> Result<Vec<String>, IoError> {
    let dirs = try!(fs::read_dir(path));
    let dirs = dirs
        .filter_map(Result::ok)
        .map(|d| d.file_name())
        .map(OsString::into_string)
        .filter_map(Result::ok)
        .collect::<Vec<String>>();
    Ok(dirs)
}

pub fn is_empty_dir<P: AsRef<Path>>(path: P) -> bool {
    match fs::read_dir(path) {
        Ok(rd) => rd.count() == 0,
        Err(_) => false,
    }
}

fn is_hidden_name(file_name: &str) -> bool {
    file_name.starts_with(".") && file_name.len() > 1 && file_name != ".."
}
#[test]
fn hidden_name() {
    let file_names = [
        ".a",
        ".ab",
        ".abc",
        "..a",
        "...",
    ];
    for file_name in &file_names {
        assert!(is_hidden_name(file_name));
    }
}
#[test]
fn non_hidden_name() {
    let file_names = [
        "",

        ".",
        "..",
        "a",
        "ab",
        "abc",
    ];
    for file_name in &file_names {
        assert!(!is_hidden_name(file_name));
    }
}

fn is_hidden(entry: &WalkDirEntry) -> bool {
    entry
        .file_name()
        .to_str()
        .map_or(false, is_hidden_name)
}

fn is_pinned(entry: &WalkDirEntry) -> bool {
    entry
        .file_name()
        .to_str()
        .map_or(false, |s| s == WORKING_DIR_NAME || s == KEEPED_FILE_NAME)
}

fn is_target(entry: &WalkDirEntry) -> bool {
    !is_hidden(entry) && !is_pinned(entry)
}

fn to_string(entry: WalkDirEntry) -> Option<String> {
    entry
        .path()
        .to_str()
        .map(|p| p.to_string())
}

pub fn walk_dir<P: AsRef<Path>>(root: P) -> BTreeSet<String> {
    let walker = WalkDir::new(root)
        .into_iter()
        .filter_entry(is_target)
        .filter_map(Result::ok)
        .filter(|e| !e.file_type().is_dir())
        .collect::<Vec<WalkDirEntry>>();

    walker
        .into_iter()
        .filter_map(to_string)
        .collect::<BTreeSet<String>>()
}

pub fn dirs_ordered_by_descending_depth<P: AsRef<Path>>(root: P) -> Vec<String> {
    let mut walker = WalkDir::new(root)
        .into_iter()
        .filter_entry(is_target)
        .filter_entry(|e| e.file_type().is_dir())
        .filter_map(Result::ok)
        .collect::<Vec<WalkDirEntry>>();

    walker.sort_by(|l, r| {
        let l_depth = &l.depth();
        let r_depth = &r.depth();
        r_depth.cmp(l_depth)
    });

    walker
        .into_iter()
        .filter_map(to_string)
        .collect::<Vec<String>>()
}

#[cfg(test)]
mod tests {
    use std::path::{Path, PathBuf};

    #[test]
    fn create_path_buf() {
        let paths = [
            (Path::new("path").to_path_buf()          , path_buf!["path"              ]),
            (Path::new("path").join("to")             , path_buf!["path", "to"        ]),
            (Path::new("path").join("to").join("file"), path_buf!["path", "to", "file"]),
        ];
        for &(ref correct, ref calculated) in &paths {
            assert_eq!(correct, calculated);
        }
    }
}
<commit_msg>[Remedy] Delete empty directories containing "OsStr"<commit_after>extern crate walkdir;

use self::walkdir::{DirEntry as WalkDirEntry, WalkDir, WalkDirIterator};

use constant::{WORKING_DIR_NAME, KEEPED_FILE_NAME};
use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
use std::io::Error as IoError;
use std::path::{Path, PathBuf};
use std::result::Result;

macro_rules! path_buf {
    ($($x: expr),+) => {
        PathBuf::new()
            $(.join($x))+
    };
}

pub fn ls<P: AsRef<Path>>(path: P) -> Result<Vec<String>, IoError> {
    let dirs = try!(fs::read_dir(path));
    let dirs = dirs
        .filter_map(Result::ok)
        .map(|d| d.file_name())
        .map(OsString::into_string)
        .filter_map(Result::ok)
        .collect::<Vec<String>>();
    Ok(dirs)
}

pub fn is_empty_dir<P: AsRef<Path>>(path: P) -> bool {
    match fs::read_dir(path) {
        Ok(rd) => rd.count() == 0,
        Err(_) => false,
    }
}

fn is_hidden_name(file_name: &str) -> bool {
    file_name.starts_with(".") && file_name.len() > 1 && file_name != ".."
}
#[test]
fn hidden_name() {
    let file_names = [
        ".a",
        ".ab",
        ".abc",
        "..a",
        "...",
    ];
    for file_name in &file_names {
        assert!(is_hidden_name(file_name));
    }
}
#[test]
fn non_hidden_name() {
    let file_names = [
        "",

        ".",
        "..",
        "a",
        "ab",
        "abc",
    ];
    for file_name in &file_names {
        assert!(!is_hidden_name(file_name));
    }
}

fn is_hidden(entry: &WalkDirEntry) -> bool {
    entry
        .file_name()
        .to_str()
        .map_or(false, is_hidden_name)
}

fn is_pinned(entry: &WalkDirEntry) -> bool {
    entry
        .file_name()
        .to_str()
        .map_or(false, |s| s == WORKING_DIR_NAME || s == KEEPED_FILE_NAME)
}

fn is_target(entry: &WalkDirEntry) -> bool {
    !is_hidden(entry) && !is_pinned(entry)
}

pub fn walk_dir<P: AsRef<Path>>(root: P) -> BTreeSet<String> {
    let walker = WalkDir::new(root)
        .into_iter()
        .filter_entry(is_target)
        .filter_map(Result::ok)
        .filter(|e| !e.file_type().is_dir())
        .collect::<Vec<WalkDirEntry>>();

    walker
        .into_iter()
        .filter_map(|e| e.path().to_str().map(|s| s.to_string()))
        .collect::<BTreeSet<String>>()
}

pub fn dirs_ordered_by_descending_depth<P: AsRef<Path>>(root: P) -> Vec<PathBuf> {
    let mut walker = WalkDir::new(root)
        .into_iter()
        .filter_entry(is_target)
        .filter_entry(|e| e.file_type().is_dir())
        .filter_map(Result::ok)
        .collect::<Vec<WalkDirEntry>>();

    walker.sort_by(|l, r| {
        let l_depth = &l.depth();
        let r_depth = &r.depth();
        r_depth.cmp(l_depth)
    });

    walker
        .into_iter()
        .map(|e| e.path().to_path_buf())
        .collect::<Vec<PathBuf>>()
}

#[cfg(test)]
mod tests {
    use std::path::{Path, PathBuf};

    #[test]
    fn create_path_buf() {
        let paths = [
            (Path::new("path").to_path_buf()          , path_buf!["path"              ]),
            (Path::new("path").join("to")             , path_buf!["path", "to"        ]),
            (Path::new("path").join("to").join("file"), path_buf!["path", "to", "file"]),
        ];
        for &(ref correct, ref calculated) in &paths {
            assert_eq!(correct, calculated);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray 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.
use libnum::{Zero, One, Float};
use std::any::Any;
use std::fmt;
use std::ops::{Add, Sub, Mul, Div};
#[cfg(feature="assign_ops")]
use std::ops::{
    AddAssign,
    SubAssign,
    MulAssign,
    DivAssign,
    RemAssign,
};
use ScalarOperand;

#[cfg(feature="rblas")]
use std::any::TypeId;

#[cfg(feature="rblas")]
use ShapeError;

#[cfg(feature="rblas")]
use error::{from_kind, ErrorKind};

#[cfg(feature="rblas")]
use blas::{AsBlas, BlasArrayView};

#[cfg(feature="rblas")]
use imp_prelude::*;

/// Elements that support linear algebra operations.
///
/// `Any` for type-based specialization, `Copy` so that they don't need move
/// semantics or destructors, and the rest are numerical traits.
pub trait LinalgScalar :
    Any +
    Copy +
    Zero + One +
    Add<Output=Self> +
    Sub<Output=Self> +
    Mul<Output=Self> +
    Div<Output=Self>
{ }

impl<T> LinalgScalar for T
    where T:
    Any +
    Copy +
    Zero + One +
    Add<Output=T> +
    Sub<Output=T> +
    Mul<Output=T> +
    Div<Output=T>
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
#[cfg(not(feature="assign_ops"))]
pub trait NdFloat :
    Float +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
///
/// This trait can only be implemented by `f32` and `f64`.
#[cfg(feature="assign_ops")]
pub trait NdFloat :
    Float +
    AddAssign + SubAssign + MulAssign + DivAssign + RemAssign +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

impl NdFloat for f32 { }
impl NdFloat for f64 { }

#[cfg(feature = "rblas")]
pub trait AsBlasAny<A, S, D> : AsBlas<A, S, D> {
    fn blas_view_as_type<T: Any>(&self) -> Result<BlasArrayView<T, D>, ShapeError>
        where S: Data;
}

#[cfg(feature = "rblas")]
/// ***Requires `features = "rblas"`***
impl<A, S, D> AsBlasAny<A, S, D> for ArrayBase<S, D>
    where S: Data<Elem=A>,
          D: Dimension,
          A: Any,
{
    fn blas_view_as_type<T: Any>(&self) -> Result<BlasArrayView<T, D>, ShapeError>
        where S: Data
    {
        if TypeId::of::<A>() == TypeId::of::<T>() {
            unsafe {
                let v = self.view();
                let u = ArrayView::new_(v.ptr as *const T, v.dim, v.strides);
                Priv(u).into_blas_view()
            }
        } else {
            Err(from_kind(ErrorKind::IncompatibleLayout))
        }
    }
}
<commit_msg>Remove unused helpers from linalg.rs<commit_after>// Copyright 2014-2016 bluss and ndarray 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.
use libnum::{Zero, One, Float};
use std::any::Any;
use std::fmt;
use std::ops::{Add, Sub, Mul, Div};
#[cfg(feature="assign_ops")]
use std::ops::{
    AddAssign,
    SubAssign,
    MulAssign,
    DivAssign,
    RemAssign,
};
use ScalarOperand;

/// Elements that support linear algebra operations.
///
/// `Any` for type-based specialization, `Copy` so that they don't need move
/// semantics or destructors, and the rest are numerical traits.
pub trait LinalgScalar :
    Any +
    Copy +
    Zero + One +
    Add<Output=Self> +
    Sub<Output=Self> +
    Mul<Output=Self> +
    Div<Output=Self>
{ }

impl<T> LinalgScalar for T
    where T:
    Any +
    Copy +
    Zero + One +
    Add<Output=T> +
    Sub<Output=T> +
    Mul<Output=T> +
    Div<Output=T>
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
#[cfg(not(feature="assign_ops"))]
pub trait NdFloat :
    Float +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

/// Floating-point element types `f32` and `f64`.
///
/// Trait `NdFloat` is only implemented for `f32` and `f64` but encompasses as
/// much float-relevant ndarray functionality as possible, including the traits
/// needed for linear algebra (`Any`) and for *right hand side* scalar
/// operations (`ScalarOperand`).
///
/// This trait can only be implemented by `f32` and `f64`.
#[cfg(feature="assign_ops")]
pub trait NdFloat :
    Float +
    AddAssign + SubAssign + MulAssign + DivAssign + RemAssign +
    fmt::Display + fmt::Debug + fmt::LowerExp + fmt::UpperExp +
    ScalarOperand + LinalgScalar
{ }

impl NdFloat for f32 { }
impl NdFloat for f64 { }
<|endoftext|>


<commit_before>use std;
use serde_json;
use std::io::prelude::*;
use std::net::{ToSocketAddrs, UdpSocket};
use std::hash::{Hash, Hasher, SipHasher};
use log::{Log, LogLevel, LogMetadata, LogRecord};
use flate2::Compression;
use flate2::write::GzEncoder;
use chrono::{DateTime, UTC};
use byteorder::{BigEndian, WriteBytesExt};

use GraylogError;

const MAX_PACKET_SIZE: usize = 8192;
const MAGIC_BYTES: u16 = 0x1E0F;
const HEADER_SIZE: usize = 12; // TODO: figure out how to do this with mem::size_of<ChunkHeader>()

struct GraylogLogger {
    server: A,
    sock: UdpSocket,
    level: LogLevel,
    hostname: String,
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Gelf {
    version: String,
    host: String,
    short_message: String,
    full_message: Option<String>,
    timestamp: Option<i64>,
    level: Option<u8>,
    #[serde(rename="_file")]
    file: String,
    #[serde(rename="_line")]
    line: u32,
}

struct GelfChunks<'a> {
    count: usize,
    total: usize,
    #[allow(dead_code)]
    data: &'a [u8],
    chunks: Vec<&'a [u8]>,
    message_id: u64,
}

struct Chunk<'a> {
    header: ChunkHeader,
    data: &'a [u8],
}

impl<'a> Chunk<'a> {
    fn to_binary(&self) -> Result<Vec<u8>, GraylogError> {
        let mut wrt = vec![];
        try!(wrt.write_u16::<BigEndian>(self.header.magic_bytes));
        try!(wrt.write_u64::<BigEndian>(self.header.message_id));
        try!(wrt.write_u8(self.header.seq_number));
        try!(wrt.write_u8(self.header.seq_count));
        wrt.extend(self.data.iter());
        Ok(wrt)
    }
}

#[derive(Debug)]
struct ChunkHeader {
    magic_bytes: u16,
    message_id: u64,
    seq_number: u8,
    seq_count: u8,
}

impl<'a> GelfChunks<'a> {
    fn new(data: &'a [u8], message_id: u64) -> GelfChunks<'a> {
        let chunk_size = MAX_PACKET_SIZE - HEADER_SIZE;
        let mut chunks = data.chunks(chunk_size).collect::<Vec<&[u8]>>();
        chunks.reverse();

        GelfChunks {
            count: 0,
            total: chunks.len(),
            chunks: chunks,
            data: data,
            message_id: message_id,
        }
    }
}

impl<'a> Iterator for GelfChunks<'a> {
    type Item = Chunk<'a>;

    fn next(&mut self) -> Option<Chunk<'a>> {
        self.chunks.pop().map(|data| {
            let header = ChunkHeader {
                magic_bytes: MAGIC_BYTES,
                message_id: self.message_id,
                seq_number: self.count as u8,
                seq_count: self.total as u8,
            };
            println!("{:?}", header);

            self.count += 1;

            Chunk {
                header: header,
                data: data,
            }
        })
    }
}

pub fn init(addr: A, level: LogLevel) -> Result<(), GraylogError>
    where A: std::marker::Send + std::marker::Sync
{
    use log;
    use std::process::Command;
    let sock = try!(UdpSocket::bind("0.0.0.0:0"));

    try!(log::set_logger(|max_log_level| {
        max_log_level.set(level.to_log_level_filter());
        let hostname = Command::new("hostname")
            .arg("-f")
            .output()
            .map(|out| String::from_utf8_lossy(&out.stdout).into_owned())
            .unwrap_or("unknown".to_string());

        Box::new(GraylogLogger {
            level: level,
            server: addr,
            sock: sock,
            hostname: hostname,
        })
    }));
    Ok(())
}

impl Gelf {
    fn message_id(&self) -> u64 {
        use chrono::Timelike;
        let mut s = SipHasher::new();
        self.host.hash(&mut s);
        self.timestamp.hash(&mut s);
        UTC::now().nanosecond().hash(&mut s);
        s.finish()
    }
}

impl GraylogLogger {
    fn send_as_gelf(&self, record: &LogRecord) -> Result<usize, GraylogError> {
        let utc: DateTime<UTC> = UTC::now();

        let location = record.location();
        let gelf = Gelf {
            version: "1.1".to_string(),
            short_message: format!("{}", record.args()),
            full_message: None,
            timestamp: Some(utc.timestamp()),
            level: None,
            host: self.hostname.clone(),
            file: location.file().to_string(),
            line: location.line(),
        };

        let json = try!(serde_json::to_string(&gelf));
        let mut e = GzEncoder::new(Vec::new(), Compression::Default);
        try!(e.write_all(json.as_bytes()));

        let compressed_bytes = try!(e.finish());
        if compressed_bytes.len() > MAX_PACKET_SIZE {
            self.send_chunked_gelf(&compressed_bytes, gelf.message_id())
        } else {
            self.send(&compressed_bytes)
        }
    }

    fn send_chunked_gelf(&self, buffer: &[u8], message_id: u64) -> Result<usize, GraylogError> {
        let chunks = GelfChunks::new(buffer, message_id);
        println!("Graylog message_id: {:x}", message_id);
        for chunk in chunks {
            let data = try!(chunk.to_binary());
            try!(self.send(&data));
        }
        Ok(1)
    }

    fn send(&self, buffer: &[u8]) -> Result<usize, GraylogError> {
        let s = try!(self.sock.send_to(buffer, &self.server).or_else(|e| {
            println!("Error writing to Graylog: {}", e);
            Err(e)
        }));
        Ok(s)
    }
}

impl Log for GraylogLogger
    where A: std::marker::Send + std::marker::Sync
{
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            if self.send_as_gelf(record).is_err() {
                println!("{} {} - {}", UTC::now(), record.level(), record.args());
            };
        }
    }
}

#[test]
fn test_gelf_serialization() {
    use serde_json::Value;
    let file = "asdfasdfadsf.rs".to_string();
    let line = 123;
    let gelf = Gelf {
        version: "1.1".to_string(),
        host: "somehost".to_string(),
        short_message: "some short message".to_string(),
        full_message: Some("Full message".to_string()),
        timestamp: Some(UTC::now().timestamp()),
        level: None,
        file: file.clone(),
        line: line,
    };
    let json = serde_json::to_string(&gelf).unwrap();
    println!("Json\n{}", json);

    let data: Value = serde_json::from_str(&json).unwrap();
    let obj = data.as_object().unwrap();
    assert_eq!(obj.get("_file").unwrap().as_string().unwrap(), file);
    assert_eq!(obj.get("_line").unwrap().as_u64().unwrap(), line as u64);

    let deserialized_gelf: Gelf = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized_gelf, gelf);
    println!("{:?}", obj);
}

#[cfg(test)]
mod tests {
    use log;

    use super::*;

    #[test]
    fn test_it_works() {
        assert!(init("192.168.1.1", log::LogLevel::Debug).is_ok());
    }

}
<commit_msg>trim the hostname<commit_after>use std;
use serde_json;
use std::io::prelude::*;
use std::net::{ToSocketAddrs, UdpSocket};
use std::hash::{Hash, Hasher, SipHasher};
use log::{Log, LogLevel, LogMetadata, LogRecord};
use flate2::Compression;
use flate2::write::GzEncoder;
use chrono::{DateTime, UTC};
use byteorder::{BigEndian, WriteBytesExt};

use GraylogError;

const MAX_PACKET_SIZE: usize = 8192;
const MAGIC_BYTES: u16 = 0x1E0F;
const HEADER_SIZE: usize = 12; // TODO: figure out how to do this with mem::size_of<ChunkHeader>()

struct GraylogLogger {
    server: A,
    sock: UdpSocket,
    level: LogLevel,
    hostname: String,
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Gelf {
    version: String,
    host: String,
    short_message: String,
    full_message: Option<String>,
    timestamp: Option<i64>,
    level: Option<u8>,
    #[serde(rename="_file")]
    file: String,
    #[serde(rename="_line")]
    line: u32,
}

struct GelfChunks<'a> {
    count: usize,
    total: usize,
    #[allow(dead_code)]
    data: &'a [u8],
    chunks: Vec<&'a [u8]>,
    message_id: u64,
}

struct Chunk<'a> {
    header: ChunkHeader,
    data: &'a [u8],
}

impl<'a> Chunk<'a> {
    fn to_binary(&self) -> Result<Vec<u8>, GraylogError> {
        let mut wrt = vec![];
        try!(wrt.write_u16::<BigEndian>(self.header.magic_bytes));
        try!(wrt.write_u64::<BigEndian>(self.header.message_id));
        try!(wrt.write_u8(self.header.seq_number));
        try!(wrt.write_u8(self.header.seq_count));
        wrt.extend(self.data.iter());
        Ok(wrt)
    }
}

#[derive(Debug)]
struct ChunkHeader {
    magic_bytes: u16,
    message_id: u64,
    seq_number: u8,
    seq_count: u8,
}

impl<'a> GelfChunks<'a> {
    fn new(data: &'a [u8], message_id: u64) -> GelfChunks<'a> {
        let chunk_size = MAX_PACKET_SIZE - HEADER_SIZE;
        let mut chunks = data.chunks(chunk_size).collect::<Vec<&[u8]>>();
        chunks.reverse();

        GelfChunks {
            count: 0,
            total: chunks.len(),
            chunks: chunks,
            data: data,
            message_id: message_id,
        }
    }
}

impl<'a> Iterator for GelfChunks<'a> {
    type Item = Chunk<'a>;

    fn next(&mut self) -> Option<Chunk<'a>> {
        self.chunks.pop().map(|data| {
            let header = ChunkHeader {
                magic_bytes: MAGIC_BYTES,
                message_id: self.message_id,
                seq_number: self.count as u8,
                seq_count: self.total as u8,
            };
            println!("{:?}", header);

            self.count += 1;

            Chunk {
                header: header,
                data: data,
            }
        })
    }
}

pub fn init(addr: A, level: LogLevel) -> Result<(), GraylogError>
    where A: std::marker::Send + std::marker::Sync
{
    use log;
    use std::process::Command;
    let sock = try!(UdpSocket::bind("0.0.0.0:0"));

    try!(log::set_logger(|max_log_level| {
        max_log_level.set(level.to_log_level_filter());
        let hostname = Command::new("hostname")
            .arg("-f")
            .output()
            .map(|out| String::from_utf8_lossy(&out.stdout).into_owned())
            .unwrap_or("unknown".to_string());

        Box::new(GraylogLogger {
            level: level,
            server: addr,
            sock: sock,
            hostname: hostname.trim().to_string(),
        })
    }));
    Ok(())
}

impl Gelf {
    fn message_id(&self) -> u64 {
        use chrono::Timelike;
        let mut s = SipHasher::new();
        self.host.hash(&mut s);
        self.timestamp.hash(&mut s);
        UTC::now().nanosecond().hash(&mut s);
        s.finish()
    }
}

impl GraylogLogger {
    fn send_as_gelf(&self, record: &LogRecord) -> Result<usize, GraylogError> {
        let utc: DateTime<UTC> = UTC::now();

        let location = record.location();
        let gelf = Gelf {
            version: "1.1".to_string(),
            short_message: format!("{}", record.args()),
            full_message: None,
            timestamp: Some(utc.timestamp()),
            level: None,
            host: self.hostname.clone(),
            file: location.file().to_string(),
            line: location.line(),
        };

        let json = try!(serde_json::to_string(&gelf));
        let mut e = GzEncoder::new(Vec::new(), Compression::Default);
        try!(e.write_all(json.as_bytes()));

        let compressed_bytes = try!(e.finish());
        if compressed_bytes.len() > MAX_PACKET_SIZE {
            self.send_chunked_gelf(&compressed_bytes, gelf.message_id())
        } else {
            self.send(&compressed_bytes)
        }
    }

    fn send_chunked_gelf(&self, buffer: &[u8], message_id: u64) -> Result<usize, GraylogError> {
        let chunks = GelfChunks::new(buffer, message_id);
        println!("Graylog message_id: {:x}", message_id);
        for chunk in chunks {
            let data = try!(chunk.to_binary());
            try!(self.send(&data));
        }
        Ok(1)
    }

    fn send(&self, buffer: &[u8]) -> Result<usize, GraylogError> {
        let s = try!(self.sock.send_to(buffer, &self.server).or_else(|e| {
            println!("Error writing to Graylog: {}", e);
            Err(e)
        }));
        Ok(s)
    }
}

impl Log for GraylogLogger
    where A: std::marker::Send + std::marker::Sync
{
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            if self.send_as_gelf(record).is_err() {
                println!("{} {} - {}", UTC::now(), record.level(), record.args());
            };
        }
    }
}

#[test]
fn test_gelf_serialization() {
    use serde_json::Value;
    let file = "asdfasdfadsf.rs".to_string();
    let line = 123;
    let gelf = Gelf {
        version: "1.1".to_string(),
        host: "somehost".to_string(),
        short_message: "some short message".to_string(),
        full_message: Some("Full message".to_string()),
        timestamp: Some(UTC::now().timestamp()),
        level: None,
        file: file.clone(),
        line: line,
    };
    let json = serde_json::to_string(&gelf).unwrap();
    println!("Json\n{}", json);

    let data: Value = serde_json::from_str(&json).unwrap();
    let obj = data.as_object().unwrap();
    assert_eq!(obj.get("_file").unwrap().as_string().unwrap(), file);
    assert_eq!(obj.get("_line").unwrap().as_u64().unwrap(), line as u64);

    let deserialized_gelf: Gelf = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized_gelf, gelf);
    println!("{:?}", obj);
}

#[cfg(test)]
mod tests {
    use log;

    use super::*;

    #[test]
    fn test_it_works() {
        assert!(init("192.168.1.1", log::LogLevel::Debug).is_ok());
    }

}
<|endoftext|>


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

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

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

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

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


<commit_before>///
/// A basic macro to ease creation and management
/// of Hooks
///
#[macro_export]
macro_rules! hook {
    ($hook_name:expr, $fn_name:ident) => {
        $crate::Hook {
            name: $hook_name.to_string(),
            callback: $fn_name,
        }
    }
}

#[cfg(test)]
mod tests{
    use super::super::Hook;
    fn cb() -> Result<(),String> {
        Ok(())
    }
    #[test]
    fn it_makes_a_hook_correctly() {
        let h1 = hook!("test", cb);
        let h2 = Hook {
            name: "test".to_string(),
            callback: cb,
        };
        assert_eq!(h1, h2);
    }
}<commit_msg>make macro syntax hook!(test cb);<commit_after>///
/// A basic macro to ease creation and management
/// of Hooks
///
#[macro_export]
macro_rules! hook {
    ($hook_name:ident $fn_name:ident) => {
        $crate::Hook {
            name: stringify!($hook_name).to_string(),
            callback: $fn_name,
        }
    }
}

#[cfg(test)]
mod tests{
    use super::super::Hook;
    fn cb() -> Result<(),String> {
        Ok(())
    }
    #[test]
    fn it_makes_a_hook_correctly() {
        let h1 = hook!(test cb);
        let h2 = Hook {
            name: "test".to_string(),
            callback: cb,
        };
        assert_eq!(h1, h2);
    }
}<|endoftext|>


<commit_before>#[macro_export]
macro_rules! rotor_compose {
    /* TODO(tailhook) make and check generic combinators
    (pub enum $name:ident { $($x:ident ($y:ty),)* }) => {
        pub enum $name { $($x ($y),)* }
        rotor_compose!(@machine $name C [] $($x($y),)*);
    };
    (enum $name:ident { $($x:ident ($y:ty),)* }) => {
        enum $name { $($x ($y),)* }
        rotor_compose!(@machine $name $($x($y),)*);
    };
    */
    (pub enum $name:ident/$cname:ident <$context_type:ident>
        { $($x:ident ($y:ty),)* })
    => {
        pub enum $name { $($x ($y),)* }
        rotor_compose!(@machine $name/$cname
            $context_type [] $($x($y),)*);
    };
    (enum $name:ident/$cname:ident <$context_type:ident>
        { $($x:ident ($y:ty),)* })
    => {
        enum $name { $($x ($y),)* }
        rotor_compose!(@machine $name/$cname
            $context_type [] $($x($y),)*);
    };
    (@machine $name:ident/$cname:ident $ctx_typ:ident
        [ $(<$ctx_name:ident $(: $ctx_bound:ident)*>)* ]
        $($iname:ident ($itype:ty),)*)
    => {
        enum $cname {
            $( $iname (<$itype as Machine>::Seed), )*
        }
        impl $( <$ctx_name:$ctx_bound> )* $crate::Machine for $name {
            type Context = $ctx_typ;
            type Seed = $cname;
            fn create(seed: $cname, scope: &mut $crate::Scope<$ctx_typ>)
                -> Result<Self, Box<::std::error::Error>>
            {
                match seed {
                    $( $cname::$iname (x)
                        => $crate::Machine::create(x, scope).map($name::$iname),
                    )*
                }
            }
            fn ready(self, events: EventSet,
                scope: &mut $crate::Scope<$ctx_typ>)
                -> $crate::Response<Self, Self::Seed>
            {
                match self {
                    $(
                        $name::$iname(m) => {
                            m.ready(events, scope)
                                .map($name::$iname, $cname::$iname)
                        }
                    )*
                }
            }
            fn spawned(self, scope: &mut $crate::Scope<$ctx_typ>)
                -> $crate::Response<Self, Self::Seed>
            {
                match self {
                    $(
                        $name::$iname(m) => {
                            m.spawned(scope)
                                .map($name::$iname, $cname::$iname)
                        }
                    )*
                }
            }
            fn timeout(self, scope: &mut $crate::Scope<$ctx_typ>)
                -> $crate::Response<Self, Self::Seed>
            {
                match self {
                    $(
                        $name::$iname(m) => {
                            m.timeout(scope)
                                .map($name::$iname, $cname::$iname)
                        }
                    )*
                }
            }
            fn wakeup(self, scope: &mut $crate::Scope<$ctx_typ>)
                -> $crate::Response<Self, Self::Seed>
            {
                match self {
                    $(
                        $name::$iname(m) => {
                            m.wakeup(scope)
                                .map($name::$iname, $cname::$iname)
                        }
                    )*
                }
            }
        }

    }
}
<commit_msg>Fix namespaces in rotor_compose macro<commit_after>#[macro_export]
macro_rules! rotor_compose {
    /* TODO(tailhook) make and check generic combinators
    (pub enum $name:ident { $($x:ident ($y:ty),)* }) => {
        pub enum $name { $($x ($y),)* }
        rotor_compose!(@machine $name C [] $($x($y),)*);
    };
    (enum $name:ident { $($x:ident ($y:ty),)* }) => {
        enum $name { $($x ($y),)* }
        rotor_compose!(@machine $name $($x($y),)*);
    };
    */
    (pub enum $name:ident/$cname:ident <$context_type:ident>
        { $($x:ident ($y:ty),)* })
    => {
        pub enum $name { $($x ($y),)* }
        rotor_compose!(@machine $name/$cname
            $context_type [] $($x($y),)*);
    };
    (enum $name:ident/$cname:ident <$context_type:ident>
        { $($x:ident ($y:ty),)* })
    => {
        enum $name { $($x ($y),)* }
        rotor_compose!(@machine $name/$cname
            $context_type [] $($x($y),)*);
    };
    (@machine $name:ident/$cname:ident $ctx_typ:ident
        [ $(<$ctx_name:ident $(: $ctx_bound:ident)*>)* ]
        $($iname:ident ($itype:ty),)*)
    => {
        enum $cname {
            $( $iname (<$itype as $crate::Machine>::Seed), )*
        }
        impl $( <$ctx_name:$ctx_bound> )* $crate::Machine for $name {
            type Context = $ctx_typ;
            type Seed = $cname;
            fn create(seed: $cname, scope: &mut $crate::Scope<$ctx_typ>)
                -> Result<Self, Box<::std::error::Error>>
            {
                match seed {
                    $( $cname::$iname (x)
                        => $crate::Machine::create(x, scope).map($name::$iname),
                    )*
                }
            }
            fn ready(self, events: $crate::EventSet,
                scope: &mut $crate::Scope<$ctx_typ>)
                -> $crate::Response<Self, Self::Seed>
            {
                match self {
                    $(
                        $name::$iname(m) => {
                            m.ready(events, scope)
                                .map($name::$iname, $cname::$iname)
                        }
                    )*
                }
            }
            fn spawned(self, scope: &mut $crate::Scope<$ctx_typ>)
                -> $crate::Response<Self, Self::Seed>
            {
                match self {
                    $(
                        $name::$iname(m) => {
                            m.spawned(scope)
                                .map($name::$iname, $cname::$iname)
                        }
                    )*
                }
            }
            fn timeout(self, scope: &mut $crate::Scope<$ctx_typ>)
                -> $crate::Response<Self, Self::Seed>
            {
                match self {
                    $(
                        $name::$iname(m) => {
                            m.timeout(scope)
                                .map($name::$iname, $cname::$iname)
                        }
                    )*
                }
            }
            fn wakeup(self, scope: &mut $crate::Scope<$ctx_typ>)
                -> $crate::Response<Self, Self::Seed>
            {
                match self {
                    $(
                        $name::$iname(m) => {
                            m.wakeup(scope)
                                .map($name::$iname, $cname::$iname)
                        }
                    )*
                }
            }
        }

    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use libc::c_int;
use types::{
    Layout,
    Symmetry,
    Transpose,
};

pub trait Matrix<T> {
    fn rows(&self) -> c_int;
    fn cols(&self) -> c_int;
    fn layout(&self) -> Layout { Layout::RowMajor }
    fn transpose(&self) -> Transpose { Transpose::None }
    fn as_ptr(&self) -> *const T;
    fn as_mut_ptr(&mut self) -> *mut T;
}

pub trait BandMatrix<T>: Matrix<T> {
    fn sub_diagonals(&self) -> c_int;
    fn sup_diagonals(&self) -> c_int;
}

pub trait TridiagonalMatrix<T>: Matrix<T> {
    fn as_ptrs(&self) -> (*const T, *const T, *const T);
    fn as_mut_ptrs(&self) -> (*mut T, *mut T, *mut T);
}

pub trait SymmetricMatrix<T>: Matrix<T> {
    fn symmetry(&self) -> Symmetry;
}

#[cfg(test)]
pub mod tests {
    use libc::c_int;
    use matrix::Matrix;

    impl<T> Matrix<T> for (c_int, c_int, Vec<T>) {
        fn rows(&self) -> c_int {
            self.0
        }

        fn cols(&self) -> c_int {
            self.1
        }

        fn as_ptr(&self) -> *const T {
            self.2[..].as_ptr()
        }

        fn as_mut_ptr(&mut self) -> *mut T {
            (&mut self.2[..]).as_mut_ptr()
        }
    }
}
<commit_msg>Remove layout from Matrix type<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use libc::c_int;
use types::{
    Symmetry,
    Transpose,
};

pub trait Matrix<T> {
    fn rows(&self) -> c_int;
    fn cols(&self) -> c_int;
    fn transpose(&self) -> Transpose { Transpose::None }
    fn as_ptr(&self) -> *const T;
    fn as_mut_ptr(&mut self) -> *mut T;
}

pub trait BandMatrix<T>: Matrix<T> {
    fn sub_diagonals(&self) -> c_int;
    fn sup_diagonals(&self) -> c_int;
}

pub trait TridiagonalMatrix<T>: Matrix<T> {
    fn as_ptrs(&self) -> (*const T, *const T, *const T);
    fn as_mut_ptrs(&self) -> (*mut T, *mut T, *mut T);
}

pub trait SymmetricMatrix<T>: Matrix<T> {
    fn symmetry(&self) -> Symmetry;
}

#[cfg(test)]
pub mod tests {
    use libc::c_int;
    use matrix::Matrix;

    impl<T> Matrix<T> for (c_int, c_int, Vec<T>) {
        fn rows(&self) -> c_int {
            self.0
        }

        fn cols(&self) -> c_int {
            self.1
        }

        fn as_ptr(&self) -> *const T {
            self.2[..].as_ptr()
        }

        fn as_mut_ptr(&mut self) -> *mut T {
            (&mut self.2[..]).as_mut_ptr()
        }
    }
}
<|endoftext|>


<commit_before>use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::io::{Result, Error, ErrorKind, Read, Write};
use std::mem::size_of;

/// A message that can be encoded and decoded according to the LCM protocol.
pub trait Message {
    /// Encodes a message into a buffer, with the message hash at the beginning.
    fn encode_with_hash(&self) -> Result<Vec<u8>> where Self: Sized {
        let hash = Self::hash();
        let size = hash.size() + self.size();
        let mut buffer = Vec::with_capacity(size);
        hash.encode(&mut buffer)?;
        self.encode(&mut buffer)?;
        Ok(buffer)
    }

    /// Decodes a message from a buffer,
    /// and also checks that the hash at the beginning is correct.
    fn decode_with_hash(mut buffer: &mut Read) -> Result<Self>
        where Self: Sized
    {
        let hash: u64 = Message::decode(&mut buffer)?;
        if hash != Self::hash() {
            return Err(Error::new(ErrorKind::Other, "Invalid hash"));
        }
        Message::decode(buffer)
    }

    /// Returns the message hash for this type.
    /// Returns `0` for all primitive types.
    /// Generated `Lcm` types should implement this function.
    fn hash() -> u64 where Self: Sized {
        0
    }

    /// Encodes a message into a buffer.
    /// `Lcm` uses a `Vec<u8>` with its capacity set to the value returned by [`size()`].
    fn encode(&self, buffer: &mut Write) -> Result<()>;

    /// Decodes a message from a buffer.
    fn decode(buffer: &mut Read) -> Result<Self> where Self: Sized;

    /// Returns the number of bytes this message is expected to take when encoded.
    fn size(&self) -> usize;
}

impl Message for bool {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let value: i8 = match *self {
            true => 1,
            false => 0,
        };
        value.encode(buffer)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        let value = buffer.read_i8()?;
        match value {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(Error::new(ErrorKind::InvalidData,
                                "Booleans should be encoded as 0 or 1"))
        }
    }

    fn size(&self) -> usize {
        size_of::<i8>()
    }
}

impl Message for u8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u8(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_u8()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i8(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i8()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i16 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i16::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i32::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for u64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u64::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_u64::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i64::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f32::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_f32::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f64::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_f64::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for String {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let len: i32 = self.len() as i32 + 1;
        len.encode(buffer)?;
        for &b in self.as_bytes() {
            b.encode(buffer)?;
        }
        (0 as u8).encode(buffer)?;
        Ok(())
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        let len = buffer.read_i32::<BigEndian>()? - 1;
        let mut buf = Vec::with_capacity(len as usize);
        for _ in 0..len {
            buf.push(u8::decode(buffer)?)
        }
        let result = String::from_utf8(buf).map_err(|e| Error::new(ErrorKind::Other, e))?;
        match buffer.read_u8() {
            Ok(0) => Ok(result),
            Ok(_) => Err(Error::new(ErrorKind::InvalidData, "Expected null terminator")),
            Err(e) => Err(e),
        }
    }

    fn size(&self) -> usize {
        size_of::<i32>() + self.len() + 1
    }
}
<commit_msg>Change hash values of primitives<commit_after>use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use std::io::{Result, Error, ErrorKind, Read, Write};
use std::mem::size_of;

/// A message that can be encoded and decoded according to the LCM protocol.
pub trait Message {
    /// Encodes a message into a buffer, with the message hash at the beginning.
    fn encode_with_hash(&self) -> Result<Vec<u8>> where Self: Sized {
        let hash = Self::hash();
        let size = hash.size() + self.size();
        let mut buffer = Vec::with_capacity(size);
        hash.encode(&mut buffer)?;
        self.encode(&mut buffer)?;
        Ok(buffer)
    }

    /// Decodes a message from a buffer,
    /// and also checks that the hash at the beginning is correct.
    fn decode_with_hash(mut buffer: &mut Read) -> Result<Self>
        where Self: Sized
    {
        let hash: u64 = Message::decode(&mut buffer)?;
        if hash != Self::hash() {
            return Err(Error::new(ErrorKind::Other, "Invalid hash"));
        }
        Message::decode(buffer)
    }

    /// Returns the message hash for this type.
    /// Hash values are ignored for the primitive types.
    /// Generated `Lcm` types should implement this function.
    fn hash() -> u64 where Self: Sized;

    /// Encodes a message into a buffer.
    /// `Lcm` uses a `Vec<u8>` with its capacity set to the value returned by [`size()`].
    fn encode(&self, buffer: &mut Write) -> Result<()>;

    /// Decodes a message from a buffer.
    fn decode(buffer: &mut Read) -> Result<Self> where Self: Sized;

    /// Returns the number of bytes this message is expected to take when encoded.
    fn size(&self) -> usize;
}

impl Message for bool {
    fn hash() -> u64 {
        0
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let value: i8 = match *self {
            true => 1,
            false => 0,
        };
        value.encode(buffer)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        let value = buffer.read_i8()?;
        match value {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(Error::new(ErrorKind::InvalidData,
                                "Booleans should be encoded as 0 or 1"))
        }
    }

    fn size(&self) -> usize {
        size_of::<i8>()
    }
}

impl Message for u8 {
    fn hash() -> u64 {
        1 << 0
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u8(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_u8()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i8 {
    fn hash() -> u64 {
        1 << 1
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i8(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i8()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i16 {
    fn hash() -> u64 {
        1 << 2
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i16::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i32 {
    fn hash() -> u64 {
        1 << 3
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i32::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for u64 {
    fn hash() -> u64 {
        1 << 4
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u64::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_u64::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i64 {
    fn hash() -> u64 {
        1 << 5
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i64::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f32 {
    fn hash() -> u64 {
        1 << 6
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f32::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_f32::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f64 {
    fn hash() -> u64 {
        1 << 7
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f64::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_f64::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for String {
    fn hash() -> u64 {
        1 << 8
    }

    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let len: i32 = self.len() as i32 + 1;
        len.encode(buffer)?;
        for &b in self.as_bytes() {
            b.encode(buffer)?;
        }
        (0 as u8).encode(buffer)?;
        Ok(())
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        let len = buffer.read_i32::<BigEndian>()? - 1;
        let mut buf = Vec::with_capacity(len as usize);
        for _ in 0..len {
            buf.push(u8::decode(buffer)?)
        }
        let result = String::from_utf8(buf).map_err(|e| Error::new(ErrorKind::Other, e))?;
        match buffer.read_u8() {
            Ok(0) => Ok(result),
            Ok(_) => Err(Error::new(ErrorKind::InvalidData, "Expected null terminator")),
            Err(e) => Err(e),
        }
    }

    fn size(&self) -> usize {
        size_of::<i32>() + self.len() + 1
    }
}
<|endoftext|>


<commit_before>//! Extensions to `std::process` for Windows.

#![stable(feature = "process_extensions", since = "1.2.0")]

use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
use crate::process;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};

#[stable(feature = "process_extensions", since = "1.2.0")]
impl FromRawHandle for process::Stdio {
    unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio {
        let handle = sys::handle::Handle::new(handle as *mut _);
        let io = sys::process::Stdio::Handle(handle);
        process::Stdio::from_inner(io)
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawHandle for process::Child {
    fn as_raw_handle(&self) -> RawHandle {
        self.as_inner().handle().raw() as *mut _
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawHandle for process::Child {
    fn into_raw_handle(self) -> RawHandle {
        self.into_inner().into_handle().into_raw() as *mut _
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawHandle for process::ChildStdin {
    fn as_raw_handle(&self) -> RawHandle {
        self.as_inner().handle().raw() as *mut _
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawHandle for process::ChildStdout {
    fn as_raw_handle(&self) -> RawHandle {
        self.as_inner().handle().raw() as *mut _
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawHandle for process::ChildStderr {
    fn as_raw_handle(&self) -> RawHandle {
        self.as_inner().handle().raw() as *mut _
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawHandle for process::ChildStdin {
    fn into_raw_handle(self) -> RawHandle {
        self.into_inner().into_handle().into_raw() as *mut _
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawHandle for process::ChildStdout {
    fn into_raw_handle(self) -> RawHandle {
        self.into_inner().into_handle().into_raw() as *mut _
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawHandle for process::ChildStderr {
    fn into_raw_handle(self) -> RawHandle {
        self.into_inner().into_handle().into_raw() as *mut _
    }
}

/// Windows-specific extensions to [`process::ExitStatus`].
#[stable(feature = "exit_status_from", since = "1.12.0")]
pub trait ExitStatusExt {
    /// Creates a new `ExitStatus` from the raw underlying `u32` return value of
    /// a process.
    #[stable(feature = "exit_status_from", since = "1.12.0")]
    fn from_raw(raw: u32) -> Self;
}

#[stable(feature = "exit_status_from", since = "1.12.0")]
impl ExitStatusExt for process::ExitStatus {
    fn from_raw(raw: u32) -> Self {
        process::ExitStatus::from_inner(From::from(raw))
    }
}

/// Windows-specific extensions to the [`process::Command`] builder.
#[stable(feature = "windows_process_extensions", since = "1.16.0")]
pub trait CommandExt {
    /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
    ///
    /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`.
    ///
    /// [1]: https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
    #[stable(feature = "windows_process_extensions", since = "1.16.0")]
    fn creation_flags(&mut self, flags: u32) -> &mut process::Command;
}

#[stable(feature = "windows_process_extensions", since = "1.16.0")]
impl CommandExt for process::Command {
    fn creation_flags(&mut self, flags: u32) -> &mut process::Command {
        self.as_inner_mut().creation_flags(flags);
        self
    }
}
<commit_msg>ExitStatusExt windows: Retrospectively seal this trait<commit_after>//! Extensions to `std::process` for Windows.

#![stable(feature = "process_extensions", since = "1.2.0")]

use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
use crate::process;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};

mod private {
    /// This trait being unreachable from outside the crate
    /// prevents other implementations of the `ExitStatusExt` trait,
    /// which allows potentially adding more trait methods in the future.
    #[stable(feature = "none", since = "1.51.0")]
    pub trait Sealed {}
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl FromRawHandle for process::Stdio {
    unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio {
        let handle = sys::handle::Handle::new(handle as *mut _);
        let io = sys::process::Stdio::Handle(handle);
        process::Stdio::from_inner(io)
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawHandle for process::Child {
    fn as_raw_handle(&self) -> RawHandle {
        self.as_inner().handle().raw() as *mut _
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawHandle for process::Child {
    fn into_raw_handle(self) -> RawHandle {
        self.into_inner().into_handle().into_raw() as *mut _
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawHandle for process::ChildStdin {
    fn as_raw_handle(&self) -> RawHandle {
        self.as_inner().handle().raw() as *mut _
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawHandle for process::ChildStdout {
    fn as_raw_handle(&self) -> RawHandle {
        self.as_inner().handle().raw() as *mut _
    }
}

#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawHandle for process::ChildStderr {
    fn as_raw_handle(&self) -> RawHandle {
        self.as_inner().handle().raw() as *mut _
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawHandle for process::ChildStdin {
    fn into_raw_handle(self) -> RawHandle {
        self.into_inner().into_handle().into_raw() as *mut _
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawHandle for process::ChildStdout {
    fn into_raw_handle(self) -> RawHandle {
        self.into_inner().into_handle().into_raw() as *mut _
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawHandle for process::ChildStderr {
    fn into_raw_handle(self) -> RawHandle {
        self.into_inner().into_handle().into_raw() as *mut _
    }
}

/// Windows-specific extensions to [`process::ExitStatus`].
///
/// This trait is saeled (since Rust 1.51): it cannot be implemented outside the standard library.
/// This is so that future additional methods are not breaking changes.
#[stable(feature = "exit_status_from", since = "1.12.0")]
pub trait ExitStatusExt: private::Sealed {
    /// Creates a new `ExitStatus` from the raw underlying `u32` return value of
    /// a process.
    #[stable(feature = "exit_status_from", since = "1.12.0")]
    fn from_raw(raw: u32) -> Self;
}

#[stable(feature = "exit_status_from", since = "1.12.0")]
impl ExitStatusExt for process::ExitStatus {
    fn from_raw(raw: u32) -> Self {
        process::ExitStatus::from_inner(From::from(raw))
    }
}

#[stable(feature = "none", since = "1.51.0")]
impl private::Sealed for process::ExitStatus {}

/// Windows-specific extensions to the [`process::Command`] builder.
#[stable(feature = "windows_process_extensions", since = "1.16.0")]
pub trait CommandExt {
    /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
    ///
    /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`.
    ///
    /// [1]: https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
    #[stable(feature = "windows_process_extensions", since = "1.16.0")]
    fn creation_flags(&mut self, flags: u32) -> &mut process::Command;
}

#[stable(feature = "windows_process_extensions", since = "1.16.0")]
impl CommandExt for process::Command {
    fn creation_flags(&mut self, flags: u32) -> &mut process::Command {
        self.as_inner_mut().creation_flags(flags);
        self
    }
}
<|endoftext|>