<commit_before>use std::sync::atomic;

extern {
    fn __rmc_action_register(name: *const u8) -> i32;
    fn __rmc_action_close(reg_id: i32) -> i32;
    fn __rmc_edge_register(is_vis: i32, src: *const u8, dst: *const u8) -> i32;
    fn __rmc_push() -> i32;
}

pub fn push() { unsafe { __rmc_push(); } }

pub fn _action_register(name: *const u8) -> i32 {
    unsafe { __rmc_action_register(name) }
}
pub fn _action_close(reg_id: i32) -> i32 {
    unsafe { __rmc_action_close(reg_id) }
}
pub fn _edge_register(is_vis: i32, src: *const u8, dst: *const u8) -> i32 {
    unsafe { __rmc_edge_register(is_vis, src, dst) }
}

#[macro_export]
macro_rules! ident_cstr {
    ($i:ident) => { concat!(stringify!($i), "\0").as_ptr() }
}

#[macro_export]
macro_rules! L {
    ($label:ident, $e:expr) => {{
        let id = $crate::_action_register(ident_cstr!($label));
        let v = $e;
        $crate::_action_close(id);
        v
    }}
}

#[macro_export]
macro_rules! RMC_EDGE {
    ($sort:expr, $src:ident, $dst:ident) => {
        $crate::_edge_register($sort, ident_cstr!($src), ident_cstr!($dst))
    }
}
#[macro_export]
macro_rules! XEDGE {
    ($src:ident, $dst:ident) => { RMC_EDGE!(0, $src, $dst) }
}
#[macro_export]
macro_rules! VEDGE {
    ($src:ident, $dst:ident) => { RMC_EDGE!(1, $src, $dst) }
}

pub static STORE_ORDER: atomic::Ordering = atomic::Ordering::Relaxed;
pub static LOAD_ORDER: atomic::Ordering = atomic::Ordering::Relaxed;
pub static RMW_ORDER: atomic::Ordering = atomic::Ordering::Relaxed;
<commit_msg>Make the wrapper functions as inline(always)<commit_after>use std::sync::atomic;

extern {
    fn __rmc_action_register(name: *const u8) -> i32;
    fn __rmc_action_close(reg_id: i32) -> i32;
    fn __rmc_edge_register(is_vis: i32, src: *const u8, dst: *const u8) -> i32;
    fn __rmc_push() -> i32;
}

#[inline(always)]
pub fn push() { unsafe { __rmc_push(); } }

#[inline(always)]
pub fn _action_register(name: *const u8) -> i32 {
    unsafe { __rmc_action_register(name) }
}
#[inline(always)]
pub fn _action_close(reg_id: i32) -> i32 {
    unsafe { __rmc_action_close(reg_id) }
}
#[inline(always)]
pub fn _edge_register(is_vis: i32, src: *const u8, dst: *const u8) -> i32 {
    unsafe { __rmc_edge_register(is_vis, src, dst) }
}

#[macro_export]
macro_rules! ident_cstr {
    ($i:ident) => { concat!(stringify!($i), "\0").as_ptr() }
}

#[macro_export]
macro_rules! L {
    ($label:ident, $e:expr) => {{
        let id = $crate::_action_register(ident_cstr!($label));
        let v = $e;
        $crate::_action_close(id);
        v
    }}
}

#[macro_export]
macro_rules! RMC_EDGE {
    ($sort:expr, $src:ident, $dst:ident) => {
        $crate::_edge_register($sort, ident_cstr!($src), ident_cstr!($dst))
    }
}
#[macro_export]
macro_rules! XEDGE {
    ($src:ident, $dst:ident) => { RMC_EDGE!(0, $src, $dst) }
}
#[macro_export]
macro_rules! VEDGE {
    ($src:ident, $dst:ident) => { RMC_EDGE!(1, $src, $dst) }
}

pub static STORE_ORDER: atomic::Ordering = atomic::Ordering::Relaxed;
pub static LOAD_ORDER: atomic::Ordering = atomic::Ordering::Relaxed;
pub static RMW_ORDER: atomic::Ordering = atomic::Ordering::Relaxed;
<|endoftext|>


<commit_before>use super::internal::*;
use super::*;
use std::cmp;
use std::iter;
use std::usize;

/// `Interleave` is an iterator that interleaves elements of iterators
/// `i` and `j` in one continuous iterator. This struct is created by
/// the [`interleave()`] method on [`IndexedParallelIterator`]
///
/// [`interleave()`]: trait.IndexedParallelIterator.html#method.interleave
/// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Interleave<I, J>
    where I: IndexedParallelIterator,
          J: IndexedParallelIterator<Item = I::Item>
{
    i: I,
    j: J,
    flag: bool,
}

/// Create a new `Interleave` iterator
///
/// NB: a free fn because it is NOT part of the end-user API.
pub fn new<I, J>(i: I, j: J) -> Interleave<I, J>
    where I: IndexedParallelIterator,
          J: IndexedParallelIterator<Item = I::Item>
{
    let flag = false;
    Interleave { i, j, flag }
}

impl<I, J> ParallelIterator for Interleave<I, J>
    where I: IndexedParallelIterator,
          J: IndexedParallelIterator<Item = I::Item>
{
    type Item = I::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: Consumer<I::Item>
    {
        bridge(self, consumer)
    }

    fn opt_len(&mut self) -> Option<usize> {
        Some(self.len())
    }
}

impl<I, J> IndexedParallelIterator for Interleave<I, J>
    where I: IndexedParallelIterator,
          J: IndexedParallelIterator<Item = I::Item>,
{
    fn drive<C>(self, consumer: C) -> C::Result
        where C: Consumer<Self::Item>
    {
        bridge(self, consumer)
    }

    fn len(&mut self) -> usize {
        self.i.len() + self.j.len()
    }

    fn with_producer<CB>(mut self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        let (i_len, j_len) = (self.i.len(), self.j.len());
        return self.i.with_producer(CallbackI {
            callback: callback,
            i_len: i_len,
            j_len: j_len,
            j: self.j
        });

        struct CallbackI<CB, J> {
            callback: CB,
            i_len: usize,
            j_len: usize,
            j: J
        }

        impl<CB, J> ProducerCallback<J::Item> for CallbackI<CB, J>
            where J: IndexedParallelIterator,
                  CB: ProducerCallback<J::Item>
        {
            type Output = CB::Output;

            fn callback<I>(self, i_producer: I) -> Self::Output
                where I: Producer<Item = J::Item>
            {
                self.j.with_producer(CallbackJ {
                    i_producer: i_producer,
                    i_len: self.i_len,
                    j_len: self.j_len,
                    callback: self.callback
                })
            }
        }

        struct CallbackJ<CB, I> {
            callback: CB,
            i_len: usize,
            j_len: usize,
            i_producer: I
        }

        impl<CB, I> ProducerCallback<I::Item> for CallbackJ<CB, I>
            where I: Producer,
                  CB: ProducerCallback<I::Item>
        {
            type Output = CB::Output;

            fn callback<J>(self, j_producer: J) -> Self::Output
                where J: Producer<Item = I::Item>
            {
                let producer = InterleaveProducer::new(self.i_producer, j_producer, self.i_len, self.j_len, false);
                self.callback.callback(producer)
            }
        }
    }
}

pub struct InterleaveProducer<I, J>
    where I: Producer,
          J: Producer<Item = I::Item>
{
    i: I,
    j: J,
    i_len: usize,
    j_len: usize,
    flag: bool,
}

impl<I, J> InterleaveProducer<I, J>
    where I: Producer,
          J: Producer<Item = I::Item>
{
    fn new(i: I, j: J, i_len: usize, j_len: usize, flag: bool) -> InterleaveProducer<I, J> {
        InterleaveProducer { i, j, i_len, j_len, flag }
    }
}

impl<I, J> Producer for InterleaveProducer<I, J>
    where I: Producer,
          J: Producer<Item = I::Item>
{
    type Item = I::Item;
    type IntoIter = InterleaveSeq<I::IntoIter, J::IntoIter>;

    fn into_iter(self) -> Self::IntoIter {
        InterleaveSeq::new(self.i.into_iter(), self.j.into_iter())
    }

    fn min_len(&self) -> usize {
        cmp::max(self.i.min_len(), self.j.min_len())
    }

    fn max_len(&self) -> usize {
        cmp::min(self.i.max_len(), self.j.max_len())
    }

    fn split_at(self, index: usize) -> (Self, Self) {
        // Switch on state
        let even = index%2 == 0;
        let idx = index >> 1;

        // We know 0 < index <= self.i_len + self.j_len
        // Find a, b satisfying the following conditions:
        // (1) 0 < a <= self.i_len
        // (2) 0 < b <= self.j_len
        // (3) a + b == index
        // assert!(index <= self.i_len + self.j_len);

        let odd_offset = |flag| if flag { 0 } else { 1 };

        // desired split
        let (i_idx, j_idx) = (idx + odd_offset(even || self.flag),
                              idx + odd_offset(even || !self.flag));

        let (i_split, j_split) = if self.i_len >= i_idx && self.j_len >= j_idx {
            (i_idx, j_idx)
        } else if self.i_len >= i_idx {
            // j too short
            (index - self.j_len, self.j_len)
        } else {
            // i too short
            (self.i_len, index - self.i_len)
        };

        let trailing_flag = even == self.flag;
        let (i_left, i_right) = self.i.split_at(i_split);
        let (j_left, j_right) = self.j.split_at(j_split);

        (InterleaveProducer::new(
            i_left,
            j_left,
            i_split,
            j_split,
            self.flag
        ), InterleaveProducer::new(
            i_right,
            j_right,
            self.i_len - i_split,
            self.j_len - j_split,
            trailing_flag
        ))
    }
}

/// Wrapper for Interleave to implement DoubleEndedIterator and
/// ExactSizeIterator
pub struct InterleaveSeq<I, J> {
    i: I,
    j: J,
    flag: bool
}

impl<I, J> InterleaveSeq<I, J> {
    fn new(i: I, j: J) -> InterleaveSeq<I, J>
        where I: DoubleEndedIterator + ExactSizeIterator,
              J: DoubleEndedIterator<Item = I::Item> + ExactSizeIterator<Item = I::Item>
    {
        InterleaveSeq { i: i, j: j, flag: false }
    }
}

impl<I, J> Iterator for InterleaveSeq<I, J>
    where I: Iterator,
          J: Iterator<Item = I::Item>
{
    type Item = I::Item;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.flag = !self.flag;
        if self.flag {
            match self.i.next() {
                None => self.j.next(),
                r => r
            }
        } else {
            match self.j.next() {
                None => self.i.next(),
                r => r
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (ih, jh) = (self.i.size_hint(), self.j.size_hint());
        let min = ih.0.checked_add(jh.0).unwrap_or(usize::MAX);
        let max = match (ih.1, jh.1) {
            (Some(x), Some(y)) => x.checked_add(y),
            _=> None
        };
        (min, max)
    }
}

// The implementation for DoubleEndedIterator requires
// ExactSizeIterator to provide `next_back()`. The last element will
// come from the iterator that runs out last (ie has the most elements
// in it). If the iterators have the same number of elements, then the
// last iterator will provide the last element.
impl<I, J> DoubleEndedIterator for InterleaveSeq<I, J>
    where I: DoubleEndedIterator + ExactSizeIterator,
          J: DoubleEndedIterator<Item = I::Item> + ExactSizeIterator<Item = I::Item>
{
    #[inline]
    fn next_back(&mut self) -> Option<I::Item> {
        if self.i.len() <= self.j.len() {
            self.j.next_back()
        } else {
            self.i.next_back()
        }
    }
}

impl<I, J> ExactSizeIterator for InterleaveSeq<I, J>
    where I: ExactSizeIterator,
          J: ExactSizeIterator<Item = I::Item>
{
    #[inline]
    fn len(&self) -> usize {
        self.i.len() + self.j.len()
    }
}
<commit_msg>interleave: Remove more unused imports<commit_after>use super::internal::*;
use super::*;
use std::usize;

/// `Interleave` is an iterator that interleaves elements of iterators
/// `i` and `j` in one continuous iterator. This struct is created by
/// the [`interleave()`] method on [`IndexedParallelIterator`]
///
/// [`interleave()`]: trait.IndexedParallelIterator.html#method.interleave
/// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Interleave<I, J>
    where I: IndexedParallelIterator,
          J: IndexedParallelIterator<Item = I::Item>
{
    i: I,
    j: J,
    flag: bool,
}

/// Create a new `Interleave` iterator
///
/// NB: a free fn because it is NOT part of the end-user API.
pub fn new<I, J>(i: I, j: J) -> Interleave<I, J>
    where I: IndexedParallelIterator,
          J: IndexedParallelIterator<Item = I::Item>
{
    let flag = false;
    Interleave { i, j, flag }
}

impl<I, J> ParallelIterator for Interleave<I, J>
    where I: IndexedParallelIterator,
          J: IndexedParallelIterator<Item = I::Item>
{
    type Item = I::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: Consumer<I::Item>
    {
        bridge(self, consumer)
    }

    fn opt_len(&mut self) -> Option<usize> {
        Some(self.len())
    }
}

impl<I, J> IndexedParallelIterator for Interleave<I, J>
    where I: IndexedParallelIterator,
          J: IndexedParallelIterator<Item = I::Item>,
{
    fn drive<C>(self, consumer: C) -> C::Result
        where C: Consumer<Self::Item>
    {
        bridge(self, consumer)
    }

    fn len(&mut self) -> usize {
        self.i.len() + self.j.len()
    }

    fn with_producer<CB>(mut self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        let (i_len, j_len) = (self.i.len(), self.j.len());
        return self.i.with_producer(CallbackI {
            callback: callback,
            i_len: i_len,
            j_len: j_len,
            j: self.j
        });

        struct CallbackI<CB, J> {
            callback: CB,
            i_len: usize,
            j_len: usize,
            j: J
        }

        impl<CB, J> ProducerCallback<J::Item> for CallbackI<CB, J>
            where J: IndexedParallelIterator,
                  CB: ProducerCallback<J::Item>
        {
            type Output = CB::Output;

            fn callback<I>(self, i_producer: I) -> Self::Output
                where I: Producer<Item = J::Item>
            {
                self.j.with_producer(CallbackJ {
                    i_producer: i_producer,
                    i_len: self.i_len,
                    j_len: self.j_len,
                    callback: self.callback
                })
            }
        }

        struct CallbackJ<CB, I> {
            callback: CB,
            i_len: usize,
            j_len: usize,
            i_producer: I
        }

        impl<CB, I> ProducerCallback<I::Item> for CallbackJ<CB, I>
            where I: Producer,
                  CB: ProducerCallback<I::Item>
        {
            type Output = CB::Output;

            fn callback<J>(self, j_producer: J) -> Self::Output
                where J: Producer<Item = I::Item>
            {
                let producer = InterleaveProducer::new(self.i_producer, j_producer, self.i_len, self.j_len, false);
                self.callback.callback(producer)
            }
        }
    }
}

pub struct InterleaveProducer<I, J>
    where I: Producer,
          J: Producer<Item = I::Item>
{
    i: I,
    j: J,
    i_len: usize,
    j_len: usize,
    flag: bool,
}

impl<I, J> InterleaveProducer<I, J>
    where I: Producer,
          J: Producer<Item = I::Item>
{
    fn new(i: I, j: J, i_len: usize, j_len: usize, flag: bool) -> InterleaveProducer<I, J> {
        InterleaveProducer { i, j, i_len, j_len, flag }
    }
}

impl<I, J> Producer for InterleaveProducer<I, J>
    where I: Producer,
          J: Producer<Item = I::Item>
{
    type Item = I::Item;
    type IntoIter = InterleaveSeq<I::IntoIter, J::IntoIter>;

    fn into_iter(self) -> Self::IntoIter {
        InterleaveSeq::new(self.i.into_iter(), self.j.into_iter())
    }

    fn min_len(&self) -> usize {
        cmp::max(self.i.min_len(), self.j.min_len())
    }

    fn max_len(&self) -> usize {
        cmp::min(self.i.max_len(), self.j.max_len())
    }

    fn split_at(self, index: usize) -> (Self, Self) {
        // Switch on state
        let even = index%2 == 0;
        let idx = index >> 1;

        // We know 0 < index <= self.i_len + self.j_len
        // Find a, b satisfying the following conditions:
        // (1) 0 < a <= self.i_len
        // (2) 0 < b <= self.j_len
        // (3) a + b == index
        // assert!(index <= self.i_len + self.j_len);

        let odd_offset = |flag| if flag { 0 } else { 1 };

        // desired split
        let (i_idx, j_idx) = (idx + odd_offset(even || self.flag),
                              idx + odd_offset(even || !self.flag));

        let (i_split, j_split) = if self.i_len >= i_idx && self.j_len >= j_idx {
            (i_idx, j_idx)
        } else if self.i_len >= i_idx {
            // j too short
            (index - self.j_len, self.j_len)
        } else {
            // i too short
            (self.i_len, index - self.i_len)
        };

        let trailing_flag = even == self.flag;
        let (i_left, i_right) = self.i.split_at(i_split);
        let (j_left, j_right) = self.j.split_at(j_split);

        (InterleaveProducer::new(
            i_left,
            j_left,
            i_split,
            j_split,
            self.flag
        ), InterleaveProducer::new(
            i_right,
            j_right,
            self.i_len - i_split,
            self.j_len - j_split,
            trailing_flag
        ))
    }
}

/// Wrapper for Interleave to implement DoubleEndedIterator and
/// ExactSizeIterator
pub struct InterleaveSeq<I, J> {
    i: I,
    j: J,
    flag: bool
}

impl<I, J> InterleaveSeq<I, J> {
    fn new(i: I, j: J) -> InterleaveSeq<I, J>
        where I: DoubleEndedIterator + ExactSizeIterator,
              J: DoubleEndedIterator<Item = I::Item> + ExactSizeIterator<Item = I::Item>
    {
        InterleaveSeq { i: i, j: j, flag: false }
    }
}

impl<I, J> Iterator for InterleaveSeq<I, J>
    where I: Iterator,
          J: Iterator<Item = I::Item>
{
    type Item = I::Item;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.flag = !self.flag;
        if self.flag {
            match self.i.next() {
                None => self.j.next(),
                r => r
            }
        } else {
            match self.j.next() {
                None => self.i.next(),
                r => r
            }
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (ih, jh) = (self.i.size_hint(), self.j.size_hint());
        let min = ih.0.checked_add(jh.0).unwrap_or(usize::MAX);
        let max = match (ih.1, jh.1) {
            (Some(x), Some(y)) => x.checked_add(y),
            _=> None
        };
        (min, max)
    }
}

// The implementation for DoubleEndedIterator requires
// ExactSizeIterator to provide `next_back()`. The last element will
// come from the iterator that runs out last (ie has the most elements
// in it). If the iterators have the same number of elements, then the
// last iterator will provide the last element.
impl<I, J> DoubleEndedIterator for InterleaveSeq<I, J>
    where I: DoubleEndedIterator + ExactSizeIterator,
          J: DoubleEndedIterator<Item = I::Item> + ExactSizeIterator<Item = I::Item>
{
    #[inline]
    fn next_back(&mut self) -> Option<I::Item> {
        if self.i.len() <= self.j.len() {
            self.j.next_back()
        } else {
            self.i.next_back()
        }
    }
}

impl<I, J> ExactSizeIterator for InterleaveSeq<I, J>
    where I: ExactSizeIterator,
          J: ExactSizeIterator<Item = I::Item>
{
    #[inline]
    fn len(&self) -> usize {
        self.i.len() + self.j.len()
    }
}
<|endoftext|>


<commit_before>
#[macro_use]
mod tryopt;
mod stringerror;

use std::net::UdpSocket;
use std::string::String;
use std::env;

extern crate tinyosc;
use tinyosc as osc;

use std::fmt::format;

fn main() {

  match rmain() {
    Ok(s) => println!("ok: {}", s),
    Err(e) => println!("error: {} ", e),
    }
}

fn rmain() -> Result<String, Box<std::error::Error> > {
  let args = env::args();
  let mut iter = args.skip(1); // skip the program name

  let syntax = "syntax: \n echotest <recvip:port> <sendip:port>";

  let recvip = try_opt_resbox!(iter.next(), syntax);
  let sendip = try_opt_resbox!(iter.next(), syntax);

  let recvsocket = try!(UdpSocket::bind(&recvip[..]));
  // for sending, bind to this.  if we bind to localhost, we can't
  // send messages to other machines.  for that reason, don't reuse the
  // recvsocket for sending.
  let sendsocket = try!(UdpSocket::bind("0.0.0.0:0"));
  let mut buf = [0; 100];
  println!("echotest");

  loop {
    let (amt, _) = try!(recvsocket.recv_from(&mut buf));

    println!("length: {}", amt);
    let inmsg = match osc::Message::deserialize(&buf[.. amt]) {
       Ok(m) => m,
       Err(e) => return Err(stringerror::string_box_err(
                 &format(format_args!("OSC deserialize error {:?}", e)))),
      };

    println!("message recieved {} {:?}", inmsg.path, inmsg.arguments );

    match inmsg {
      osc::Message { path: ref inpath, arguments: ref args } => {

        if &inpath[0..2] == "hs"
          {
            // look for a "location" update, ie
            // an arg "location" followed by a float.
            let mut arg_iter = args.into_iter();
            let mut arg = arg_iter.next();

            while arg.is_some()
            {
              match arg
              {
              Some(&osc::Argument::s("location")) => {
                arg = arg_iter.next();
                match arg {
                  Some(&osc::Argument::f(loc)) => {
                    let outpath = format(format_args!("hs{}", &inpath[2..]));
                    // let outpath = format(format_args!("lb{}", &inpath[2..]));
                    let labtext = format(format_args!("{}", loc));
                    let mut arghs = Vec::new();
                    // arghs.push(osc::Argument::f(b * 100.0 - 100.0));
                    arghs.push(osc::Argument::s("label"));
                    arghs.push(osc::Argument::s(&labtext));
                    let outmsg = osc::Message { path: &outpath, arguments: arghs };
                    match outmsg.serialize() {
                      Ok(v) => {
                        println!("sending {} {:?}", outmsg.path, outmsg.arguments );
                        sendsocket.send_to(&v, &sendip[..]);
                      },
                      Err(e) => { println!("error: {:?}", e) },
                    }
                    break;
                    },
                  _ => {
                    continue;
                  }
                }
              }
              _ => {
                arg = arg_iter.next();
                  continue;
              }
            }
          }
          Ok(0)
          }
        else if &inpath[0..1] == "b"
          {
            // for any kind of button message, update the label.
            // amounts to update the label to the last pressed (or released) button.
            match &args[0] {
              &osc::Argument::s(_) => {
                  let outpath = "lb3";
                  let mut arghs = Vec::new();
                  arghs.push(osc::Argument::s("label"));
                  arghs.push(osc::Argument::s(&inpath));
                  let outmsg = osc::Message { path: &outpath, arguments: arghs };
                  match outmsg.serialize() {
                    Ok(v) => {
                      println!("sending {} {:?}", outmsg.path, outmsg.arguments );
              			  sendsocket.send_to(&v, &sendip[..])
                    },
                    Err(e) => return Err(Box::new(e)),
                  }
                },
              _ => {
                println!("ignore args: {:?}", args);
                // return Err(Error::new(ErrorKind::Other, "unexpected osc args!"));
                Ok(0)
              },
            }
          }
        else
          {
             println!("ignore args 2: {:?}", args);
             // println!("ignore");
             Ok(0)
          }
        },
      };
  };

  // drop(socket); // close the socket
  // Ok(String::from("meh"))
}

<commit_msg>handle send error<commit_after>
#[macro_use]
mod tryopt;
mod stringerror;

use std::net::UdpSocket;
use std::string::String;
use std::env;

extern crate tinyosc;
use tinyosc as osc;

use std::fmt::format;

fn main() {

  match rmain() {
    Ok(s) => println!("ok: {}", s),
    Err(e) => println!("error: {} ", e),
    }
}

fn rmain() -> Result<String, Box<std::error::Error> > {
  let args = env::args();
  let mut iter = args.skip(1); // skip the program name

  let syntax = "syntax: \n echotest <recvip:port> <sendip:port>";

  let recvip = try_opt_resbox!(iter.next(), syntax);
  let sendip = try_opt_resbox!(iter.next(), syntax);

  let recvsocket = try!(UdpSocket::bind(&recvip[..]));
  // for sending, bind to this.  if we bind to localhost, we can't
  // send messages to other machines.  for that reason, don't reuse the
  // recvsocket for sending.
  let sendsocket = try!(UdpSocket::bind("0.0.0.0:0"));
  let mut buf = [0; 100];
  println!("echotest");

  loop {
    let (amt, _) = try!(recvsocket.recv_from(&mut buf));

    println!("length: {}", amt);
    let inmsg = match osc::Message::deserialize(&buf[.. amt]) {
       Ok(m) => m,
       Err(e) => return Err(stringerror::string_box_err(
                 &format(format_args!("OSC deserialize error {:?}", e)))),
      };

    println!("message recieved {} {:?}", inmsg.path, inmsg.arguments );

    match inmsg {
      osc::Message { path: ref inpath, arguments: ref args } => {

        if &inpath[0..2] == "hs"
          {
            // look for a "location" update, ie
            // an arg "location" followed by a float.
            let mut arg_iter = args.into_iter();
            let mut arg = arg_iter.next();

            while arg.is_some()
            {
              match arg
              {
              Some(&osc::Argument::s("location")) => {
                arg = arg_iter.next();
                match arg {
                  Some(&osc::Argument::f(loc)) => {
                    let outpath = format(format_args!("hs{}", &inpath[2..]));
                    // let outpath = format(format_args!("lb{}", &inpath[2..]));
                    let labtext = format(format_args!("{}", loc));
                    let mut arghs = Vec::new();
                    // arghs.push(osc::Argument::f(b * 100.0 - 100.0));
                    arghs.push(osc::Argument::s("label"));
                    arghs.push(osc::Argument::s(&labtext));
                    let outmsg = osc::Message { path: &outpath, arguments: arghs };
                    match outmsg.serialize() {
                      Ok(v) => {
                        println!("sending {} {:?}", outmsg.path, outmsg.arguments );
                        match sendsocket.send_to(&v, &sendip[..]) {
                          Ok(_) => (),
                          Err(e) => println!("error sending osc message: {:?}", e),
                          }
                      },
                      Err(e) => { println!("error: {:?}", e) },
                    }
                    break;
                    },
                  _ => {
                    continue;
                  }
                }
              }
              _ => {
                arg = arg_iter.next();
                  continue;
              }
            }
          }
          Ok(0)
          }
        else if &inpath[0..1] == "b"
          {
            // for any kind of button message, update the label.
            // amounts to update the label to the last pressed (or released) button.
            match &args[0] {
              &osc::Argument::s(_) => {
                  let outpath = "lb3";
                  let mut arghs = Vec::new();
                  arghs.push(osc::Argument::s("label"));
                  arghs.push(osc::Argument::s(&inpath));
                  let outmsg = osc::Message { path: &outpath, arguments: arghs };
                  match outmsg.serialize() {
                    Ok(v) => {
                      println!("sending {} {:?}", outmsg.path, outmsg.arguments );
              			  sendsocket.send_to(&v, &sendip[..])
                    },
                    Err(e) => return Err(Box::new(e)),
                  }
                },
              _ => {
                println!("ignore args: {:?}", args);
                // return Err(Error::new(ErrorKind::Other, "unexpected osc args!"));
                Ok(0)
              },
            }
          }
        else
          {
             println!("ignore args 2: {:?}", args);
             // println!("ignore");
             Ok(0)
          }
        },
      };
  };

  // drop(socket); // close the socket
  // Ok(String::from("meh"))
}

<|endoftext|>


<commit_before>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;
pub use self::recursive::*;

use addr::{PhysAddr, VirtAddr};
use core::ops::{Add, AddAssign, Sub, SubAssign};
use ux::*;

mod page_table;
mod recursive;

/// The default page size on x86_64.
pub const PAGE_SIZE: u16 = 4096;

/// A virtual 4kB page.
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Page {
    number: u64,
}

impl Page {
    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Page {
        Page {
            number: address.as_u64() / u64::from(PAGE_SIZE),
        }
    }

    pub fn from_page_table_indices(p4_index: u9, p3_index: u9, p2_index: u9, p1_index: u9) -> Page {
        use bit_field::BitField;

        let mut addr = 0;
        addr.set_bits(39..48, u64::from(p4_index));
        addr.set_bits(30..39, u64::from(p3_index));
        addr.set_bits(21..30, u64::from(p2_index));
        addr.set_bits(12..21, u64::from(p1_index));
        Page::containing_address(VirtAddr::new(addr))
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        VirtAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }

    pub fn range(start: Page, end: Page) -> PageRange {
        PageRange { start, end }
    }

    pub fn range_inclusive(start: Page, end: Page) -> PageRangeInclusive {
        PageRangeInclusive { start, end }
    }
}

impl Add<u64> for Page {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for Page {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for Page {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for Page {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

impl Sub<Page> for Page {
    type Output = u64;
    fn sub(self, rhs: Page) -> Self::Output {
        self.number.checked_sub(rhs.number).unwrap()
    }
}

pub struct PageRange {
    pub start: Page,
    pub end: Page,
}

impl Iterator for PageRange {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
        if self.start < self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

pub struct PageRangeInclusive {
    pub start: Page,
    pub end: Page,
}

impl Iterator for PageRangeInclusive {
    type Item = Page;

    fn next(&mut self) -> Option<Page> {
        if self.start <= self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

/// A physical 4kB frame.
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct PhysFrame {
    number: u64,
}

impl PhysFrame {
    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> PhysFrame {
        PhysFrame {
            number: address.as_u64() / u64::from(PAGE_SIZE),
        }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        PhysAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    pub fn range(start: PhysFrame, end: PhysFrame) -> PhysFrameRange {
        PhysFrameRange { start, end }
    }

    pub fn range_inclusive(start: PhysFrame, end: PhysFrame) -> PhysFrameRangeInclusive {
        PhysFrameRangeInclusive { start, end }
    }
}

impl Add<u64> for PhysFrame {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for PhysFrame {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for PhysFrame {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for PhysFrame {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

impl Sub<PhysFrame> for PhysFrame {
    type Output = u64;
    fn sub(self, rhs: PhysFrame) -> Self::Output {
        self.number.checked_sub(rhs.number).unwrap()
    }
}

pub struct PhysFrameRange {
    pub start: PhysFrame,
    pub end: PhysFrame,
}

impl Iterator for PhysFrameRange {
    type Item = PhysFrame;

    fn next(&mut self) -> Option<PhysFrame> {
        if self.start < self.end {
            let frame = self.start.clone();
            self.start += 1;
            Some(frame)
        } else {
            None
        }
    }
}

pub struct PhysFrameRangeInclusive {
    pub start: PhysFrame,
    pub end: PhysFrame,
}

impl Iterator for PhysFrameRangeInclusive {
    type Item = PhysFrame;

    fn next(&mut self) -> Option<PhysFrame> {
        if self.start <= self.end {
            let frame = self.start.clone();
            self.start += 1;
            Some(frame)
        } else {
            None
        }
    }
}

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

    #[test]
    pub fn test_page_ranges() {
        let page_size = u64::from(PAGE_SIZE);
        let number = 1000;

        let start_addr = VirtAddr::new(0xdeadbeaf);
        let start = Page::containing_address(start_addr);
        let end = start.clone() + number;

        let mut range = Page::range(start.clone(), end.clone());
        for i in 0..number {
            assert_eq!(
                range.next(),
                Some(Page::containing_address(
                    start_addr + u64::from(PAGE_SIZE) * i
                ))
            );
        }
        assert_eq!(range.next(), None);

        let mut range_inclusive = Page::range_inclusive(start, end);
        for i in 0..=number {
            assert_eq!(
                range_inclusive.next(),
                Some(Page::containing_address(
                    start_addr + u64::from(PAGE_SIZE) * i
                ))
            );
        }
        assert_eq!(range_inclusive.next(), None);
    }
}
<commit_msg>Make Page and Frame generic over page size<commit_after>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;
pub use self::recursive::*;

use {VirtAddr, PhysAddr};
use core::ops::{Add, AddAssign, Sub, SubAssign};
use core::marker::PhantomData;
use core::fmt;
use ux::*;

mod page_table;
mod recursive;

pub trait PageSize: Copy + Eq + PartialOrd + Ord {
    const SIZE: u64;
    const SIZE_AS_DEBUG_STR: &'static str;
}

pub trait NotGiantPageSize: PageSize {}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Size4KB {}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Size2MB {}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Size1GB {}

impl PageSize for Size4KB {
    const SIZE: u64 = 4096;
    const SIZE_AS_DEBUG_STR: &'static str = "4KB";
}
impl NotGiantPageSize for Size4KB {}

impl PageSize for Size2MB {
    const SIZE: u64 = Size4KB::SIZE * 512;
    const SIZE_AS_DEBUG_STR: &'static str = "2MB";
}
impl NotGiantPageSize for Size2MB {}

impl PageSize for Size1GB {
    const SIZE: u64 = Size2MB::SIZE * 512;
    const SIZE_AS_DEBUG_STR: &'static str = "1GB";
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)]
pub struct Page<S: PageSize = Size4KB> {
    start_address: VirtAddr,
    size: PhantomData<S>,
}

impl<S: PageSize> Page<S> {
    /// Returns the page that starts at the given virtual address.
    ///
    /// Returns an error if the address is not correctly aligned (i.e. is not a valid page start).
    pub fn from_start_address(address: VirtAddr) -> Result<Self, ()> {
        if !address.is_aligned(S::SIZE) {
            return Err(());
        }
        Ok(Page::containing_address(address))
    }

    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Self {
        Page {
            start_address: address.align_down(S::SIZE),
            size: PhantomData,
        }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        self.start_address
    }

    /// Returns the size the page (4KB, 2MB or 1GB).
    pub const fn size(&self) -> u64 {
        S::SIZE
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    pub fn range(start: Self, end: Self) -> PageRange<S> {
        PageRange { start, end }
    }

    pub fn range_inclusive(start: Self, end: Self) -> PageRangeInclusive<S> {
        PageRangeInclusive { start, end }
    }
}

impl<S: NotGiantPageSize> Page<S> {
    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }
}

impl Page<Size1GB> {
    pub fn from_page_table_indices_1gb(p4_index: u9, p3_index: u9) -> Self {
        use bit_field::BitField;

        let mut addr = 0;
        addr.set_bits(39..48, u64::from(p4_index));
        addr.set_bits(30..39, u64::from(p3_index));
        Page::containing_address(VirtAddr::new(addr))
    }
}

impl Page<Size2MB> {
    pub fn from_page_table_indices_2mb(p4_index: u9, p3_index: u9, p2_index: u9) -> Self {
        use bit_field::BitField;

        let mut addr = 0;
        addr.set_bits(39..48, u64::from(p4_index));
        addr.set_bits(30..39, u64::from(p3_index));
        addr.set_bits(21..30, u64::from(p2_index));
        Page::containing_address(VirtAddr::new(addr))
    }
}

impl Page<Size4KB> {
    pub fn from_page_table_indices(p4_index: u9, p3_index: u9, p2_index: u9, p1_index: u9) -> Self {
        use bit_field::BitField;

        let mut addr = 0;
        addr.set_bits(39..48, u64::from(p4_index));
        addr.set_bits(30..39, u64::from(p3_index));
        addr.set_bits(21..30, u64::from(p2_index));
        addr.set_bits(12..21, u64::from(p1_index));
        Page::containing_address(VirtAddr::new(addr))
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }
}

impl<S: PageSize> fmt::Debug for Page<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_fmt(format_args!("Page[{}]({:#x})", S::SIZE_AS_DEBUG_STR,
            self.start_address().as_u64()))
    }
}

impl<S: PageSize> Add<u64> for Page<S> {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() + rhs * u64::from(S::SIZE))
    }
}

impl<S: PageSize> AddAssign<u64> for Page<S> {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl<S: PageSize> Sub<u64> for Page<S> {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() - rhs * u64::from(S::SIZE))
    }
}

impl<S: PageSize> SubAssign<u64> for Page<S> {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

impl<S: PageSize> Sub<Self> for Page<S> {
    type Output = u64;
    fn sub(self, rhs: Self) -> Self::Output {
        (self.start_address - rhs.start_address) / S::SIZE
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct PageRange<S: PageSize = Size4KB> {
    pub start: Page<S>,
    pub end: Page<S>,
}

impl<S: PageSize> PageRange<S> {
    pub fn is_empty(&self) -> bool {
        !(self.start < self.end)
    }
}

impl<S: PageSize> Iterator for PageRange<S> {
    type Item = Page<S>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.start < self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

impl PageRange<Size2MB> {
    pub fn as_4kb_page_range(self) -> PageRange<Size4KB> {
        PageRange {
            start: Page::containing_address(self.start.start_address()),
            end: Page::containing_address(self.end.start_address()),
        }
    }
}

impl<S: PageSize> fmt::Debug for PageRange<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("PageRange")
            .field("start", &self.start)
            .field("end", &self.end)
            .finish()
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct PageRangeInclusive<S: PageSize = Size4KB> {
    pub start: Page<S>,
    pub end: Page<S>,
}

impl<S: PageSize> PageRangeInclusive<S> {
    pub fn is_empty(&self) -> bool {
        !(self.start <= self.end)
    }
}

impl<S: PageSize> Iterator for PageRangeInclusive<S> {
    type Item = Page<S>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.start <= self.end {
            let page = self.start.clone();
            self.start += 1;
            Some(page)
        } else {
            None
        }
    }
}

impl<S: PageSize> fmt::Debug for PageRangeInclusive<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("PageRangeInclusive")
            .field("start", &self.start)
            .field("end", &self.end)
            .finish()
    }
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)]
pub struct PhysFrame<S: PageSize = Size4KB> {
    start_address: PhysAddr,
    size: PhantomData<S>,
}

impl<S: PageSize> PhysFrame<S> {
    /// Returns the frame that starts at the given virtual address.
    ///
    /// Returns an error if the address is not correctly aligned (i.e. is not a valid frame start).
    pub fn from_start_address(address: PhysAddr) -> Result<Self, ()> {
        if !address.is_aligned(S::SIZE) {
            return Err(());
        }
        Ok(PhysFrame::containing_address(address))
    }

    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> Self {
        PhysFrame {
            start_address: address.align_down(S::SIZE),
            size: PhantomData,
        }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        self.start_address
    }

    /// Returns the size the frame (4KB, 2MB or 1GB).
    pub fn size(&self) -> u64 {
        S::SIZE
    }

    pub fn range(start: PhysFrame<S>, end: PhysFrame<S>) -> PhysFrameRange<S> {
        PhysFrameRange { start, end }
    }

    pub fn range_inclusive(start: PhysFrame<S>, end: PhysFrame<S>) -> PhysFrameRangeInclusive<S> {
        PhysFrameRangeInclusive { start, end }
    }
}

impl<S: PageSize> fmt::Debug for PhysFrame<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_fmt(format_args!("PhysFrame[{}]({:#x})", S::SIZE_AS_DEBUG_STR,
            self.start_address().as_u64()))
    }
}

impl<S: PageSize> Add<u64> for PhysFrame<S> {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() + rhs * u64::from(S::SIZE))
    }
}

impl<S: PageSize> AddAssign<u64> for PhysFrame<S> {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl<S: PageSize> Sub<u64> for PhysFrame<S> {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() - rhs * u64::from(S::SIZE))
    }
}

impl<S: PageSize> SubAssign<u64> for PhysFrame<S> {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

impl<S: PageSize> Sub<PhysFrame<S>> for PhysFrame<S> {
    type Output = u64;
    fn sub(self, rhs: PhysFrame<S>) -> Self::Output {
        (self.start_address - rhs.start_address) / S::SIZE
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct PhysFrameRange<S: PageSize = Size4KB> {
    pub start: PhysFrame<S>,
    pub end: PhysFrame<S>,
}

impl<S: PageSize> PhysFrameRange<S> {
    pub fn is_empty(&self) -> bool {
        !(self.start < self.end)
    }
}

impl<S: PageSize> Iterator for PhysFrameRange<S> {
    type Item = PhysFrame<S>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.start < self.end {
            let frame = self.start.clone();
            self.start += 1;
            Some(frame)
        } else {
            None
        }
    }
}

impl<S: PageSize> fmt::Debug for PhysFrameRange<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("PhysFrameRange")
            .field("start", &self.start)
            .field("end", &self.end)
            .finish()
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct PhysFrameRangeInclusive<S: PageSize = Size4KB> {
    pub start: PhysFrame<S>,
    pub end: PhysFrame<S>,
}

impl<S: PageSize> PhysFrameRangeInclusive<S> {
    pub fn is_empty(&self) -> bool {
        !(self.start <= self.end)
    }
}

impl<S: PageSize> Iterator for PhysFrameRangeInclusive<S> {
    type Item = PhysFrame<S>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.start <= self.end {
            let frame = self.start.clone();
            self.start += 1;
            Some(frame)
        } else {
            None
        }
    }
}

impl<S: PageSize> fmt::Debug for PhysFrameRangeInclusive<S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("PhysFrameRangeInclusive")
            .field("start", &self.start)
            .field("end", &self.end)
            .finish()
    }
}

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

    #[test]
    pub fn test_page_ranges() {
        let page_size = u64::from(PAGE_SIZE);
        let number = 1000;

        let start_addr = VirtAddr::new(0xdeadbeaf);
        let start = Page::containing_address(start_addr);
        let end = start.clone() + number;

        let mut range = Page::range(start.clone(), end.clone());
        for i in 0..number {
            assert_eq!(
                range.next(),
                Some(Page::containing_address(
                    start_addr + u64::from(PAGE_SIZE) * i
                ))
            );
        }
        assert_eq!(range.next(), None);

        let mut range_inclusive = Page::range_inclusive(start, end);
        for i in 0..=number {
            assert_eq!(
                range_inclusive.next(),
                Some(Page::containing_address(
                    start_addr + u64::from(PAGE_SIZE) * i
                ))
            );
        }
        assert_eq!(range_inclusive.next(), None);
    }
}
<|endoftext|>


<commit_before>//! Instruction Set Architectures.
//!
//! The `isa` module provides a `TargetIsa` trait which provides the behavior specialization needed
//! by the ISA-independent code generator. The sub-modules of this module provide definitions for
//! the instruction sets that Cranelift can target. Each sub-module has it's own implementation of
//! `TargetIsa`.
//!
//! # Constructing a `TargetIsa` instance
//!
//! The target ISA is built from the following information:
//!
//! - The name of the target ISA as a string. Cranelift is a cross-compiler, so the ISA to target
//!   can be selected dynamically. Individual ISAs can be left out when Cranelift is compiled, so a
//!   string is used to identify the proper sub-module.
//! - Values for settings that apply to all ISAs. This is represented by a `settings::Flags`
//!   instance.
//! - Values for ISA-specific settings.
//!
//! The `isa::lookup()` function is the main entry point which returns an `isa::Builder`
//! appropriate for the requested ISA:
//!
//! ```
//! # extern crate cranelift_codegen;
//! # #[macro_use] extern crate target_lexicon;
//! # fn main() {
//! use cranelift_codegen::isa;
//! use cranelift_codegen::settings::{self, Configurable};
//! use std::str::FromStr;
//! use target_lexicon::Triple;
//!
//! let shared_builder = settings::builder();
//! let shared_flags = settings::Flags::new(shared_builder);
//!
//! match isa::lookup(triple!("riscv32")) {
//!     Err(_) => {
//!         // The RISC-V target ISA is not available.
//!     }
//!     Ok(mut isa_builder) => {
//!         isa_builder.set("supports_m", "on");
//!         let isa = isa_builder.finish(shared_flags);
//!     }
//! }
//! # }
//! ```
//!
//! The configured target ISA trait object is a `Box<TargetIsa>` which can be used for multiple
//! concurrent function compilations.

pub use isa::call_conv::CallConv;
pub use isa::constraints::{BranchRange, ConstraintKind, OperandConstraint, RecipeConstraints};
pub use isa::encoding::{base_size, EncInfo, Encoding};
pub use isa::registers::{regs_overlap, RegClass, RegClassIndex, RegInfo, RegUnit};
pub use isa::stack::{StackBase, StackBaseMask, StackRef};

use binemit;
use flowgraph;
use ir;
use isa::enc_tables::Encodings;
use regalloc;
use result::CodegenResult;
use settings;
use settings::SetResult;
use std::boxed::Box;
use std::fmt;
use target_lexicon::{Architecture, PointerWidth, Triple};
use timing;

#[cfg(build_riscv)]
mod riscv;

#[cfg(build_x86)]
mod x86;

#[cfg(build_arm32)]
mod arm32;

#[cfg(build_arm64)]
mod arm64;

mod call_conv;
mod constraints;
mod enc_tables;
mod encoding;
pub mod registers;
mod stack;

/// Returns a builder that can create a corresponding `TargetIsa`
/// or `Err(LookupError::Unsupported)` if not enabled.
macro_rules! isa_builder {
    ($module:ident, $name:ident) => {{
        #[cfg($name)]
        fn $name(triple: Triple) -> Result<Builder, LookupError> {
            Ok($module::isa_builder(triple))
        };
        #[cfg(not($name))]
        fn $name(_triple: Triple) -> Result<Builder, LookupError> {
            Err(LookupError::Unsupported)
        }
        $name
    }};
}

/// Look for a supported ISA with the given `name`.
/// Return a builder that can create a corresponding `TargetIsa`.
pub fn lookup(triple: Triple) -> Result<Builder, LookupError> {
    match triple.architecture {
        Architecture::Riscv32 | Architecture::Riscv64 => isa_builder!(riscv, build_riscv)(triple),
        Architecture::I386 | Architecture::I586 | Architecture::I686 | Architecture::X86_64 => {
            isa_builder!(x86, build_x86)(triple)
        }
        Architecture::Thumbv6m
        | Architecture::Thumbv7em
        | Architecture::Thumbv7m
        | Architecture::Arm
        | Architecture::Armv4t
        | Architecture::Armv5te
        | Architecture::Armv7
        | Architecture::Armv7s => isa_builder!(arm32, build_arm32)(triple),
        Architecture::Aarch64 => isa_builder!(arm64, build_arm64)(triple),
        _ => Err(LookupError::Unsupported),
    }
}

/// Describes reason for target lookup failure
#[derive(Fail, PartialEq, Eq, Copy, Clone, Debug)]
pub enum LookupError {
    /// Support for this target was disabled in the current build.
    #[fail(display = "Support for this target is disabled")]
    SupportDisabled,

    /// Support for this target has not yet been implemented.
    #[fail(display = "Support for this target has not been implemented yet")]
    Unsupported,
}

/// Builder for a `TargetIsa`.
/// Modify the ISA-specific settings before creating the `TargetIsa` trait object with `finish`.
pub struct Builder {
    triple: Triple,
    setup: settings::Builder,
    constructor: fn(Triple, settings::Flags, settings::Builder) -> Box<TargetIsa>,
}

impl Builder {
    /// Combine the ISA-specific settings with the provided ISA-independent settings and allocate a
    /// fully configured `TargetIsa` trait object.
    pub fn finish(self, shared_flags: settings::Flags) -> Box<TargetIsa> {
        (self.constructor)(self.triple, shared_flags, self.setup)
    }
}

impl settings::Configurable for Builder {
    fn set(&mut self, name: &str, value: &str) -> SetResult<()> {
        self.setup.set(name, value)
    }

    fn enable(&mut self, name: &str) -> SetResult<()> {
        self.setup.enable(name)
    }
}

/// After determining that an instruction doesn't have an encoding, how should we proceed to
/// legalize it?
///
/// The `Encodings` iterator returns a legalization function to call.
pub type Legalize =
    fn(ir::Inst, &mut ir::Function, &mut flowgraph::ControlFlowGraph, &TargetIsa) -> bool;

/// This struct provides information that a frontend may need to know about a target to
/// produce Cranelift IR for the target.
#[derive(Clone, Copy)]
pub struct TargetFrontendConfig {
    /// The default calling convention of the target.
    pub default_call_conv: CallConv,

    /// The pointer width of the target.
    pub pointer_width: PointerWidth,
}

impl TargetFrontendConfig {
    /// Get the pointer type of this target.
    pub fn pointer_type(self) -> ir::Type {
        ir::Type::int(u16::from(self.pointer_bits())).unwrap()
    }

    /// Get the width of pointers on this target, in units of bits.
    pub fn pointer_bits(self) -> u8 {
        self.pointer_width.bits()
    }

    /// Get the width of pointers on this target, in units of bytes.
    pub fn pointer_bytes(self) -> u8 {
        self.pointer_width.bytes()
    }
}

/// Methods that are specialized to a target ISA. Implies a Display trait that shows the
/// shared flags, as well as any isa-specific flags.
pub trait TargetIsa: fmt::Display {
    /// Get the name of this ISA.
    fn name(&self) -> &'static str;

    /// Get the target triple that was used to make this trait object.
    fn triple(&self) -> &Triple;

    /// Get the ISA-independent flags that were used to make this trait object.
    fn flags(&self) -> &settings::Flags;

    /// Get the default calling convention of this target.
    fn default_call_conv(&self) -> CallConv {
        CallConv::default_for_triple(self.triple())
    }

    /// Get the pointer type of this ISA.
    fn pointer_type(&self) -> ir::Type {
        ir::Type::int(u16::from(self.pointer_bits())).unwrap()
    }

    /// Get the width of pointers on this ISA.
    fn pointer_width(&self) -> PointerWidth {
        self.triple().pointer_width().unwrap()
    }

    /// Get the width of pointers on this ISA, in units of bits.
    fn pointer_bits(&self) -> u8 {
        self.pointer_width().bits()
    }

    /// Get the width of pointers on this ISA, in units of bytes.
    fn pointer_bytes(&self) -> u8 {
        self.pointer_width().bytes()
    }

    /// Get the information needed by frontends producing Cranelift IR.
    fn frontend_config(&self) -> TargetFrontendConfig {
        TargetFrontendConfig {
            default_call_conv: self.default_call_conv(),
            pointer_width: self.pointer_width(),
        }
    }

    /// Does the CPU implement scalar comparisons using a CPU flags register?
    fn uses_cpu_flags(&self) -> bool {
        false
    }

    /// Does the CPU implement multi-register addressing?
    fn uses_complex_addresses(&self) -> bool {
        false
    }

    /// Get a data structure describing the registers in this ISA.
    fn register_info(&self) -> RegInfo;

    /// Returns an iterator over legal encodings for the instruction.
    fn legal_encodings<'a>(
        &'a self,
        func: &'a ir::Function,
        inst: &'a ir::InstructionData,
        ctrl_typevar: ir::Type,
    ) -> Encodings<'a>;

    /// Encode an instruction after determining it is legal.
    ///
    /// If `inst` can legally be encoded in this ISA, produce the corresponding `Encoding` object.
    /// Otherwise, return `Legalize` action.
    ///
    /// This is also the main entry point for determining if an instruction is legal.
    fn encode(
        &self,
        func: &ir::Function,
        inst: &ir::InstructionData,
        ctrl_typevar: ir::Type,
    ) -> Result<Encoding, Legalize> {
        let mut iter = self.legal_encodings(func, inst, ctrl_typevar);
        iter.next().ok_or_else(|| iter.legalize())
    }

    /// Get a data structure describing the instruction encodings in this ISA.
    fn encoding_info(&self) -> EncInfo;

    /// Legalize a function signature.
    ///
    /// This is used to legalize both the signature of the function being compiled and any called
    /// functions. The signature should be modified by adding `ArgumentLoc` annotations to all
    /// arguments and return values.
    ///
    /// Arguments with types that are not supported by the ABI can be expanded into multiple
    /// arguments:
    ///
    /// - Integer types that are too large to fit in a register can be broken into multiple
    ///   arguments of a smaller integer type.
    /// - Floating point types can be bit-cast to an integer type of the same size, and possible
    ///   broken into smaller integer types.
    /// - Vector types can be bit-cast and broken down into smaller vectors or scalars.
    ///
    /// The legalizer will adapt argument and return values as necessary at all ABI boundaries.
    ///
    /// When this function is called to legalize the signature of the function currently being
    /// compiled, `current` is true. The legalized signature can then also contain special purpose
    /// arguments and return values such as:
    ///
    /// - A `link` argument representing the link registers on RISC architectures that don't push
    ///   the return address on the stack.
    /// - A `link` return value which will receive the value that was passed to the `link`
    ///   argument.
    /// - An `sret` argument can be added if one wasn't present already. This is necessary if the
    ///   signature returns more values than registers are available for returning values.
    /// - An `sret` return value can be added if the ABI requires a function to return its `sret`
    ///   argument in a register.
    ///
    /// Arguments and return values for the caller's frame pointer and other callee-saved registers
    /// should not be added by this function. These arguments are not added until after register
    /// allocation.
    fn legalize_signature(&self, sig: &mut ir::Signature, current: bool);

    /// Get the register class that should be used to represent an ABI argument or return value of
    /// type `ty`. This should be the top-level register class that contains the argument
    /// registers.
    ///
    /// This function can assume that it will only be asked to provide register classes for types
    /// that `legalize_signature()` produces in `ArgumentLoc::Reg` entries.
    fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass;

    /// Get the set of allocatable registers that can be used when compiling `func`.
    ///
    /// This set excludes reserved registers like the stack pointer and other special-purpose
    /// registers.
    fn allocatable_registers(&self, func: &ir::Function) -> regalloc::RegisterSet;

    /// Compute the stack layout and insert prologue and epilogue code into `func`.
    ///
    /// Return an error if the stack frame is too large.
    fn prologue_epilogue(&self, func: &mut ir::Function) -> CodegenResult<()> {
        let _tt = timing::prologue_epilogue();
        // This default implementation is unlikely to be good enough.
        use ir::stackslot::{StackOffset, StackSize};
        use stack_layout::layout_stack;

        let word_size = StackSize::from(self.pointer_bytes());

        // Account for the SpiderMonkey standard prologue pushes.
        if func.signature.call_conv == CallConv::Baldrdash {
            let bytes = StackSize::from(self.flags().baldrdash_prologue_words()) * word_size;
            let mut ss = ir::StackSlotData::new(ir::StackSlotKind::IncomingArg, bytes);
            ss.offset = Some(-(bytes as StackOffset));
            func.stack_slots.push(ss);
        }

        layout_stack(&mut func.stack_slots, word_size)?;
        Ok(())
    }

    /// Emit binary machine code for a single instruction into the `sink` trait object.
    ///
    /// Note that this will call `put*` methods on the `sink` trait object via its vtable which
    /// is not the fastest way of emitting code.
    ///
    /// This function is under the "testing_hooks" feature, and is only suitable for use by
    /// test harnesses. It increases code size, and is inefficient.
    #[cfg(feature = "testing_hooks")]
    fn emit_inst(
        &self,
        func: &ir::Function,
        inst: ir::Inst,
        divert: &mut regalloc::RegDiversions,
        sink: &mut binemit::CodeSink,
    );

    /// Emit a whole function into memory.
    fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut binemit::MemoryCodeSink);
}
<commit_msg>Make TargetIsa thread-safe<commit_after>//! Instruction Set Architectures.
//!
//! The `isa` module provides a `TargetIsa` trait which provides the behavior specialization needed
//! by the ISA-independent code generator. The sub-modules of this module provide definitions for
//! the instruction sets that Cranelift can target. Each sub-module has it's own implementation of
//! `TargetIsa`.
//!
//! # Constructing a `TargetIsa` instance
//!
//! The target ISA is built from the following information:
//!
//! - The name of the target ISA as a string. Cranelift is a cross-compiler, so the ISA to target
//!   can be selected dynamically. Individual ISAs can be left out when Cranelift is compiled, so a
//!   string is used to identify the proper sub-module.
//! - Values for settings that apply to all ISAs. This is represented by a `settings::Flags`
//!   instance.
//! - Values for ISA-specific settings.
//!
//! The `isa::lookup()` function is the main entry point which returns an `isa::Builder`
//! appropriate for the requested ISA:
//!
//! ```
//! # extern crate cranelift_codegen;
//! # #[macro_use] extern crate target_lexicon;
//! # fn main() {
//! use cranelift_codegen::isa;
//! use cranelift_codegen::settings::{self, Configurable};
//! use std::str::FromStr;
//! use target_lexicon::Triple;
//!
//! let shared_builder = settings::builder();
//! let shared_flags = settings::Flags::new(shared_builder);
//!
//! match isa::lookup(triple!("riscv32")) {
//!     Err(_) => {
//!         // The RISC-V target ISA is not available.
//!     }
//!     Ok(mut isa_builder) => {
//!         isa_builder.set("supports_m", "on");
//!         let isa = isa_builder.finish(shared_flags);
//!     }
//! }
//! # }
//! ```
//!
//! The configured target ISA trait object is a `Box<TargetIsa>` which can be used for multiple
//! concurrent function compilations.

pub use isa::call_conv::CallConv;
pub use isa::constraints::{BranchRange, ConstraintKind, OperandConstraint, RecipeConstraints};
pub use isa::encoding::{base_size, EncInfo, Encoding};
pub use isa::registers::{regs_overlap, RegClass, RegClassIndex, RegInfo, RegUnit};
pub use isa::stack::{StackBase, StackBaseMask, StackRef};

use binemit;
use flowgraph;
use ir;
use isa::enc_tables::Encodings;
use regalloc;
use result::CodegenResult;
use settings;
use settings::SetResult;
use std::boxed::Box;
use std::fmt;
use target_lexicon::{Architecture, PointerWidth, Triple};
use timing;

#[cfg(build_riscv)]
mod riscv;

#[cfg(build_x86)]
mod x86;

#[cfg(build_arm32)]
mod arm32;

#[cfg(build_arm64)]
mod arm64;

mod call_conv;
mod constraints;
mod enc_tables;
mod encoding;
pub mod registers;
mod stack;

/// Returns a builder that can create a corresponding `TargetIsa`
/// or `Err(LookupError::Unsupported)` if not enabled.
macro_rules! isa_builder {
    ($module:ident, $name:ident) => {{
        #[cfg($name)]
        fn $name(triple: Triple) -> Result<Builder, LookupError> {
            Ok($module::isa_builder(triple))
        };
        #[cfg(not($name))]
        fn $name(_triple: Triple) -> Result<Builder, LookupError> {
            Err(LookupError::Unsupported)
        }
        $name
    }};
}

/// Look for a supported ISA with the given `name`.
/// Return a builder that can create a corresponding `TargetIsa`.
pub fn lookup(triple: Triple) -> Result<Builder, LookupError> {
    match triple.architecture {
        Architecture::Riscv32 | Architecture::Riscv64 => isa_builder!(riscv, build_riscv)(triple),
        Architecture::I386 | Architecture::I586 | Architecture::I686 | Architecture::X86_64 => {
            isa_builder!(x86, build_x86)(triple)
        }
        Architecture::Thumbv6m
        | Architecture::Thumbv7em
        | Architecture::Thumbv7m
        | Architecture::Arm
        | Architecture::Armv4t
        | Architecture::Armv5te
        | Architecture::Armv7
        | Architecture::Armv7s => isa_builder!(arm32, build_arm32)(triple),
        Architecture::Aarch64 => isa_builder!(arm64, build_arm64)(triple),
        _ => Err(LookupError::Unsupported),
    }
}

/// Describes reason for target lookup failure
#[derive(Fail, PartialEq, Eq, Copy, Clone, Debug)]
pub enum LookupError {
    /// Support for this target was disabled in the current build.
    #[fail(display = "Support for this target is disabled")]
    SupportDisabled,

    /// Support for this target has not yet been implemented.
    #[fail(display = "Support for this target has not been implemented yet")]
    Unsupported,
}

/// Builder for a `TargetIsa`.
/// Modify the ISA-specific settings before creating the `TargetIsa` trait object with `finish`.
pub struct Builder {
    triple: Triple,
    setup: settings::Builder,
    constructor: fn(Triple, settings::Flags, settings::Builder) -> Box<TargetIsa>,
}

impl Builder {
    /// Combine the ISA-specific settings with the provided ISA-independent settings and allocate a
    /// fully configured `TargetIsa` trait object.
    pub fn finish(self, shared_flags: settings::Flags) -> Box<TargetIsa> {
        (self.constructor)(self.triple, shared_flags, self.setup)
    }
}

impl settings::Configurable for Builder {
    fn set(&mut self, name: &str, value: &str) -> SetResult<()> {
        self.setup.set(name, value)
    }

    fn enable(&mut self, name: &str) -> SetResult<()> {
        self.setup.enable(name)
    }
}

/// After determining that an instruction doesn't have an encoding, how should we proceed to
/// legalize it?
///
/// The `Encodings` iterator returns a legalization function to call.
pub type Legalize =
    fn(ir::Inst, &mut ir::Function, &mut flowgraph::ControlFlowGraph, &TargetIsa) -> bool;

/// This struct provides information that a frontend may need to know about a target to
/// produce Cranelift IR for the target.
#[derive(Clone, Copy)]
pub struct TargetFrontendConfig {
    /// The default calling convention of the target.
    pub default_call_conv: CallConv,

    /// The pointer width of the target.
    pub pointer_width: PointerWidth,
}

impl TargetFrontendConfig {
    /// Get the pointer type of this target.
    pub fn pointer_type(self) -> ir::Type {
        ir::Type::int(u16::from(self.pointer_bits())).unwrap()
    }

    /// Get the width of pointers on this target, in units of bits.
    pub fn pointer_bits(self) -> u8 {
        self.pointer_width.bits()
    }

    /// Get the width of pointers on this target, in units of bytes.
    pub fn pointer_bytes(self) -> u8 {
        self.pointer_width.bytes()
    }
}

/// Methods that are specialized to a target ISA. Implies a Display trait that shows the
/// shared flags, as well as any isa-specific flags.
pub trait TargetIsa: fmt::Display + Sync {
    /// Get the name of this ISA.
    fn name(&self) -> &'static str;

    /// Get the target triple that was used to make this trait object.
    fn triple(&self) -> &Triple;

    /// Get the ISA-independent flags that were used to make this trait object.
    fn flags(&self) -> &settings::Flags;

    /// Get the default calling convention of this target.
    fn default_call_conv(&self) -> CallConv {
        CallConv::default_for_triple(self.triple())
    }

    /// Get the pointer type of this ISA.
    fn pointer_type(&self) -> ir::Type {
        ir::Type::int(u16::from(self.pointer_bits())).unwrap()
    }

    /// Get the width of pointers on this ISA.
    fn pointer_width(&self) -> PointerWidth {
        self.triple().pointer_width().unwrap()
    }

    /// Get the width of pointers on this ISA, in units of bits.
    fn pointer_bits(&self) -> u8 {
        self.pointer_width().bits()
    }

    /// Get the width of pointers on this ISA, in units of bytes.
    fn pointer_bytes(&self) -> u8 {
        self.pointer_width().bytes()
    }

    /// Get the information needed by frontends producing Cranelift IR.
    fn frontend_config(&self) -> TargetFrontendConfig {
        TargetFrontendConfig {
            default_call_conv: self.default_call_conv(),
            pointer_width: self.pointer_width(),
        }
    }

    /// Does the CPU implement scalar comparisons using a CPU flags register?
    fn uses_cpu_flags(&self) -> bool {
        false
    }

    /// Does the CPU implement multi-register addressing?
    fn uses_complex_addresses(&self) -> bool {
        false
    }

    /// Get a data structure describing the registers in this ISA.
    fn register_info(&self) -> RegInfo;

    /// Returns an iterator over legal encodings for the instruction.
    fn legal_encodings<'a>(
        &'a self,
        func: &'a ir::Function,
        inst: &'a ir::InstructionData,
        ctrl_typevar: ir::Type,
    ) -> Encodings<'a>;

    /// Encode an instruction after determining it is legal.
    ///
    /// If `inst` can legally be encoded in this ISA, produce the corresponding `Encoding` object.
    /// Otherwise, return `Legalize` action.
    ///
    /// This is also the main entry point for determining if an instruction is legal.
    fn encode(
        &self,
        func: &ir::Function,
        inst: &ir::InstructionData,
        ctrl_typevar: ir::Type,
    ) -> Result<Encoding, Legalize> {
        let mut iter = self.legal_encodings(func, inst, ctrl_typevar);
        iter.next().ok_or_else(|| iter.legalize())
    }

    /// Get a data structure describing the instruction encodings in this ISA.
    fn encoding_info(&self) -> EncInfo;

    /// Legalize a function signature.
    ///
    /// This is used to legalize both the signature of the function being compiled and any called
    /// functions. The signature should be modified by adding `ArgumentLoc` annotations to all
    /// arguments and return values.
    ///
    /// Arguments with types that are not supported by the ABI can be expanded into multiple
    /// arguments:
    ///
    /// - Integer types that are too large to fit in a register can be broken into multiple
    ///   arguments of a smaller integer type.
    /// - Floating point types can be bit-cast to an integer type of the same size, and possible
    ///   broken into smaller integer types.
    /// - Vector types can be bit-cast and broken down into smaller vectors or scalars.
    ///
    /// The legalizer will adapt argument and return values as necessary at all ABI boundaries.
    ///
    /// When this function is called to legalize the signature of the function currently being
    /// compiled, `current` is true. The legalized signature can then also contain special purpose
    /// arguments and return values such as:
    ///
    /// - A `link` argument representing the link registers on RISC architectures that don't push
    ///   the return address on the stack.
    /// - A `link` return value which will receive the value that was passed to the `link`
    ///   argument.
    /// - An `sret` argument can be added if one wasn't present already. This is necessary if the
    ///   signature returns more values than registers are available for returning values.
    /// - An `sret` return value can be added if the ABI requires a function to return its `sret`
    ///   argument in a register.
    ///
    /// Arguments and return values for the caller's frame pointer and other callee-saved registers
    /// should not be added by this function. These arguments are not added until after register
    /// allocation.
    fn legalize_signature(&self, sig: &mut ir::Signature, current: bool);

    /// Get the register class that should be used to represent an ABI argument or return value of
    /// type `ty`. This should be the top-level register class that contains the argument
    /// registers.
    ///
    /// This function can assume that it will only be asked to provide register classes for types
    /// that `legalize_signature()` produces in `ArgumentLoc::Reg` entries.
    fn regclass_for_abi_type(&self, ty: ir::Type) -> RegClass;

    /// Get the set of allocatable registers that can be used when compiling `func`.
    ///
    /// This set excludes reserved registers like the stack pointer and other special-purpose
    /// registers.
    fn allocatable_registers(&self, func: &ir::Function) -> regalloc::RegisterSet;

    /// Compute the stack layout and insert prologue and epilogue code into `func`.
    ///
    /// Return an error if the stack frame is too large.
    fn prologue_epilogue(&self, func: &mut ir::Function) -> CodegenResult<()> {
        let _tt = timing::prologue_epilogue();
        // This default implementation is unlikely to be good enough.
        use ir::stackslot::{StackOffset, StackSize};
        use stack_layout::layout_stack;

        let word_size = StackSize::from(self.pointer_bytes());

        // Account for the SpiderMonkey standard prologue pushes.
        if func.signature.call_conv == CallConv::Baldrdash {
            let bytes = StackSize::from(self.flags().baldrdash_prologue_words()) * word_size;
            let mut ss = ir::StackSlotData::new(ir::StackSlotKind::IncomingArg, bytes);
            ss.offset = Some(-(bytes as StackOffset));
            func.stack_slots.push(ss);
        }

        layout_stack(&mut func.stack_slots, word_size)?;
        Ok(())
    }

    /// Emit binary machine code for a single instruction into the `sink` trait object.
    ///
    /// Note that this will call `put*` methods on the `sink` trait object via its vtable which
    /// is not the fastest way of emitting code.
    ///
    /// This function is under the "testing_hooks" feature, and is only suitable for use by
    /// test harnesses. It increases code size, and is inefficient.
    #[cfg(feature = "testing_hooks")]
    fn emit_inst(
        &self,
        func: &ir::Function,
        inst: ir::Inst,
        divert: &mut regalloc::RegDiversions,
        sink: &mut binemit::CodeSink,
    );

    /// Emit a whole function into memory.
    fn emit_function_to_memory(&self, func: &ir::Function, sink: &mut binemit::MemoryCodeSink);
}
<|endoftext|>


<commit_before>//! Definition of the `TryJoinAll` combinator, waiting for all of a list of
//! futures to finish with either success or error.

use std::fmt;
use std::future::Future;
use std::iter::FromIterator;
use std::mem;
use std::pin::Pin;
use std::prelude::v1::*;
use std::task::Poll;
use super::TryFuture;

#[derive(Debug)]
enum ElemState<F>
where
    F: TryFuture,
{
    Pending(F),
    Done(Option<Result<F::Ok, F::Error>>),
}

impl<F> ElemState<F>
where
    F: TryFuture,
{
    fn pending_pin_mut<'a>(self: Pin<&'a mut Self>) -> Option<Pin<&'a mut F>> {
        // Safety: Basic enum pin projection, no drop + optionally Unpin based
        // on the type of this variant
        match unsafe { self.get_unchecked_mut() } {
            ElemState::Pending(f) => Some(unsafe { Pin::new_unchecked(f) }),
            ElemState::Done(_) => None,
        }
    }

    fn take_done(self: Pin<&mut Self>) -> Option<Result<F::Ok, F::Error>> {
        // Safety: Going from pin to a variant we never pin-project
        match unsafe { self.get_unchecked_mut() } {
            ElemState::Pending(_) => None,
            ElemState::Done(output) => output.take(),
        }
    }
}

impl<F> Unpin for ElemState<F> where F: TryFuture + Unpin {}

fn iter_pin_mut<T>(slice: Pin<&mut [T]>) -> impl Iterator<Item = Pin<&mut T>> {
    // Safety: `std` _could_ make this unsound if it were to decide Pin's
    // invariants aren't required to transmit through slices. Otherwise this has
    // the same safety as a normal field pin projection.
    unsafe { slice.get_unchecked_mut() }
        .iter_mut()
        .map(|t| unsafe { Pin::new_unchecked(t) })
}

#[derive(Debug)]
enum FinalState<E = ()> {
    Pending,
    AllDone,
    Error(E)
}

/// A future which takes a list of futures and resolves with a vector of the
/// completed values or an error.
///
/// This future is created with the `try_join_all` function.
#[must_use = "futures do nothing unless polled"]
pub struct TryJoinAll<F>
where
    F: TryFuture,
{
    elems: Pin<Box<[ElemState<F>]>>,
}

impl<F> fmt::Debug for TryJoinAll<F>
where
    F: TryFuture + fmt::Debug,
    F::Ok: fmt::Debug,
    F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("TryJoinAll")
            .field("elems", &self.elems)
            .finish()
    }
}

/// Creates a future which represents either a collection of the results of the
/// futures given or an error.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>` in the same order as they
/// were provided.
///
/// If any future returns an error then all other futures will be canceled and
/// an error will be returned immediately. If all futures complete successfully,
/// however, then the returned future will succeed with a `Vec` of all the
/// successful results.
///
/// # Examples
///
/// ```
/// #![feature(async_await, await_macro, futures_api)]
/// # futures::executor::block_on(async {
/// use futures::future::{self, try_join_all};
///
/// let futures = vec![
///     future::ok::<u32, u32>(1),
///     future::ok::<u32, u32>(2),
///     future::ok::<u32, u32>(3),
/// ];
///
/// assert_eq!(await!(try_join_all(futures)), Ok(vec![1, 2, 3]));
///
/// let futures = vec![
///     future::ok::<u32, u32>(1),
///     future::err::<u32, u32>(2),
///     future::ok::<u32, u32>(3),
/// ];
///
/// assert_eq!(await!(try_join_all(futures)), Err(2));
/// # });
/// ```
pub fn try_join_all<I>(i: I) -> TryJoinAll<I::Item>
where
    I: IntoIterator,
    I::Item: TryFuture,
{
    let elems: Box<[_]> = i.into_iter().map(ElemState::Pending).collect();
    TryJoinAll {
        elems: Box::into_pin(elems),
    }
}

impl<F> Future for TryJoinAll<F>
where
    F: TryFuture,
{
    type Output = Result<Vec<F::Ok>, F::Error>;

    fn poll(
        mut self: Pin<&mut Self>,
        lw: &::std::task::LocalWaker,
    ) -> Poll<Self::Output> {
        let mut state = FinalState::AllDone;

        for mut elem in iter_pin_mut(self.elems.as_mut()) {
            if let Some(pending) = elem.as_mut().pending_pin_mut() {
                match pending.try_poll(lw) {
                    Poll::Pending => state = FinalState::Pending,
                    Poll::Ready(output) => match output {
                        Ok(item) => elem.set(ElemState::Done(Some(Ok(item)))),
                        Err(e) => {
                            state = FinalState::Error(e);
                            break;
                        }
                    }
                }
            }
        }

        match state {
            FinalState::Pending => Poll::Pending,
            FinalState::AllDone => {
                let mut elems = mem::replace(&mut self.elems, Box::pin([]));
                let result = iter_pin_mut(elems.as_mut())
                    .map(|e| e.take_done().unwrap())
                    .collect();
                Poll::Ready(result)
            },
            FinalState::Error(e) => {
                let _ = mem::replace(&mut self.elems, Box::pin([]));
                Poll::Ready(Err(e))
            },
        }
    }
}

impl<F: TryFuture> FromIterator<F> for TryJoinAll<F> {
    fn from_iter<T: IntoIterator<Item = F>>(iter: T) -> Self {
        try_join_all(iter)
    }
}
<commit_msg>Eliminate unnecessary Result inside ElemState::Done<commit_after>//! Definition of the `TryJoinAll` combinator, waiting for all of a list of
//! futures to finish with either success or error.

use std::fmt;
use std::future::Future;
use std::iter::FromIterator;
use std::mem;
use std::pin::Pin;
use std::prelude::v1::*;
use std::task::Poll;
use super::TryFuture;

#[derive(Debug)]
enum ElemState<F>
where
    F: TryFuture,
{
    Pending(F),
    Done(Option<F::Ok>),
}

impl<F> ElemState<F>
where
    F: TryFuture,
{
    fn pending_pin_mut<'a>(self: Pin<&'a mut Self>) -> Option<Pin<&'a mut F>> {
        // Safety: Basic enum pin projection, no drop + optionally Unpin based
        // on the type of this variant
        match unsafe { self.get_unchecked_mut() } {
            ElemState::Pending(f) => Some(unsafe { Pin::new_unchecked(f) }),
            ElemState::Done(_) => None,
        }
    }

    fn take_done(self: Pin<&mut Self>) -> Option<F::Ok> {
        // Safety: Going from pin to a variant we never pin-project
        match unsafe { self.get_unchecked_mut() } {
            ElemState::Pending(_) => None,
            ElemState::Done(output) => output.take(),
        }
    }
}

impl<F> Unpin for ElemState<F> where F: TryFuture + Unpin {}

fn iter_pin_mut<T>(slice: Pin<&mut [T]>) -> impl Iterator<Item = Pin<&mut T>> {
    // Safety: `std` _could_ make this unsound if it were to decide Pin's
    // invariants aren't required to transmit through slices. Otherwise this has
    // the same safety as a normal field pin projection.
    unsafe { slice.get_unchecked_mut() }
        .iter_mut()
        .map(|t| unsafe { Pin::new_unchecked(t) })
}

#[derive(Debug)]
enum FinalState<E = ()> {
    Pending,
    AllDone,
    Error(E)
}

/// A future which takes a list of futures and resolves with a vector of the
/// completed values or an error.
///
/// This future is created with the `try_join_all` function.
#[must_use = "futures do nothing unless polled"]
pub struct TryJoinAll<F>
where
    F: TryFuture,
{
    elems: Pin<Box<[ElemState<F>]>>,
}

impl<F> fmt::Debug for TryJoinAll<F>
where
    F: TryFuture + fmt::Debug,
    F::Ok: fmt::Debug,
    F::Error: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt.debug_struct("TryJoinAll")
            .field("elems", &self.elems)
            .finish()
    }
}

/// Creates a future which represents either a collection of the results of the
/// futures given or an error.
///
/// The returned future will drive execution for all of its underlying futures,
/// collecting the results into a destination `Vec<T>` in the same order as they
/// were provided.
///
/// If any future returns an error then all other futures will be canceled and
/// an error will be returned immediately. If all futures complete successfully,
/// however, then the returned future will succeed with a `Vec` of all the
/// successful results.
///
/// # Examples
///
/// ```
/// #![feature(async_await, await_macro, futures_api)]
/// # futures::executor::block_on(async {
/// use futures::future::{self, try_join_all};
///
/// let futures = vec![
///     future::ok::<u32, u32>(1),
///     future::ok::<u32, u32>(2),
///     future::ok::<u32, u32>(3),
/// ];
///
/// assert_eq!(await!(try_join_all(futures)), Ok(vec![1, 2, 3]));
///
/// let futures = vec![
///     future::ok::<u32, u32>(1),
///     future::err::<u32, u32>(2),
///     future::ok::<u32, u32>(3),
/// ];
///
/// assert_eq!(await!(try_join_all(futures)), Err(2));
/// # });
/// ```
pub fn try_join_all<I>(i: I) -> TryJoinAll<I::Item>
where
    I: IntoIterator,
    I::Item: TryFuture,
{
    let elems: Box<[_]> = i.into_iter().map(ElemState::Pending).collect();
    TryJoinAll {
        elems: Box::into_pin(elems),
    }
}

impl<F> Future for TryJoinAll<F>
where
    F: TryFuture,
{
    type Output = Result<Vec<F::Ok>, F::Error>;

    fn poll(
        mut self: Pin<&mut Self>,
        lw: &::std::task::LocalWaker,
    ) -> Poll<Self::Output> {
        let mut state = FinalState::AllDone;

        for mut elem in iter_pin_mut(self.elems.as_mut()) {
            if let Some(pending) = elem.as_mut().pending_pin_mut() {
                match pending.try_poll(lw) {
                    Poll::Pending => state = FinalState::Pending,
                    Poll::Ready(output) => match output {
                        Ok(item) => elem.set(ElemState::Done(Some(item))),
                        Err(e) => {
                            state = FinalState::Error(e);
                            break;
                        }
                    }
                }
            }
        }

        match state {
            FinalState::Pending => Poll::Pending,
            FinalState::AllDone => {
                let mut elems = mem::replace(&mut self.elems, Box::pin([]));
                let results = iter_pin_mut(elems.as_mut())
                    .map(|e| e.take_done().unwrap())
                    .collect();
                Poll::Ready(Ok(results))
            },
            FinalState::Error(e) => {
                let _ = mem::replace(&mut self.elems, Box::pin([]));
                Poll::Ready(Err(e))
            },
        }
    }
}

impl<F: TryFuture> FromIterator<F> for TryJoinAll<F> {
    fn from_iter<T: IntoIterator<Item = F>>(iter: T) -> Self {
        try_join_all(iter)
    }
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashMap};

use chrono::prelude::*;
use serde_derive::{Deserialize, Serialize};
use strum_macros::{Display, EnumString};

use crate::state::{GroupStatus, State};
use crate::task::Task;

/// This is the main message enum. \
/// Everything that's communicated in Pueue can be serialized as this enum.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Message {
    Add(AddMessage),
    Remove(Vec<usize>),
    Switch(SwitchMessage),
    Stash(Vec<usize>),
    Enqueue(EnqueueMessage),

    Start(StartMessage),
    Restart(RestartMessage),
    Pause(PauseMessage),
    Kill(KillMessage),
    Signal(SignalMessage),

    Send(SendMessage),
    EditRequest(usize),
    EditResponse(EditResponseMessage),
    Edit(EditMessage),
    Group(GroupMessage),
    GroupResponse(GroupResponseMessage),

    Status,
    StatusResponse(Box<State>),
    Log(LogRequestMessage),
    LogResponse(BTreeMap<usize, TaskLogMessage>),
    Stream(String),
    StreamRequest(StreamRequestMessage),
    /// The boolean decides, whether the children should be get a SIGTERM as well.
    Reset(ResetMessage),
    Clean(CleanMessage),
    DaemonShutdown,

    Success(String),
    Failure(String),

    Parallel(ParallelMessage),
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AddMessage {
    pub command: String,
    pub path: String,
    pub envs: HashMap<String, String>,
    pub start_immediately: bool,
    pub stashed: bool,
    pub group: String,
    pub enqueue_at: Option<DateTime<Local>>,
    pub dependencies: Vec<usize>,
    pub label: Option<String>,
    pub print_task_id: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SwitchMessage {
    pub task_id_1: usize,
    pub task_id_2: usize,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EnqueueMessage {
    pub task_ids: Vec<usize>,
    pub enqueue_at: Option<DateTime<Local>>,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct StartMessage {
    pub task_ids: Vec<usize>,
    pub group: String,
    pub all: bool,
    pub children: bool,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct RestartMessage {
    pub tasks: Vec<TasksToRestart>,
    pub start_immediately: bool,
    pub stashed: bool,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct TasksToRestart {
    pub task_id: usize,
    pub command: String,
    pub path: String,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct PauseMessage {
    pub task_ids: Vec<usize>,
    pub group: String,
    pub wait: bool,
    pub all: bool,
    pub children: bool,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct KillMessage {
    pub task_ids: Vec<usize>,
    pub group: String,
    pub all: bool,
    pub children: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SendMessage {
    pub task_id: usize,
    pub input: String,
}

/// This is a small custom Enum for all currently supported unix signals.
/// Supporting all unix signals would be a mess, since there is a LOT of them.
///
/// This is also needed for usage in clap, since nix's Signal doesn't implement [Display] and
/// [std::str::FromStr].
#[derive(PartialEq, Clone, Debug, Deserialize, Serialize, Display, EnumString)]
pub enum Signal {
    SigTerm,
    SigInt,
    SigKill,
    SigCont,
    SigStop,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SignalMessage {
    pub signal: Signal,
    pub task_ids: Vec<usize>,
    pub children: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EditMessage {
    pub task_id: usize,
    pub command: String,
    pub path: String,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EditResponseMessage {
    pub task_id: usize,
    pub command: String,
    pub path: String,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GroupMessage {
    pub add: Option<String>,
    pub remove: Option<String>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GroupResponseMessage {
    pub groups: BTreeMap<String, GroupStatus>,
    pub settings: BTreeMap<String, usize>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ResetMessage {
    pub children: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CleanMessage {
    #[serde(default = "false_default")]
    pub successful_only: bool,
}
fn false_default() -> bool {
    false
}

/// `err` decides, whether you should stream stderr or stdout.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StreamRequestMessage {
    pub task_id: Option<usize>,
    pub err: bool,
}

/// Request logs for specific tasks.
///
/// `task_ids` specifies the requested tasks. If none are given, all tasks are selected.
/// `send_logs` Determines whether tasks should be sent at all.
/// `lines` Determines whether only a few lines of log should be returned.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LogRequestMessage {
    pub task_ids: Vec<usize>,
    pub send_logs: bool,
    pub lines: Option<usize>,
}

/// Helper struct for sending tasks and their log output to the client.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TaskLogMessage {
    pub task: Task,
    pub stdout: Option<Vec<u8>>,
    pub stderr: Option<Vec<u8>>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ParallelMessage {
    pub parallel_tasks: usize,
    pub group: String,
}

pub fn create_success_message<T: ToString>(text: T) -> Message {
    Message::Success(text.to_string())
}

pub fn create_failure_message<T: ToString>(text: T) -> Message {
    Message::Failure(text.to_string())
}
<commit_msg>Move signal to kill message<commit_after>use std::collections::{BTreeMap, HashMap};

use chrono::prelude::*;
use serde_derive::{Deserialize, Serialize};
use strum_macros::{Display, EnumString};

use crate::state::{GroupStatus, State};
use crate::task::Task;

/// This is the main message enum. \
/// Everything that's communicated in Pueue can be serialized as this enum.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Message {
    Add(AddMessage),
    Remove(Vec<usize>),
    Switch(SwitchMessage),
    Stash(Vec<usize>),
    Enqueue(EnqueueMessage),

    Start(StartMessage),
    Restart(RestartMessage),
    Pause(PauseMessage),
    Kill(KillMessage),

    Send(SendMessage),
    EditRequest(usize),
    EditResponse(EditResponseMessage),
    Edit(EditMessage),
    Group(GroupMessage),
    GroupResponse(GroupResponseMessage),

    Status,
    StatusResponse(Box<State>),
    Log(LogRequestMessage),
    LogResponse(BTreeMap<usize, TaskLogMessage>),
    Stream(String),
    StreamRequest(StreamRequestMessage),
    /// The boolean decides, whether the children should be get a SIGTERM as well.
    Reset(ResetMessage),
    Clean(CleanMessage),
    DaemonShutdown,

    Success(String),
    Failure(String),

    Parallel(ParallelMessage),
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AddMessage {
    pub command: String,
    pub path: String,
    pub envs: HashMap<String, String>,
    pub start_immediately: bool,
    pub stashed: bool,
    pub group: String,
    pub enqueue_at: Option<DateTime<Local>>,
    pub dependencies: Vec<usize>,
    pub label: Option<String>,
    pub print_task_id: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SwitchMessage {
    pub task_id_1: usize,
    pub task_id_2: usize,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EnqueueMessage {
    pub task_ids: Vec<usize>,
    pub enqueue_at: Option<DateTime<Local>>,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct StartMessage {
    pub task_ids: Vec<usize>,
    pub group: String,
    pub all: bool,
    pub children: bool,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct RestartMessage {
    pub tasks: Vec<TasksToRestart>,
    pub start_immediately: bool,
    pub stashed: bool,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct TasksToRestart {
    pub task_id: usize,
    pub command: String,
    pub path: String,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct PauseMessage {
    pub task_ids: Vec<usize>,
    pub group: String,
    pub wait: bool,
    pub all: bool,
    pub children: bool,
}

/// This is a small custom Enum for all currently supported unix signals.
/// Supporting all unix signals would be a mess, since there is a LOT of them.
///
/// This is also needed for usage in clap, since nix's Signal doesn't implement [Display] and
/// [std::str::FromStr].
#[derive(PartialEq, Clone, Debug, Deserialize, Serialize, Display, EnumString)]
pub enum Signal {
    SigTerm,
    SigInt,
    SigKill,
    SigCont,
    SigStop,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct KillMessage {
    pub task_ids: Vec<usize>,
    pub group: String,
    pub all: bool,
    pub children: bool,
    pub signal: Option<Signal>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SendMessage {
    pub task_id: usize,
    pub input: String,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EditMessage {
    pub task_id: usize,
    pub command: String,
    pub path: String,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EditResponseMessage {
    pub task_id: usize,
    pub command: String,
    pub path: String,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GroupMessage {
    pub add: Option<String>,
    pub remove: Option<String>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GroupResponseMessage {
    pub groups: BTreeMap<String, GroupStatus>,
    pub settings: BTreeMap<String, usize>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ResetMessage {
    pub children: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CleanMessage {
    #[serde(default = "false_default")]
    pub successful_only: bool,
}
fn false_default() -> bool {
    false
}

/// `err` decides, whether you should stream stderr or stdout.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StreamRequestMessage {
    pub task_id: Option<usize>,
    pub err: bool,
}

/// Request logs for specific tasks.
///
/// `task_ids` specifies the requested tasks. If none are given, all tasks are selected.
/// `send_logs` Determines whether tasks should be sent at all.
/// `lines` Determines whether only a few lines of log should be returned.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LogRequestMessage {
    pub task_ids: Vec<usize>,
    pub send_logs: bool,
    pub lines: Option<usize>,
}

/// Helper struct for sending tasks and their log output to the client.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TaskLogMessage {
    pub task: Task,
    pub stdout: Option<Vec<u8>>,
    pub stderr: Option<Vec<u8>>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ParallelMessage {
    pub parallel_tasks: usize,
    pub group: String,
}

pub fn create_success_message<T: ToString>(text: T) -> Message {
    Message::Success(text.to_string())
}

pub fn create_failure_message<T: ToString>(text: T) -> Message {
    Message::Failure(text.to_string())
}
<|endoftext|>