<commit_before>extern crate capnp;
extern crate clap;
extern crate regex;

use std::io;
use std::process;

use clap::{Arg, App, SubCommand};

mod entry_capnp;

use std::io::BufRead;
use std::io::Read;
use std::io::Write;

fn with_entries<
    R: io::Read,
    F: FnMut(&mut R, entry_capnp::FileEntry) -> io::Result<()>
>(
    mut from: &mut R,
    mut work: F
) -> io::Result<()> {

    loop {
        match entry_capnp::read_entry(&mut from).expect("TODO: error type mapping") {
            None => return Ok(()),
            Some(entry) => if let Err(e) = work(&mut from, entry) {
                return Err(e);
            }
        }
    }
}

fn cat<R: io::Read, W: io::Write>(mut from: &mut R, to: &mut W) -> io::Result<()> {
    with_entries(&mut from, move |from, entry| {
        assert_eq!(entry.len, copy_upto(from, to, entry.len)?);
        Ok(())
    })
}

fn grep<R: io::Read>(mut from: &mut R, regex: &regex::Regex) -> io::Result<()> {
    with_entries(&mut from, move |mut from, entry| {
        let paths = join_backwards(&entry.paths, "/ /");

        for line in io::BufReader::new((&mut from).take(entry.len)).lines() {
            match line {
                Ok(line) => {
                    if regex.is_match(line.as_str()) {
                        println!("{}:{}", paths, line);
                    }
                }
                Err(e) => {
                    write!(io::stderr(), "skipping non-utf-8 ({}) file: {}\n", e, paths)?;
                }
            }
        }

        Ok(())
    })
}

fn direct_run<R: io::Read>(mut from: &mut R, cmd: &Vec<&str>) -> io::Result<()> {
    with_entries(&mut from, move |mut from, entry| {
        // skip others; assuming they're empty
        if !entry.normal_file {
            assert_eq!(0, entry.len);
            return Ok(());
        }

        if !entry.content_follows {
            return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                                      "Can't do anything for contentless streams"));
        }

        let mut child = process::Command::new(cmd[0])
            .args(&cmd[1..])
            .env("TAR_REALNAME", join_backwards(&entry.paths, "/ /"))
            .env("TAR_FILENAME", entry.paths[0].to_string())
            .env("TAR_SIZE", format!("{}", entry.len))
            .stdin(process::Stdio::piped())
            .stdout(process::Stdio::inherit())
            .stderr(process::Stdio::inherit())
            .spawn()?;

        assert_eq!(entry.len, copy_upto(&mut from, &mut child.stdin.as_mut().unwrap(), entry.len)?);

        assert!(child.wait()?.success());

        Ok(())
    })
}

fn copy_upto<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W, how_much: u64) -> io::Result<u64>
    where R: io::Read, W: io::Write
{
    let mut buf = [0; 8 * 1024];
    let mut written = 0;
    loop {
        let max_to_read = std::cmp::min(how_much - written, buf.len() as u64) as usize;
        let len = match reader.read(&mut buf[0..max_to_read]) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

fn join_backwards(what: &Vec<String>, join: &str) -> String {
    let mut ret = String::with_capacity(what.len() * 40);

    for i in (1..(what.len() - 1)).rev() {
        ret.push_str(what[i].as_str());
        ret.push_str(join);
    }
    ret.push_str(what[0].as_str());
    ret
}

fn main() {
    let from = io::stdin();
    let mut from = from.lock();

    match App::new("contentin")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("cat")
        )
        .subcommand(SubCommand::with_name("grep")
            .arg(Arg::with_name("pattern")
                .required(true)
                .help("pattern to search for"))
        )
        .subcommand(SubCommand::with_name("run")
                        .setting(clap::AppSettings::TrailingVarArg)
                        .setting(clap::AppSettings::DontDelimitTrailingValues)
                        .arg(Arg::with_name("sh")
                            .long("sh")
                            .help("Run with `sh -c`, and ssh-like quoting behaviour"))
//                      .arg(Arg::with_name("command-failure")
//                          .long("command-failure")
//                          .takes_value(true)
//                          .use_delimiter(false)
//                          .default_value("fatal")
//                          .possible_values(&[
//                              "fatal",
//                              "ignore",
//                          ])
                        .arg(Arg::with_name("command")
                            .required(true)
                            .help("Command to run, and its arguments")
                            .multiple(true))
        )
        .get_matches().subcommand() {
        ("cat", Some(_)) => {
            let stdout = io::stdout();
            let mut stdout = stdout.lock();
            cat(&mut from, &mut stdout).expect("TODO: handle error");
        }
        ("grep", Some(matches)) => {
            let pattern = matches.value_of("pattern").unwrap();
            match regex::Regex::new(pattern) {
                Ok(regex) => {
                    grep(&mut from, &regex).expect("TODO: handle error")
                }
                Err(e) => {
                    println!("invalid regex: {} {}", pattern, e);
                    // TODO: return 2;
                }
            }
        }
        ("run", Some(matches)) => {
            let raw_command: Vec<&str> = matches.values_of("command").unwrap().collect();
            let as_dumb_line = raw_command.join(" ");

            let cmd = if matches.is_present("sh") {
                vec!("sh", "-c", as_dumb_line.as_str())
            } else {
                raw_command
            };

            direct_run(&mut from, &cmd).expect("TODO: handle error")
        },
        _ => unreachable!(),
    }
}
<commit_msg>unpack capnp errors<commit_after>extern crate capnp;
extern crate clap;
extern crate regex;

use std::io;
use std::process;

use clap::{Arg, App, SubCommand};

mod entry_capnp;

use std::io::BufRead;
use std::io::Read;
use std::io::Write;

fn with_entries<
    R: io::Read,
    F: FnMut(&mut R, entry_capnp::FileEntry) -> io::Result<()>
>(
    mut from: &mut R,
    mut work: F
) -> io::Result<()> {

    loop {
        match entry_capnp::read_entry(&mut from) {
            Ok(None) => return Ok(()),
            Ok(Some(entry)) => if let Err(e) = work(&mut from, entry) {
                return Err(e);
            },
            Err(e) => match e.kind {
                capnp::ErrorKind::Failed => {
                    return Err(io::Error::new(io::ErrorKind::InvalidData,
                                              format!("capnp failure: {}", e)));
                }
                _ => panic!("unexpected capnp error return: {}", e)
            }
        }
    }
}

fn cat<R: io::Read, W: io::Write>(mut from: &mut R, to: &mut W) -> io::Result<()> {
    with_entries(&mut from, move |from, entry| {
        assert_eq!(entry.len, copy_upto(from, to, entry.len)?);
        Ok(())
    })
}

fn grep<R: io::Read>(mut from: &mut R, regex: &regex::Regex) -> io::Result<()> {
    with_entries(&mut from, move |mut from, entry| {
        let paths = join_backwards(&entry.paths, "/ /");

        for line in io::BufReader::new((&mut from).take(entry.len)).lines() {
            match line {
                Ok(line) => {
                    if regex.is_match(line.as_str()) {
                        println!("{}:{}", paths, line);
                    }
                }
                Err(e) => {
                    write!(io::stderr(), "skipping non-utf-8 ({}) file: {}\n", e, paths)?;
                }
            }
        }

        Ok(())
    })
}

fn direct_run<R: io::Read>(mut from: &mut R, cmd: &Vec<&str>) -> io::Result<()> {
    with_entries(&mut from, move |mut from, entry| {
        // skip others; assuming they're empty
        if !entry.normal_file {
            assert_eq!(0, entry.len);
            return Ok(());
        }

        if !entry.content_follows {
            return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                                      "Can't do anything for contentless streams"));
        }

        let mut child = process::Command::new(cmd[0])
            .args(&cmd[1..])
            .env("TAR_REALNAME", join_backwards(&entry.paths, "/ /"))
            .env("TAR_FILENAME", entry.paths[0].to_string())
            .env("TAR_SIZE", format!("{}", entry.len))
            .stdin(process::Stdio::piped())
            .stdout(process::Stdio::inherit())
            .stderr(process::Stdio::inherit())
            .spawn()?;

        assert_eq!(entry.len, copy_upto(&mut from, &mut child.stdin.as_mut().unwrap(), entry.len)?);

        assert!(child.wait()?.success());

        Ok(())
    })
}

fn copy_upto<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W, how_much: u64) -> io::Result<u64>
    where R: io::Read, W: io::Write
{
    let mut buf = [0; 8 * 1024];
    let mut written = 0;
    loop {
        let max_to_read = std::cmp::min(how_much - written, buf.len() as u64) as usize;
        let len = match reader.read(&mut buf[0..max_to_read]) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

fn join_backwards(what: &Vec<String>, join: &str) -> String {
    let mut ret = String::with_capacity(what.len() * 40);

    for i in (1..(what.len() - 1)).rev() {
        ret.push_str(what[i].as_str());
        ret.push_str(join);
    }
    ret.push_str(what[0].as_str());
    ret
}

fn main() {
    let from = io::stdin();
    let mut from = from.lock();

    match App::new("contentin")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .subcommand(SubCommand::with_name("cat")
        )
        .subcommand(SubCommand::with_name("grep")
            .arg(Arg::with_name("pattern")
                .required(true)
                .help("pattern to search for"))
        )
        .subcommand(SubCommand::with_name("run")
                        .setting(clap::AppSettings::TrailingVarArg)
                        .setting(clap::AppSettings::DontDelimitTrailingValues)
                        .arg(Arg::with_name("sh")
                            .long("sh")
                            .help("Run with `sh -c`, and ssh-like quoting behaviour"))
//                      .arg(Arg::with_name("command-failure")
//                          .long("command-failure")
//                          .takes_value(true)
//                          .use_delimiter(false)
//                          .default_value("fatal")
//                          .possible_values(&[
//                              "fatal",
//                              "ignore",
//                          ])
                        .arg(Arg::with_name("command")
                            .required(true)
                            .help("Command to run, and its arguments")
                            .multiple(true))
        )
        .get_matches().subcommand() {
        ("cat", Some(_)) => {
            let stdout = io::stdout();
            let mut stdout = stdout.lock();
            cat(&mut from, &mut stdout).expect("TODO: handle error");
        }
        ("grep", Some(matches)) => {
            let pattern = matches.value_of("pattern").unwrap();
            match regex::Regex::new(pattern) {
                Ok(regex) => {
                    grep(&mut from, &regex).expect("TODO: handle error")
                }
                Err(e) => {
                    println!("invalid regex: {} {}", pattern, e);
                    // TODO: return 2;
                }
            }
        }
        ("run", Some(matches)) => {
            let raw_command: Vec<&str> = matches.values_of("command").unwrap().collect();
            let as_dumb_line = raw_command.join(" ");

            let cmd = if matches.is_present("sh") {
                vec!("sh", "-c", as_dumb_line.as_str())
            } else {
                raw_command
            };

            direct_run(&mut from, &cmd).expect("TODO: handle error")
        },
        _ => unreachable!(),
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::account_address::AccountAddress;
use anyhow::{ensure, Error, Result};
#[cfg(any(test, feature = "fuzzing"))]
use proptest_derive::Arbitrary;
#[cfg(any(test, feature = "fuzzing"))]
use rand::{rngs::OsRng, RngCore};
use serde::{de, ser, Deserialize, Serialize};
use std::{
    convert::{TryFrom, TryInto},
    fmt,
    str::FromStr,
};

/// A struct that represents a globally unique id for an Event stream that a user can listen to.
/// By design, the lower part of EventKey is the same as account address.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
pub struct EventKey([u8; EventKey::LENGTH]);

impl EventKey {
    /// Construct a new EventKey from a byte array slice.
    pub fn new(key: [u8; Self::LENGTH]) -> Self {
        EventKey(key)
    }

    /// The number of bytes in an EventKey.
    pub const LENGTH: usize = AccountAddress::LENGTH + 8;

    /// Get the byte representation of the event key.
    pub fn as_bytes(&self) -> &[u8] {
        &self.0
    }

    /// Convert event key into a byte array.
    pub fn to_vec(&self) -> Vec<u8> {
        self.0.to_vec()
    }

    /// Get the account address part in this event key
    pub fn get_creator_address(&self) -> AccountAddress {
        AccountAddress::try_from(&self.0[EventKey::LENGTH - AccountAddress::LENGTH..])
            .expect("get_creator_address failed")
    }

    /// If this is the `ith` EventKey` created by `get_creator_address()`, return `i`
    pub fn get_creation_number(&self) -> u64 {
        u64::from_le_bytes(self.0[0..8].try_into().unwrap())
    }

    #[cfg(any(test, feature = "fuzzing"))]
    /// Create a random event key for testing
    pub fn random() -> Self {
        let mut rng = OsRng;
        let salt = rng.next_u64();
        EventKey::new_from_address(&AccountAddress::random(), salt)
    }

    /// Create a unique handle by using an AccountAddress and a counter.
    pub fn new_from_address(addr: &AccountAddress, salt: u64) -> Self {
        let mut output_bytes = [0; Self::LENGTH];
        let (lhs, rhs) = output_bytes.split_at_mut(8);
        lhs.copy_from_slice(&salt.to_le_bytes());
        rhs.copy_from_slice(addr.as_ref());
        EventKey(output_bytes)
    }
}

impl FromStr for EventKey {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        let bytes_out = ::hex::decode(s)?;
        EventKey::try_from(bytes_out.as_slice())
    }
}

impl From<EventKey> for [u8; EventKey::LENGTH] {
    fn from(event_key: EventKey) -> Self {
        event_key.0
    }
}

impl From<&EventKey> for [u8; EventKey::LENGTH] {
    fn from(event_key: &EventKey) -> Self {
        event_key.0
    }
}

// TODO(#1307)
impl ser::Serialize for EventKey {
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        if serializer.is_human_readable() {
            self.to_string().serialize(serializer)
        } else {
            // In order to preserve the Serde data model and help analysis tools,
            // make sure to wrap our value in a container with the same name
            // as the original type.
            serializer.serialize_newtype_struct("EventKey", serde_bytes::Bytes::new(&self.0))
        }
    }
}

impl<'de> de::Deserialize<'de> for EventKey {
    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        if deserializer.is_human_readable() {
            let s = <String>::deserialize(deserializer)?;
            Self::try_from(
                hex::decode(s)
                    .map_err(<D::Error as ::serde::de::Error>::custom)?
                    .as_slice(),
            )
            .map_err(<D::Error as ::serde::de::Error>::custom)
        } else {
            // See comment in serialize.
            #[derive(::serde::Deserialize)]
            #[serde(rename = "EventKey")]
            struct Value<'a>(&'a [u8]);

            let value = Value::deserialize(deserializer)?;
            Self::try_from(value.0).map_err(<D::Error as ::serde::de::Error>::custom)
        }
    }
}

impl TryFrom<&[u8]> for EventKey {
    type Error = Error;

    /// Tries to convert the provided byte array into Event Key.
    fn try_from(bytes: &[u8]) -> Result<EventKey> {
        ensure!(
            bytes.len() == Self::LENGTH,
            "The Event Key {:?} is of invalid length",
            bytes
        );
        let mut addr = [0u8; Self::LENGTH];
        addr.copy_from_slice(bytes);
        Ok(EventKey(addr))
    }
}

/// A Rust representation of an Event Handle Resource.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EventHandle {
    /// Number of events in the event stream.
    count: u64,
    /// The associated globally unique key that is used as the key to the EventStore.
    key: EventKey,
}

impl EventHandle {
    /// Constructs a new Event Handle
    pub fn new(key: EventKey, count: u64) -> Self {
        EventHandle { key, count }
    }

    /// Return the key to where this event is stored in EventStore.
    pub fn key(&self) -> &EventKey {
        &self.key
    }
    /// Return the counter for the handle
    pub fn count(&self) -> u64 {
        self.count
    }

    #[cfg(any(test, feature = "fuzzing"))]
    pub fn count_mut(&mut self) -> &mut u64 {
        &mut self.count
    }

    #[cfg(any(test, feature = "fuzzing"))]
    /// Create a random event handle for testing
    pub fn random_handle(count: u64) -> Self {
        Self {
            key: EventKey::random(),
            count,
        }
    }

    #[cfg(any(test, feature = "fuzzing"))]
    /// Derive a unique handle by using an AccountAddress and a counter.
    pub fn new_from_address(addr: &AccountAddress, salt: u64) -> Self {
        Self {
            key: EventKey::new_from_address(addr, salt),
            count: 0,
        }
    }
}

impl fmt::LowerHex for EventKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", hex::encode(self.as_bytes()))
    }
}

impl fmt::Display for EventKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
        // Forward to the LowerHex impl with a "0x" prepended (the # flag).
        write!(f, "{:#x}", self)
    }
}
<commit_msg>types: improvements to EventKey<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::account_address::AccountAddress;
use hex::FromHex;
#[cfg(any(test, feature = "fuzzing"))]
use proptest_derive::Arbitrary;
#[cfg(any(test, feature = "fuzzing"))]
use rand::{rngs::OsRng, RngCore};
use serde::{de, ser, Deserialize, Serialize};
use std::{
    convert::{TryFrom, TryInto},
    fmt,
    str::FromStr,
};

/// A struct that represents a globally unique id for an Event stream that a user can listen to.
/// By design, the lower part of EventKey is the same as account address.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
pub struct EventKey([u8; EventKey::LENGTH]);

impl EventKey {
    /// Construct a new EventKey from a byte array slice.
    pub fn new(key: [u8; Self::LENGTH]) -> Self {
        EventKey(key)
    }

    /// The number of bytes in an EventKey.
    pub const LENGTH: usize = AccountAddress::LENGTH + 8;

    /// Get the byte representation of the event key.
    pub fn as_bytes(&self) -> &[u8] {
        &self.0
    }

    /// Convert event key into a byte array.
    pub fn to_vec(&self) -> Vec<u8> {
        self.0.to_vec()
    }

    /// Get the account address part in this event key
    pub fn get_creator_address(&self) -> AccountAddress {
        AccountAddress::try_from(&self.0[EventKey::LENGTH - AccountAddress::LENGTH..])
            .expect("get_creator_address failed")
    }

    /// If this is the `ith` EventKey` created by `get_creator_address()`, return `i`
    pub fn get_creation_number(&self) -> u64 {
        u64::from_le_bytes(self.0[0..8].try_into().unwrap())
    }

    #[cfg(any(test, feature = "fuzzing"))]
    /// Create a random event key for testing
    pub fn random() -> Self {
        let mut rng = OsRng;
        let salt = rng.next_u64();
        EventKey::new_from_address(&AccountAddress::random(), salt)
    }

    /// Create a unique handle by using an AccountAddress and a counter.
    pub fn new_from_address(addr: &AccountAddress, salt: u64) -> Self {
        let mut output_bytes = [0; Self::LENGTH];
        let (lhs, rhs) = output_bytes.split_at_mut(8);
        lhs.copy_from_slice(&salt.to_le_bytes());
        rhs.copy_from_slice(addr.as_ref());
        EventKey(output_bytes)
    }

    pub fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, EventKeyParseError> {
        <[u8; Self::LENGTH]>::from_hex(hex)
            .map_err(|_| EventKeyParseError)
            .map(Self)
    }

    pub fn from_bytes<T: AsRef<[u8]>>(bytes: T) -> Result<Self, EventKeyParseError> {
        <[u8; Self::LENGTH]>::try_from(bytes.as_ref())
            .map_err(|_| EventKeyParseError)
            .map(Self)
    }
}

impl FromStr for EventKey {
    type Err = EventKeyParseError;

    fn from_str(s: &str) -> Result<Self, EventKeyParseError> {
        EventKey::from_hex(s)
    }
}

impl From<EventKey> for [u8; EventKey::LENGTH] {
    fn from(event_key: EventKey) -> Self {
        event_key.0
    }
}

impl From<&EventKey> for [u8; EventKey::LENGTH] {
    fn from(event_key: &EventKey) -> Self {
        event_key.0
    }
}

impl ser::Serialize for EventKey {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        if serializer.is_human_readable() {
            self.to_string().serialize(serializer)
        } else {
            // In order to preserve the Serde data model and help analysis tools,
            // make sure to wrap our value in a container with the same name
            // as the original type.
            serializer.serialize_newtype_struct("EventKey", serde_bytes::Bytes::new(&self.0))
        }
    }
}

impl<'de> de::Deserialize<'de> for EventKey {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        use serde::de::Error;

        if deserializer.is_human_readable() {
            let s = <String>::deserialize(deserializer)?;
            EventKey::from_hex(s).map_err(D::Error::custom)
        } else {
            // See comment in serialize.
            #[derive(::serde::Deserialize)]
            #[serde(rename = "EventKey")]
            struct Value<'a>(&'a [u8]);

            let value = Value::deserialize(deserializer)?;
            Self::try_from(value.0).map_err(D::Error::custom)
        }
    }
}

impl TryFrom<&[u8]> for EventKey {
    type Error = EventKeyParseError;

    /// Tries to convert the provided byte array into Event Key.
    fn try_from(bytes: &[u8]) -> Result<EventKey, EventKeyParseError> {
        Self::from_bytes(bytes)
    }
}

#[derive(Clone, Copy, Debug)]
pub struct EventKeyParseError;

impl fmt::Display for EventKeyParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
        write!(f, "unable to parse EventKey")
    }
}

impl std::error::Error for EventKeyParseError {}

/// A Rust representation of an Event Handle Resource.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EventHandle {
    /// Number of events in the event stream.
    count: u64,
    /// The associated globally unique key that is used as the key to the EventStore.
    key: EventKey,
}

impl EventHandle {
    /// Constructs a new Event Handle
    pub fn new(key: EventKey, count: u64) -> Self {
        EventHandle { key, count }
    }

    /// Return the key to where this event is stored in EventStore.
    pub fn key(&self) -> &EventKey {
        &self.key
    }

    /// Return the counter for the handle
    pub fn count(&self) -> u64 {
        self.count
    }

    #[cfg(any(test, feature = "fuzzing"))]
    pub fn count_mut(&mut self) -> &mut u64 {
        &mut self.count
    }

    #[cfg(any(test, feature = "fuzzing"))]
    /// Create a random event handle for testing
    pub fn random_handle(count: u64) -> Self {
        Self {
            key: EventKey::random(),
            count,
        }
    }

    #[cfg(any(test, feature = "fuzzing"))]
    /// Derive a unique handle by using an AccountAddress and a counter.
    pub fn new_from_address(addr: &AccountAddress, salt: u64) -> Self {
        Self {
            key: EventKey::new_from_address(addr, salt),
            count: 0,
        }
    }
}

impl fmt::LowerHex for EventKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            write!(f, "0x")?;
        }

        for byte in &self.0 {
            write!(f, "{:02x}", byte)?;
        }

        Ok(())
    }
}

impl fmt::Display for EventKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:x}", self)
    }
}
<|endoftext|>


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

#![cfg_attr(feature = "fatal-warnings", deny(warnings))]

#[macro_use]
extern crate bencher;
extern crate rpds;

mod utils;

use bencher::{black_box, Bencher};
use rpds::List;
use utils::iterations;
use utils::BencherNoDrop;

fn rpds_list_push_front(bench: &mut Bencher) {
    let limit = iterations(100_000);

    bench.iter_no_drop(|| {
        let mut list: List<usize> = List::new();

        for i in 0..limit {
            list = list.push_front(i);
        }

        list
    });
}

fn rpds_list_push_front_mut(bench: &mut Bencher) {
    let limit = iterations(100_000);

    bench.iter_no_drop(|| {
        let mut list: List<usize> = List::new();

        for i in 0..limit {
            list.push_front_mut(i);
        }

        list
    });
}

fn rpds_list_drop_first(bench: &mut Bencher) {
    let limit = iterations(100_000);
    let mut full_list: List<usize> = List::new();

    for i in 0..limit {
        full_list = full_list.push_front(i);
    }

    bench.iter_no_drop(|| {
        let mut list: List<usize> = full_list.clone();

        for _ in 0..limit {
            list = list.drop_first().unwrap();
        }

        list
    });
}

fn rpds_list_drop_first_mut(bench: &mut Bencher) {
    let limit = iterations(100_000);
    let mut full_list: List<usize> = List::new();

    for i in 0..limit {
        full_list.push_front_mut(i);
    }

    bench.iter_no_drop(|| {
        let mut list: List<usize> = full_list.clone();

        for _ in 0..limit {
            list.drop_first_mut();
        }

        list
    });
}

fn rpds_list_iterate(bench: &mut Bencher) {
    let limit = iterations(100_000);
    let mut list: List<usize> = List::new();

    for i in 0..limit {
        list = list.push_front(i);
    }

    bench.iter(|| {
        for i in list.iter() {
            black_box(i);
        }
    });
}

benchmark_group!(
    benches,
    rpds_list_push_front,
    rpds_list_push_front_mut,
    rpds_list_drop_first,
    rpds_list_drop_first_mut,
    rpds_list_iterate
);
benchmark_main!(benches);
<commit_msg>Added benchmarks for `List::reverse()`.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#![cfg_attr(feature = "fatal-warnings", deny(warnings))]

#[macro_use]
extern crate bencher;
extern crate rpds;

mod utils;

use bencher::{black_box, Bencher};
use rpds::List;
use utils::iterations;
use utils::BencherNoDrop;

fn rpds_list_push_front(bench: &mut Bencher) {
    let limit = iterations(100_000);

    bench.iter_no_drop(|| {
        let mut list: List<usize> = List::new();

        for i in 0..limit {
            list = list.push_front(i);
        }

        list
    });
}

fn rpds_list_push_front_mut(bench: &mut Bencher) {
    let limit = iterations(100_000);

    bench.iter_no_drop(|| {
        let mut list: List<usize> = List::new();

        for i in 0..limit {
            list.push_front_mut(i);
        }

        list
    });
}

fn rpds_list_drop_first(bench: &mut Bencher) {
    let limit = iterations(100_000);
    let mut full_list: List<usize> = List::new();

    for i in 0..limit {
        full_list = full_list.push_front(i);
    }

    bench.iter_no_drop(|| {
        let mut list: List<usize> = full_list.clone();

        for _ in 0..limit {
            list = list.drop_first().unwrap();
        }

        list
    });
}

fn rpds_list_drop_first_mut(bench: &mut Bencher) {
    let limit = iterations(100_000);
    let mut full_list: List<usize> = List::new();

    for i in 0..limit {
        full_list.push_front_mut(i);
    }

    bench.iter_no_drop(|| {
        let mut list: List<usize> = full_list.clone();

        for _ in 0..limit {
            list.drop_first_mut();
        }

        list
    });
}

fn rpds_list_reverse(bench: &mut Bencher) {
    let limit = iterations(10_000);
    let mut full_list: List<usize> = List::new();

    for i in 0..limit {
        full_list.push_front_mut(i);
    }

    bench.iter_no_drop(|| {
        let mut list: List<usize> = full_list.clone();

        for _ in 0..limit {
            list = list.reverse();
        }

        list
    });
}

fn rpds_list_reverse_mut(bench: &mut Bencher) {
    let limit = iterations(10_000);
    let mut full_list: List<usize> = List::new();

    for i in 0..limit {
        full_list.push_front_mut(i);
    }

    bench.iter_no_drop(|| {
        let mut list: List<usize> = full_list.clone();

        for _ in 0..limit {
            list.reverse_mut();
        }

        list
    });
}

fn rpds_list_iterate(bench: &mut Bencher) {
    let limit = iterations(100_000);
    let mut list: List<usize> = List::new();

    for i in 0..limit {
        list = list.push_front(i);
    }

    bench.iter(|| {
        for i in list.iter() {
            black_box(i);
        }
    });
}

benchmark_group!(
    benches,
    rpds_list_push_front,
    rpds_list_push_front_mut,
    rpds_list_drop_first,
    rpds_list_drop_first_mut,
    rpds_list_reverse,
    rpds_list_reverse_mut,
    rpds_list_iterate
);
benchmark_main!(benches);
<|endoftext|>


<commit_before>use std::os;

fn main() {
	if os::args().len() < 2 {
		println("Error: Please provide a number as argument.");
		return;
	}

	let i = from_str::<int>(os::args()[1]).unwrap();
	println!("{:d} has {:d} Collatz steps", i, collatz(i));
}

fn collatz(N: int) -> int {
	if N == 1 { return 0; }
	match N % 2 {
		0 => { 1 + collatz(N/2) }
		_ => { 1 + collatz(N*3+1) }
	}
}
<commit_msg>os::args returns a String, rather than &str now<commit_after>use std::os;

fn main() {
	if os::args().len() < 2 {
		println("Error: Please provide a number as argument.");
		return;
	}

	let i = from_str::<int>(os::args()[1].as_slice()).unwrap();
	println!("{:d} has {:d} Collatz steps", i, collatz(i));
}

fn collatz(N: int) -> int {
	if N == 1 { return 0; }
	match N % 2 {
		0 => { 1 + collatz(N/2) }
		_ => { 1 + collatz(N*3+1) }
	}
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate pattern_api_v2_test_support;
extern crate pattern_api_v2;

pub use std::ffi::{OsStr, OsString};
use std::ops::{Deref, DerefMut};
pub fn os(s: &str) -> OsStrBuf {
    OsStrBuf(s.into())
}

pub struct OsStrBuf(OsString);

impl Deref for OsStrBuf {
    type Target = OsStr;
    fn deref(&self) -> &OsStr {
        &*self.0
    }
}

impl DerefMut for OsStrBuf {
    // I'm evil, I know >:)
    #[allow(mutable_transmutes)]
    fn deref_mut(&mut self) -> &mut OsStr {
        unsafe {
            ::std::mem::transmute::<&OsStr, &mut OsStr>(&*self.0)
        }
    }
}

searcher_cross_test! {
    test1 {
        double: [
            Reject(0, 1),
            Match (1, 3),
            Reject(3, 4),
            Match (4, 6),
            Reject(6, 7),
        ];
        for:

        str,          &str:      "abbcbbd",                      &str:   "bb";
        str_mut,      &mut str:   &mut String::from("abbcbbd"),  &str:   "bb";
        u8_slice,     &[u8]:      b"abbcbbd",                    &[u8]:  b"bb";
        u8_slice_mut, &mut [u8]:  &mut {*b"abbcbbd"},            &[u8]:  b"bb";
        slice,        &[u32]:     &[1,2,2,3,2,2,4],              &[u32]: &[2,2];
        slice_mut,    &mut [u32]: &mut {[1,2,2,3,2,2,4]},        &[u32]: &[2,2];
        slice2,       &[i32]:     &[-1,-2,-2,-3,-2,-2,-4],       &[i32]: &[-2,-2];
        slice2_mut,   &mut [i32]: &mut {[-1,-2,-2,-3,-2,-2,-4]}, &[i32]: &[-2,-2];
        os_str,       &OsStr:     &os("abbcbbd"),                &OsStr: &os("bb");
        os_str_mut,   &mut OsStr: &mut os("abbcbbd"),            &OsStr: &os("bb");
        os_str2,      &OsStr:     &os("abbcbbd"),                &str:   "bb";
        os_str_mut2,  &mut OsStr: &mut os("abbcbbd"),            &str:   "bb";
    }
}
<commit_msg>Made OsStr cross tests test with partially invalid strings<commit_after>#[macro_use]
extern crate pattern_api_v2_test_support;
extern crate pattern_api_v2;

pub use std::ffi::{OsStr, OsString};
use std::ops::{Deref, DerefMut};
use std::mem;

pub fn os(s: &[u8]) -> OsStrBuf {
    let s = unsafe {
        mem::transmute::<&[u8], &str>(s)
    };
    OsStrBuf(s.into())
}

pub struct OsStrBuf(OsString);

impl Deref for OsStrBuf {
    type Target = OsStr;
    fn deref(&self) -> &OsStr {
        &*self.0
    }
}

impl DerefMut for OsStrBuf {
    // I'm evil, I know >:)
    #[allow(mutable_transmutes)]
    fn deref_mut(&mut self) -> &mut OsStr {
        unsafe {
            mem::transmute::<&OsStr, &mut OsStr>(&*self.0)
        }
    }
}

searcher_cross_test! {
    test1 {
        double: [
            Reject(0, 1),
            Match (1, 3),
            Reject(3, 4),
            Match (4, 6),
            Reject(6, 7),
        ];
        for:

    //  name,         slice type: input                          pattern
        str,          &str:      "abbcbbd",                      &str:   "bb";
        str_mut,      &mut str:   &mut String::from("abbcbbd"),  &str:   "bb";
        u8_slice,     &[u8]:      b"abbcbbd",                    &[u8]:  b"bb";
        u8_slice_mut, &mut [u8]:  &mut {*b"abbcbbd"},            &[u8]:  b"bb";
        slice,        &[u32]:     &[1,2,2,3,2,2,4],              &[u32]: &[2,2];
        slice_mut,    &mut [u32]: &mut {[1,2,2,3,2,2,4]},        &[u32]: &[2,2];
        slice2,       &[i32]:     &[-1,-2,-2,-3,-2,-2,-4],       &[i32]: &[-2,-2];
        slice2_mut,   &mut [i32]: &mut {[-1,-2,-2,-3,-2,-2,-4]}, &[i32]: &[-2,-2];
        os_str,       &OsStr:     &os(b"abb\xffbbd"),            &OsStr: &os(b"bb");
        os_str_mut,   &mut OsStr: &mut os(b"abb\xffbbd"),        &OsStr: &os(b"bb");
        os_str2,      &OsStr:     &os(b"abb\xffbbd"),            &str:   "bb";
        os_str_mut2,  &mut OsStr: &mut os(b"abb\xffbbd"),        &str:   "bb";
    }
}
<|endoftext|>


<commit_before>use std::io::{File, Truncate, Write};

pub fn to_ppm(image_data: Vec<int>, width: int, height: int, filename: &str) -> () {
    let max_color = 255;
    let header = format!("P3 {} {} {}\n", width, height, max_color);
    // let image_data_string = image_data.iter().map(|&i| i.to_str()).connect(" ");

    let path = Path::new(filename);
    let mut f = match File::open_mode(&path, Truncate, Write) {
        Ok(f)  => f,
        Err(e) => fail!("File error: {}", e),
    };

    f.write(header.as_bytes());
    // f.write_line(image_data_string);
    for oct in image_data.iter() {
        f.write_int(*oct);
        f.write(" ".as_bytes());
    }
}
<commit_msg>Clamp export ppm values to a max of 255<commit_after>use std::io::{File, Truncate, Write};
use std::cmp::min;

pub fn to_ppm(image_data: Vec<int>, width: int, height: int, filename: &str) -> () {
    let max_color = 255;
    let header = format!("P3 {} {} {}\n", width, height, max_color);

    // let image_data_string = image_data.iter().map(|&i| i.to_str()).connect(" ");
    // How do I even convert a Vec<int> to a string

    let path = Path::new(filename);
    let mut f = match File::open_mode(&path, Truncate, Write) {
        Ok(f)  => {f},
        Err(e) => fail!("File error: {}", e),
    };

    f.write(header.as_bytes());
    for oct in image_data.iter() {
        f.write_int(*min(oct, &max_color)); // Clamp to ..255
        f.write(" ".as_bytes());
    }
}
<|endoftext|>


<commit_before>/*
   Copyright 2017 Takashi Ogura

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

extern crate env_logger;
extern crate glfw;
extern crate k;
extern crate nalgebra as na;
extern crate rand;
extern crate structopt;
#[macro_use]
extern crate structopt_derive;
extern crate urdf_rs;
extern crate urdf_viz;

use glfw::{Action, Key, WindowEvent};
use k::InverseKinematicsSolver;
use k::KinematicChain;
use k::JointContainer;
use k::urdf::FromUrdf;
use k::ChainContainer;
use std::path::Path;
use structopt::StructOpt;

#[cfg(target_os = "macos")]
static NATIVE_MOD: glfw::modifiers::Modifiers = glfw::modifiers::Super;

#[cfg(not(target_os = "macos"))]
static NATIVE_MOD: glfw::modifiers::Modifiers = glfw::modifiers::Control;

fn move_joint_by_random(robot: &mut k::LinkTree<f32>) -> Result<(), k::JointError> {
    let angles_vec = robot
        .iter_joints_link()
        .map(|link| match link.joint.limits {
            Some(ref range) => (range.max - range.min) * rand::random::<f32>() + range.min,
            None => (rand::random::<f32>() - 0.5) * 2.0,
        })
        .collect::<Vec<f32>>();
    robot.set_joint_angles(&angles_vec)
}

fn move_joint_by_index(
    index: usize,
    diff_angle: f32,
    robot: &mut k::LinkTree<f32>,
) -> Result<(), k::JointError> {
    let mut angles_vec = robot.joint_angles();
    assert!(index < robot.dof());
    angles_vec[index] += diff_angle;
    robot.set_joint_angles(&angles_vec)
}

struct LoopIndex {
    index: usize,
    size: usize,
}

impl LoopIndex {
    fn new(size: usize) -> Self {
        Self {
            index: 0,
            size: size,
        }
    }
    fn get(&self) -> usize {
        self.index
    }
    fn inc(&mut self) {
        if self.size != 0 {
            self.index += 1;
            self.index %= self.size;
        }
    }
    fn dec(&mut self) {
        if self.size != 0 {
            if self.index == 0 {
                self.index = self.size - 1;
            } else {
                self.index -= 1;
            }
        }
    }
}

const HOW_TO_USE_STR: &'static str = r"
[:    joint ID +1
]:    joint ID -1
,:    IK target ID +1
.:    IK target ID -1
r:    set random angles
Up:   joint angle +0.1
Down: joint angle -0.1
Ctrl+Drag: move joint
Shift+Drag: IK (y, z)
Shift+Ctrl+Drag: IK (x, z)
c:    toggle visual/collision
";

struct UrdfViewerApp<'a> {
    urdf_robot: urdf_rs::Robot,
    robot: k::LinkTree<f32>,
    viewer: urdf_viz::Viewer,
    arms: Vec<k::LinkChain<f32>>,
    joint_names: Vec<String>,
    link_names: Vec<String>,
    num_arms: usize,
    num_joints: usize,
    index_of_arm: LoopIndex,
    index_of_move_joint: LoopIndex,
    base_dir: Option<&'a Path>,
}

impl<'a> UrdfViewerApp<'a> {
    fn new(
        urdf_robo: urdf_rs::Robot,
        base_dir: Option<&'a Path>,
        mut end_link_names: Vec<String>,
        is_collision: bool,
        disable_texture: bool,
    ) -> Self {
        let robot = k::LinkTree::<f32>::from_urdf_robot(&urdf_robo);
        let mut viewer = urdf_viz::Viewer::new("urdf-viz");
        if disable_texture {
            viewer.disable_texture();
        }
        viewer.add_robot_with_base_dir_and_collision_flag(&urdf_robo, base_dir, is_collision);
        viewer.add_axis_cylinders("origin", 1.0);
        if end_link_names.is_empty() {
            end_link_names = robot
                .iter_joints()
                .filter(|node| node.borrow().children.is_empty())
                .map(|node| node.borrow().data.name.to_owned())
                .collect::<Vec<_>>();
        }
        println!("end_link_names = {:?}", end_link_names);
        let arms = end_link_names
            .iter()
            .filter_map(|end_name| robot.new_chain(&end_name))
            .collect::<Vec<_>>();
        let joint_names = robot.joint_names();
        let num_arms = arms.len();
        let dof = robot.dof();
        let link_names = robot
            .iter_joints_link()
            .map(|link| link.name.to_string())
            .collect();
        UrdfViewerApp {
            viewer,
            arms,
            link_names,
            urdf_robot: urdf_robo,
            base_dir,
            robot,
            num_arms,
            num_joints: joint_names.len(),
            joint_names,
            index_of_arm: LoopIndex::new(num_arms),
            index_of_move_joint: LoopIndex::new(dof),
        }
    }
    fn has_arms(&self) -> bool {
        self.num_arms > 0
    }
    fn has_joints(&self) -> bool {
        self.num_joints > 0
    }
    fn init(&mut self) {
        self.update_robot();
        if self.has_arms() {
            self.viewer.add_axis_cylinders("ik_target", 0.2);
            self.update_ik_target_marker();
        }
    }
    fn get_arm(&mut self) -> &mut k::LinkChain<f32> {
        &mut self.arms[self.index_of_arm.get()]
    }
    fn update_ik_target_marker(&mut self) {
        if self.has_arms() {
            let trans = self.get_arm().end_transform();
            self.viewer.scene_node_mut("ik_target").map(|obj| {
                obj.set_local_transformation(trans);
            });
        }
    }
    fn update_robot(&mut self) {
        // this is hack to handle invalid mimic joints, like hsr
        let joint_angles = self.robot.joint_angles();
        self.robot
            .set_joint_angles(&joint_angles)
            .unwrap_or_else(|err| println!("failed to update robot joints {}", err));
        self.viewer.update(&self.robot);
        self.update_ik_target_marker();
    }
    fn run(&mut self) {
        let mut is_ctrl = false;
        let mut is_shift = false;
        let mut is_collision = false;
        let mut last_cur_pos_y = 0f64;
        let mut last_cur_pos_x = 0f64;
        let solver = k::JacobianIKSolverBuilder::new().finalize();

        while self.viewer.render() {
            self.viewer.draw_text(
                HOW_TO_USE_STR,
                40,
                &na::Point2::new(2000.0, 10.0),
                &na::Point3::new(1f32, 1.0, 1.0),
            );
            if self.has_joints() {
                self.viewer.draw_text(
                    &format!(
                        "moving joint name [{}]",
                        self.joint_names[self.index_of_move_joint.get()]
                    ),
                    60,
                    &na::Point2::new(10f32, 20.0),
                    &na::Point3::new(0.5f32, 0.5, 1.0),
                );
            }
            if self.has_arms() {
                let name = self.get_arm().name.to_owned();
                self.viewer.draw_text(
                    &format!("IK target name [{}]", name),
                    60,
                    &na::Point2::new(10f32, 100.0),
                    &na::Point3::new(0.5f32, 0.8, 0.2),
                );
            }
            if is_ctrl && !is_shift {
                self.viewer.draw_text(
                    "moving joint by drag",
                    60,
                    &na::Point2::new(10f32, 150.0),
                    &na::Point3::new(0.9f32, 0.5, 1.0),
                );
            }
            if is_shift {
                self.viewer.draw_text(
                    "solving ik",
                    60,
                    &na::Point2::new(10f32, 150.0),
                    &na::Point3::new(0.9f32, 0.5, 1.0),
                );
            }
            for mut event in self.viewer.events().iter() {
                match event.value {
                    WindowEvent::MouseButton(_, Action::Press, mods) => {
                        if mods.contains(NATIVE_MOD) {
                            is_ctrl = true;
                            event.inhibited = true;
                        }
                        if mods.contains(glfw::modifiers::Shift) {
                            is_shift = true;
                            event.inhibited = true;
                        }
                    }
                    WindowEvent::CursorPos(x, y) => {
                        if is_ctrl && !is_shift {
                            event.inhibited = true;
                            let move_gain = 0.005;
                            if self.has_joints() {
                                move_joint_by_index(
                                    self.index_of_move_joint.get(),
                                    (((x - last_cur_pos_x) + (y - last_cur_pos_y)) * move_gain)
                                        as f32,
                                    &mut self.robot,
                                ).unwrap_or(());
                                self.update_robot();
                            }
                        }
                        if is_shift {
                            event.inhibited = true;
                            if self.has_arms() {
                                let mut target = self.get_arm().end_transform();
                                let ik_move_gain = 0.002;
                                target.translation.vector[2] -=
                                    ((y - last_cur_pos_y) * ik_move_gain) as f32;
                                if is_ctrl {
                                    target.translation.vector[0] +=
                                        ((x - last_cur_pos_x) * ik_move_gain) as f32;
                                } else {
                                    target.translation.vector[1] +=
                                        ((x - last_cur_pos_x) * ik_move_gain) as f32;
                                }

                                self.update_ik_target_marker();
                                {
                                    let arm = self.get_arm();
                                    solver.solve(arm, &target).unwrap_or_else(|err| {
                                        println!("Err: {}", err);
                                        0.0f32
                                    });
                                }
                                self.update_robot();
                            }
                        }
                        last_cur_pos_x = x;
                        last_cur_pos_y = y;
                    }
                    WindowEvent::MouseButton(_, Action::Release, _) => if is_ctrl {
                        is_ctrl = false;
                        event.inhibited = true;
                    } else if is_shift {
                        is_shift = false;
                        event.inhibited = true;
                    },
                    WindowEvent::Key(code, _, Action::Press, _) => {
                        match code {
                            Key::LeftBracket => {
                                self.viewer.reset_temporal_color(
                                    &self.link_names[self.index_of_move_joint.get()],
                                );
                                self.index_of_move_joint.inc();
                                self.viewer.set_temporal_color(
                                    &self.link_names[self.index_of_move_joint.get()],
                                    1.0,
                                    0.0,
                                    0.0,
                                );
                            }
                            Key::RightBracket => {
                                self.viewer.reset_temporal_color(
                                    &self.link_names[self.index_of_move_joint.get()],
                                );
                                self.index_of_move_joint.dec();
                                self.viewer.set_temporal_color(
                                    &self.link_names[self.index_of_move_joint.get()],
                                    1.0,
                                    0.0,
                                    0.0,
                                );
                            }
                            Key::Period => {
                                self.index_of_arm.inc();
                                self.update_ik_target_marker();
                            }
                            Key::Comma => {
                                self.index_of_arm.dec();
                                self.update_ik_target_marker();
                            }
                            Key::C => {
                                self.viewer.remove_robot(&self.urdf_robot);
                                is_collision = !is_collision;
                                self.viewer.add_robot_with_base_dir_and_collision_flag(
                                    &self.urdf_robot,
                                    self.base_dir,
                                    is_collision,
                                );
                                self.update_robot();
                            }
                            Key::R => if self.has_joints() {
                                move_joint_by_random(&mut self.robot).unwrap_or(());
                                self.update_robot();
                            },
                            Key::Up => if self.has_joints() {
                                move_joint_by_index(
                                    self.index_of_move_joint.get(),
                                    0.1,
                                    &mut self.robot,
                                ).unwrap_or(());
                                self.update_robot();
                            },
                            Key::Down => if self.has_joints() {
                                move_joint_by_index(
                                    self.index_of_move_joint.get(),
                                    0.1,
                                    &mut self.robot,
                                ).unwrap_or(());
                                self.update_robot();
                            },
                            _ => {}
                        };
                        event.inhibited = true;
                    }
                    _ => {}
                }
            }
        }
    }
}

#[derive(StructOpt, Debug)]
#[structopt(name = "urdf_viz", about = "Option for visualizing urdf")]
pub struct Opt {
    #[structopt(help = "Input urdf or xacro")] pub input_urdf_or_xacro: String,
    #[structopt(short = "e", long = "end-link-name", help = "end link names")]
    pub end_link_names: Vec<String>,
    #[structopt(short = "c", long = "collision",
                help = "Show collision element instead of visual")]
    pub is_collision: bool,
    #[structopt(short = "d", long = "disable-texture", help = "Disable texture rendering")]
    pub disable_texture: bool,
}

fn main() {
    env_logger::init().unwrap();
    let opt = Opt::from_args();
    let input_path = Path::new(&opt.input_urdf_or_xacro);
    let base_dir = input_path.parent();
    let urdf_robo = urdf_rs::utils::read_urdf_or_xacro(input_path).unwrap();
    let mut app = UrdfViewerApp::new(
        urdf_robo,
        base_dir,
        opt.end_link_names,
        opt.is_collision,
        opt.disable_texture,
    );
    app.init();
    app.run();
}
<commit_msg>Fix bug of out of bounds and rotation direction<commit_after>/*
   Copyright 2017 Takashi Ogura

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

extern crate env_logger;
extern crate glfw;
extern crate k;
extern crate nalgebra as na;
extern crate rand;
extern crate structopt;
#[macro_use]
extern crate structopt_derive;
extern crate urdf_rs;
extern crate urdf_viz;

use glfw::{Action, Key, WindowEvent};
use k::InverseKinematicsSolver;
use k::KinematicChain;
use k::JointContainer;
use k::urdf::FromUrdf;
use k::ChainContainer;
use std::path::Path;
use structopt::StructOpt;

#[cfg(target_os = "macos")]
static NATIVE_MOD: glfw::modifiers::Modifiers = glfw::modifiers::Super;

#[cfg(not(target_os = "macos"))]
static NATIVE_MOD: glfw::modifiers::Modifiers = glfw::modifiers::Control;

fn move_joint_by_random(robot: &mut k::LinkTree<f32>) -> Result<(), k::JointError> {
    let angles_vec = robot
        .iter_joints_link()
        .map(|link| match link.joint.limits {
            Some(ref range) => (range.max - range.min) * rand::random::<f32>() + range.min,
            None => (rand::random::<f32>() - 0.5) * 2.0,
        })
        .collect::<Vec<f32>>();
    robot.set_joint_angles(&angles_vec)
}

fn move_joint_by_index(
    index: usize,
    diff_angle: f32,
    robot: &mut k::LinkTree<f32>,
) -> Result<(), k::JointError> {
    let mut angles_vec = robot.joint_angles();
    assert!(index < robot.dof());
    angles_vec[index] += diff_angle;
    robot.set_joint_angles(&angles_vec)
}

struct LoopIndex {
    index: usize,
    size: usize,
}

impl LoopIndex {
    fn new(size: usize) -> Self {
        Self {
            index: 0,
            size: size,
        }
    }
    fn get(&self) -> usize {
        self.index
    }
    fn inc(&mut self) {
        if self.size != 0 {
            self.index += 1;
            self.index %= self.size;
        }
    }
    fn dec(&mut self) {
        if self.size != 0 {
            if self.index == 0 {
                self.index = self.size - 1;
            } else {
                self.index -= 1;
            }
        }
    }
}

const HOW_TO_USE_STR: &'static str = r"
[:    joint ID +1
]:    joint ID -1
,:    IK target ID +1
.:    IK target ID -1
r:    set random angles
Up:   joint angle +0.1
Down: joint angle -0.1
Ctrl+Drag: move joint
Shift+Drag: IK (y, z)
Shift+Ctrl+Drag: IK (x, z)
c:    toggle visual/collision
";

struct UrdfViewerApp<'a> {
    urdf_robot: urdf_rs::Robot,
    robot: k::LinkTree<f32>,
    viewer: urdf_viz::Viewer,
    arms: Vec<k::LinkChain<f32>>,
    joint_names: Vec<String>,
    link_names: Vec<String>,
    num_arms: usize,
    num_joints: usize,
    index_of_arm: LoopIndex,
    index_of_move_joint: LoopIndex,
    base_dir: Option<&'a Path>,
}

impl<'a> UrdfViewerApp<'a> {
    fn new(
        urdf_robo: urdf_rs::Robot,
        base_dir: Option<&'a Path>,
        mut end_link_names: Vec<String>,
        is_collision: bool,
        disable_texture: bool,
    ) -> Self {
        let robot = k::LinkTree::<f32>::from_urdf_robot(&urdf_robo);
        let mut viewer = urdf_viz::Viewer::new("urdf-viz");
        if disable_texture {
            viewer.disable_texture();
        }
        viewer.add_robot_with_base_dir_and_collision_flag(&urdf_robo, base_dir, is_collision);
        viewer.add_axis_cylinders("origin", 1.0);
        if end_link_names.is_empty() {
            end_link_names = robot
                .iter_joints()
                .filter(|node| node.borrow().children.is_empty())
                .map(|node| node.borrow().data.name.to_owned())
                .collect::<Vec<_>>();
        }
        println!("end_link_names = {:?}", end_link_names);
        let arms = end_link_names
            .iter()
            .filter_map(|end_name| robot.new_chain(&end_name))
            .collect::<Vec<_>>();
        let joint_names = robot.joint_names();
        let num_arms = arms.len();
        let dof = robot.dof();
        let link_names = robot
            .iter_joints_link()
            .map(|link| link.name.to_string())
            .collect();
        UrdfViewerApp {
            viewer,
            arms,
            link_names,
            urdf_robot: urdf_robo,
            base_dir,
            robot,
            num_arms,
            num_joints: joint_names.len(),
            joint_names,
            index_of_arm: LoopIndex::new(num_arms),
            index_of_move_joint: LoopIndex::new(dof),
        }
    }
    fn has_arms(&self) -> bool {
        self.num_arms > 0
    }
    fn has_joints(&self) -> bool {
        self.num_joints > 0
    }
    fn init(&mut self) {
        self.update_robot();
        if self.has_arms() {
            self.viewer.add_axis_cylinders("ik_target", 0.2);
            self.update_ik_target_marker();
        }
    }
    fn get_arm(&mut self) -> &mut k::LinkChain<f32> {
        &mut self.arms[self.index_of_arm.get()]
    }
    fn update_ik_target_marker(&mut self) {
        if self.has_arms() {
            let trans = self.get_arm().end_transform();
            self.viewer.scene_node_mut("ik_target").map(|obj| {
                obj.set_local_transformation(trans);
            });
        }
    }
    fn update_robot(&mut self) {
        // this is hack to handle invalid mimic joints, like hsr
        let joint_angles = self.robot.joint_angles();
        self.robot
            .set_joint_angles(&joint_angles)
            .unwrap_or_else(|err| println!("failed to update robot joints {}", err));
        self.viewer.update(&self.robot);
        self.update_ik_target_marker();
    }
    fn run(&mut self) {
        let mut is_ctrl = false;
        let mut is_shift = false;
        let mut is_collision = false;
        let mut last_cur_pos_y = 0f64;
        let mut last_cur_pos_x = 0f64;
        let solver = k::JacobianIKSolverBuilder::new().finalize();

        while self.viewer.render() {
            self.viewer.draw_text(
                HOW_TO_USE_STR,
                40,
                &na::Point2::new(2000.0, 10.0),
                &na::Point3::new(1f32, 1.0, 1.0),
            );
            if self.has_joints() {
                self.viewer.draw_text(
                    &format!(
                        "moving joint name [{}]",
                        self.joint_names[self.index_of_move_joint.get()]
                    ),
                    60,
                    &na::Point2::new(10f32, 20.0),
                    &na::Point3::new(0.5f32, 0.5, 1.0),
                );
            }
            if self.has_arms() {
                let name = self.get_arm().name.to_owned();
                self.viewer.draw_text(
                    &format!("IK target name [{}]", name),
                    60,
                    &na::Point2::new(10f32, 100.0),
                    &na::Point3::new(0.5f32, 0.8, 0.2),
                );
            }
            if is_ctrl && !is_shift {
                self.viewer.draw_text(
                    "moving joint by drag",
                    60,
                    &na::Point2::new(10f32, 150.0),
                    &na::Point3::new(0.9f32, 0.5, 1.0),
                );
            }
            if is_shift {
                self.viewer.draw_text(
                    "solving ik",
                    60,
                    &na::Point2::new(10f32, 150.0),
                    &na::Point3::new(0.9f32, 0.5, 1.0),
                );
            }
            for mut event in self.viewer.events().iter() {
                match event.value {
                    WindowEvent::MouseButton(_, Action::Press, mods) => {
                        if mods.contains(NATIVE_MOD) {
                            is_ctrl = true;
                            event.inhibited = true;
                        }
                        if mods.contains(glfw::modifiers::Shift) {
                            is_shift = true;
                            event.inhibited = true;
                        }
                    }
                    WindowEvent::CursorPos(x, y) => {
                        if is_ctrl && !is_shift {
                            event.inhibited = true;
                            let move_gain = 0.005;
                            if self.has_joints() {
                                move_joint_by_index(
                                    self.index_of_move_joint.get(),
                                    (((x - last_cur_pos_x) + (y - last_cur_pos_y)) * move_gain)
                                        as f32,
                                    &mut self.robot,
                                ).unwrap_or(());
                                self.update_robot();
                            }
                        }
                        if is_shift {
                            event.inhibited = true;
                            if self.has_arms() {
                                let mut target = self.get_arm().end_transform();
                                let ik_move_gain = 0.002;
                                target.translation.vector[2] -=
                                    ((y - last_cur_pos_y) * ik_move_gain) as f32;
                                if is_ctrl {
                                    target.translation.vector[0] +=
                                        ((x - last_cur_pos_x) * ik_move_gain) as f32;
                                } else {
                                    target.translation.vector[1] +=
                                        ((x - last_cur_pos_x) * ik_move_gain) as f32;
                                }

                                self.update_ik_target_marker();
                                {
                                    let arm = self.get_arm();
                                    solver.solve(arm, &target).unwrap_or_else(|err| {
                                        println!("Err: {}", err);
                                        0.0f32
                                    });
                                }
                                self.update_robot();
                            }
                        }
                        last_cur_pos_x = x;
                        last_cur_pos_y = y;
                    }
                    WindowEvent::MouseButton(_, Action::Release, _) => if is_ctrl {
                        is_ctrl = false;
                        event.inhibited = true;
                    } else if is_shift {
                        is_shift = false;
                        event.inhibited = true;
                    },
                    WindowEvent::Key(code, _, Action::Press, _) => {
                        match code {
                            Key::LeftBracket => if self.has_joints() {
                                self.viewer.reset_temporal_color(
                                    &self.link_names[self.index_of_move_joint.get()],
                                );
                                self.index_of_move_joint.inc();
                                self.viewer.set_temporal_color(
                                    &self.link_names[self.index_of_move_joint.get()],
                                    1.0,
                                    0.0,
                                    0.0,
                                );
                            },
                            Key::RightBracket => if self.has_joints() {
                                self.viewer.reset_temporal_color(
                                    &self.link_names[self.index_of_move_joint.get()],
                                );
                                self.index_of_move_joint.dec();
                                self.viewer.set_temporal_color(
                                    &self.link_names[self.index_of_move_joint.get()],
                                    1.0,
                                    0.0,
                                    0.0,
                                );
                            },
                            Key::Period => {
                                self.index_of_arm.inc();
                                self.update_ik_target_marker();
                            }
                            Key::Comma => {
                                self.index_of_arm.dec();
                                self.update_ik_target_marker();
                            }
                            Key::C => {
                                self.viewer.remove_robot(&self.urdf_robot);
                                is_collision = !is_collision;
                                self.viewer.add_robot_with_base_dir_and_collision_flag(
                                    &self.urdf_robot,
                                    self.base_dir,
                                    is_collision,
                                );
                                self.update_robot();
                            }
                            Key::R => if self.has_joints() {
                                move_joint_by_random(&mut self.robot).unwrap_or(());
                                self.update_robot();
                            },
                            Key::Up => if self.has_joints() {
                                move_joint_by_index(
                                    self.index_of_move_joint.get(),
                                    0.1,
                                    &mut self.robot,
                                ).unwrap_or(());
                                self.update_robot();
                            },
                            Key::Down => if self.has_joints() {
                                move_joint_by_index(
                                    self.index_of_move_joint.get(),
                                    -0.1,
                                    &mut self.robot,
                                ).unwrap_or(());
                                self.update_robot();
                            },
                            _ => {}
                        };
                        event.inhibited = true;
                    }
                    _ => {}
                }
            }
        }
    }
}

#[derive(StructOpt, Debug)]
#[structopt(name = "urdf_viz", about = "Option for visualizing urdf")]
pub struct Opt {
    #[structopt(help = "Input urdf or xacro")] pub input_urdf_or_xacro: String,
    #[structopt(short = "e", long = "end-link-name", help = "end link names")]
    pub end_link_names: Vec<String>,
    #[structopt(short = "c", long = "collision",
                help = "Show collision element instead of visual")]
    pub is_collision: bool,
    #[structopt(short = "d", long = "disable-texture", help = "Disable texture rendering")]
    pub disable_texture: bool,
}

fn main() {
    env_logger::init().unwrap();
    let opt = Opt::from_args();
    let input_path = Path::new(&opt.input_urdf_or_xacro);
    let base_dir = input_path.parent();
    let urdf_robo = urdf_rs::utils::read_urdf_or_xacro(input_path).unwrap();
    let mut app = UrdfViewerApp::new(
        urdf_robo,
        base_dir,
        opt.end_link_names,
        opt.is_collision,
        opt.disable_texture,
    );
    app.init();
    app.run();
}
<|endoftext|>


<commit_before>#[feature(macro_rules)];

use std::result::{Result,Ok,Err};

#[deriving(Eq,Show)]
enum SmtpCommand<'a> {
  MAIL(&'a str),
  RCPT(&'a str),
  DATA,
}

#[deriving(Eq,Show)]
enum ParseError {
  SyntaxError(&'static str),
  UnknownCommand,
}

fn ascii_eq_ignore_case(a: &[u8], b: &[u8]) -> bool {
  if a.len() == b.len() {
    a.to_ascii().eq_ignore_case(b.to_ascii())
  }
  else {
    false
  }
}

fn parse_command<'a>(line: &'a[u8]) -> Result<SmtpCommand<'a>, ParseError>  {
    let cmd = line.slice(0, 4);
    if ascii_eq_ignore_case(cmd, bytes!("MAIL")) {
        if ascii_eq_ignore_case(line.slice(4, 11), bytes!(" FROM:<")) {
            let addr = line.slice(11, line.len() - 3);
            let rem = line.slice_from(line.len() - 3);
            if rem == bytes!(">\r\n") {
                Ok(MAIL(std::str::from_utf8(addr).unwrap()))
            }
            else {
                Err(SyntaxError("Invalid MAIL command"))
            }
        }
        else {
            Err(SyntaxError("Invalid MAIL command"))
        }
    }
    else {
      Err(UnknownCommand)
    }
}

macro_rules! assert_match(
    ($given:expr , $pattern:pat) => ({
        let given_val = $given;
        match given_val {
          $pattern => {}
          _ => {
             fail!("assertion failed: `value does not match pattern`");
          }
        }
    })
)

/*
macro_rules! assert_eq_parse_command (
  ($str:expr, $exp:expr) => (
    match bytes!($str) {
      cmd => assert_eq!(parse_command(cmd), $exp)
    }
  )
)
*/

macro_rules! test_parse_command (
  ($str:expr, $pat:pat) => (
    match bytes!($str) {
      cmd => assert_match!(parse_command(cmd), $pat)
    }
  )
)

#[test]
fn test_commands() {
  test_parse_command!("MAIL FROM:<mneumann@ntecs.de>\r\n", Ok(MAIL("mneumann@ntecs.de")));
  test_parse_command!("MAIL FROM:<mneumann@ntecs.de>\r", Err(_));
}

fn main() {
  let buf = bytes!("MAIL FROM:<mneumann@ntecs.de>\r\n");
  let cmd = parse_command(buf);
  println!("{}", cmd);
}
<commit_msg>Implement little bit more<commit_after>#[feature(macro_rules)];

use std::result::{Result,Ok,Err};

#[deriving(Eq,Show)]
enum SmtpCommand<'a> {
  MAIL(&'a str),
  RCPT(&'a str),
  DATA,
}

#[deriving(Eq,Show)]
enum ParseError {
  SyntaxError(&'static str),
  InvalidLineEnding,
  UnknownCommand,
}

fn ascii_eq_ignore_case(a: &[u8], b: &[u8]) -> bool {
  if a.len() == b.len() {
    a.to_ascii().eq_ignore_case(b.to_ascii())
  }
  else {
    false
  }
}

fn parse_command<'a>(line: &'a[u8]) -> Result<SmtpCommand<'a>, ParseError>  {
    if line.len() < 2 {
      return Err(InvalidLineEnding);
    }

    let crlf = line.slice(line.len() - 2, line.len());
    if crlf != bytes!("\r\n") {
      return Err(InvalidLineEnding);
    }

    let line = line.initn(2); // drop off line ending

    let cmd = line.slice(0, 4);
    if ascii_eq_ignore_case(cmd, bytes!("MAIL")) {
        if ascii_eq_ignore_case(line.slice(4, 11), bytes!(" FROM:<")) {
            let addr = line.slice_from(11).init();
            let rem = line.slice_from(line.len() - 1);
            if rem == bytes!(">") {
                // XXX: Verify mail addr
                Ok(MAIL(std::str::from_utf8(addr).unwrap()))
            }
            else {
                Err(SyntaxError("Invalid MAIL command: Missing >"))
            }
        }
        else {
            Err(SyntaxError("Invalid MAIL command"))
        }
    }
    else if ascii_eq_ignore_case(cmd, bytes!("DATA")) {
      if line.slice_from(4).len() == 0 {
          Ok(DATA)
      }
      else {
          Err(SyntaxError("Invalid DATA command"))
      }
    }
    else {
      Err(UnknownCommand)
    }
}

macro_rules! assert_match(
    ($given:expr , $pattern:pat) => ({
        let given_val = $given;
        match given_val {
          $pattern => {}
          _ => {
             fail!("assertion failed: `value does not match pattern`");
          }
        }
    })
)

macro_rules! test_parse_command (
  ($str:expr, $pat:pat) => (
    match bytes!($str) {
      cmd => assert_match!(parse_command(cmd), $pat)
    }
  )
)

#[test]
fn test_commands() {
  //test_parse_command!("", Err(InvalidLineEnding));
  test_parse_command!("\r", Err(InvalidLineEnding));
  test_parse_command!("\n", Err(InvalidLineEnding));
  test_parse_command!("\n\r", Err(InvalidLineEnding));
  test_parse_command!("MAIL FROM:<mneumann@ntecs.de>", Err(InvalidLineEnding));
  test_parse_command!("MAIL FROM:<mneumann@ntecs.de>\r", Err(InvalidLineEnding));
  test_parse_command!("MAIL FROM:<mneumann@ntecs.de>\n", Err(InvalidLineEnding));
  test_parse_command!("MAIL FROM:<mneumann@ntecs.de>\n\r", Err(InvalidLineEnding));

  test_parse_command!("MAIL FROM:<mneumann@ntecs.de\r\n", Err(SyntaxError("Invalid MAIL command: Missing >")));

  test_parse_command!("MAIL FROM:<mneumann@ntecs.de>\r\n", Ok(MAIL("mneumann@ntecs.de")));

  test_parse_command!("DATA\r\n", Ok(DATA));
  test_parse_command!("data\r\n", Ok(DATA));
  test_parse_command!("data test\r\n", Err(SyntaxError("Invalid DATA command")));
}

fn main() {
  let buf = bytes!("MAIL FROM:<mneumann@ntecs.de>\r\n");
  let cmd = parse_command(buf);
  println!("{}", cmd);
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]

#[macro_use]
extern crate askama_derive;
extern crate askama;

use askama::Template;

#[derive(Template)]
#[template(path = "simple.html")]
struct VariablesTemplate {
    strvar: String,
    num: i64,
    i18n: String,
}

#[test]
fn test_variables() {
    let s = VariablesTemplate {
        strvar: "foo".to_string(),
        num: 42,
        i18n: "Iñtërnâtiônàlizætiøn".to_string(),
    };
    assert_eq!(s.render(), "hello world, foo\n\
                            with number: 42\n\
                            Iñtërnâtiônàlizætiøn is important\n\
                            in vars too: Iñtërnâtiônàlizætiøn\n");
}

#[derive(Template)]
#[template(path = "if.html")]
struct IfTemplate {
    cond: bool,
}

#[test]
fn test_if() {
    let s = IfTemplate { cond: true };
    assert_eq!(s.render(), "true\n");
}

#[derive(Template)]
#[template(path = "else.html")]
struct ElseTemplate {
    cond: bool,
}

#[test]
fn test_else() {
    let s = ElseTemplate { cond: false };
    assert_eq!(s.render(), "false\n");
}
<commit_msg>Add test for elif blocks<commit_after>#![feature(proc_macro)]

#[macro_use]
extern crate askama_derive;
extern crate askama;

use askama::Template;

#[derive(Template)]
#[template(path = "simple.html")]
struct VariablesTemplate {
    strvar: String,
    num: i64,
    i18n: String,
}

#[test]
fn test_variables() {
    let s = VariablesTemplate {
        strvar: "foo".to_string(),
        num: 42,
        i18n: "Iñtërnâtiônàlizætiøn".to_string(),
    };
    assert_eq!(s.render(), "hello world, foo\n\
                            with number: 42\n\
                            Iñtërnâtiônàlizætiøn is important\n\
                            in vars too: Iñtërnâtiônàlizætiøn\n");
}

#[derive(Template)]
#[template(path = "if.html")]
struct IfTemplate {
    cond: bool,
}

#[test]
fn test_if() {
    let s = IfTemplate { cond: true };
    assert_eq!(s.render(), "true\n");
}

#[derive(Template)]
#[template(path = "else.html")]
struct ElseTemplate {
    cond: bool,
}

#[test]
fn test_else() {
    let s = ElseTemplate { cond: false };
    assert_eq!(s.render(), "false\n");
}

#[derive(Template)]
#[template(path = "elif.html")]
struct ElIfTemplate {
    cond: bool,
    check: bool,
}

#[test]
fn test_elif() {
    let s = ElIfTemplate { cond: false, check: true };
    assert_eq!(s.render(), "checked\n");
}
<|endoftext|>


<commit_before>// # References
//
// - Section 7.4 "Hints" of ACLE
// - Section 7.7 "NOP" of ACLE

/// Generates a WFI (wait for interrupt) hint instruction, or nothing.
///
/// The WFI instruction allows (but does not require) the processor to enter a
/// low-power state until one of a number of asynchronous events occurs.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
// LLVM says "instruction requires: armv6k"
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
#[inline(always)]
pub unsafe fn __wfi() {
    hint(HINT_WFI);
}

/// Generates a WFE (wait for event) hint instruction, or nothing.
///
/// The WFE instruction allows (but does not require) the processor to enter a
/// low-power state until some event occurs such as a SEV being issued by
/// another processor.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
// LLVM says "instruction requires: armv6k"
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
#[inline(always)]
pub unsafe fn __wfe() {
    hint(HINT_WFE);
}

/// Generates a SEV (send a global event) hint instruction.
///
/// This causes an event to be signaled to all processors in a multiprocessor
/// system. It is a NOP on a uniprocessor system.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M, 7-M
// LLVM says "instruction requires: armv6k"
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
#[inline(always)]
pub unsafe fn __sev() {
    hint(HINT_SEV);
}

/// Generates a send a local event hint instruction.
///
/// This causes an event to be signaled to only the processor executing this
/// instruction. In a multiprocessor system, it is not required to affect the
/// other processors.
// LLVM says "instruction requires: armv8"
#[cfg(target_arch = "aarch64")]
#[inline(always)]
pub unsafe fn __sevl() {
    hint(HINT_SEVL);
}

/// Generates a YIELD hint instruction.
///
/// This enables multithreading software to indicate to the hardware that it is
/// performing a task, for example a spin-lock, that could be swapped out to
/// improve overall system performance.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
// LLVM says "instruction requires: armv6k"
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
#[inline(always)]
pub unsafe fn __yield() {
    hint(HINT_YIELD);
}

/// Generates a DBG instruction.
///
/// This provides a hint to debugging and related systems. The argument must be
/// a constant integer from 0 to 15 inclusive. See implementation documentation
/// for the effect (if any) of this instruction and the meaning of the
/// argument. This is available only when compliling for AArch32.
// Section 10.1 of ACLE says that the supported arches are: 7, 7-M
// "The DBG hint instruction is added in ARMv7. It is UNDEFINED in the ARMv6 base architecture, and
// executes as a NOP instruction in ARMv6K and ARMv6T2." - ARM Architecture Reference Manual ARMv7-A
// and ARMv7-R edition (ARM DDI 0406C.c) sections D12.4.1 "ARM instruction set support" and D12.4.2
// "Thumb instruction set support"
#[cfg(target_feature = "v7")]
#[inline(always)]
#[rustc_args_required_const(0)]
pub unsafe fn __dbg(imm4: u32) {
    macro_rules! call {
        ($imm4:expr) => {
            asm!(concat!("DBG ", stringify!($imm4)) : : : : "volatile")
        }
    }

    match imm4 & 0b1111 {
        0 => call!(0),
        1 => call!(1),
        2 => call!(2),
        3 => call!(3),
        4 => call!(4),
        5 => call!(5),
        6 => call!(6),
        7 => call!(7),
        8 => call!(8),
        9 => call!(9),
        10 => call!(10),
        11 => call!(11),
        12 => call!(12),
        13 => call!(13),
        14 => call!(14),
        _ => call!(15),
    }
}

/// Generates an unspecified no-op instruction.
///
/// Note that not all architectures provide a distinguished NOP instruction. On
/// those that do, it is unspecified whether this intrinsic generates it or
/// another instruction. It is not guaranteed that inserting this instruction
/// will increase execution time.
#[inline(always)]
pub unsafe fn __nop() {
    hint(HINT_NOP);
}

extern "C" {
    #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.hint")]
    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.hint")]
    fn hint(_: i32);
}

// from LLVM 7.0.1's lib/Target/ARM/{ARMInstrThumb,ARMInstrInfo,ARMInstrThumb2}.td
const HINT_NOP: i32 = 0;
const HINT_YIELD: i32 = 1;
const HINT_WFE: i32 = 2;
const HINT_WFI: i32 = 3;
const HINT_SEV: i32 = 4;
const HINT_SEVL: i32 = 5;
<commit_msg>acle/hints: use asm! for __nop<commit_after>// # References
//
// - Section 7.4 "Hints" of ACLE
// - Section 7.7 "NOP" of ACLE

/// Generates a WFI (wait for interrupt) hint instruction, or nothing.
///
/// The WFI instruction allows (but does not require) the processor to enter a
/// low-power state until one of a number of asynchronous events occurs.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
// LLVM says "instruction requires: armv6k"
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
#[inline(always)]
pub unsafe fn __wfi() {
    hint(HINT_WFI);
}

/// Generates a WFE (wait for event) hint instruction, or nothing.
///
/// The WFE instruction allows (but does not require) the processor to enter a
/// low-power state until some event occurs such as a SEV being issued by
/// another processor.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
// LLVM says "instruction requires: armv6k"
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
#[inline(always)]
pub unsafe fn __wfe() {
    hint(HINT_WFE);
}

/// Generates a SEV (send a global event) hint instruction.
///
/// This causes an event to be signaled to all processors in a multiprocessor
/// system. It is a NOP on a uniprocessor system.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M, 7-M
// LLVM says "instruction requires: armv6k"
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
#[inline(always)]
pub unsafe fn __sev() {
    hint(HINT_SEV);
}

/// Generates a send a local event hint instruction.
///
/// This causes an event to be signaled to only the processor executing this
/// instruction. In a multiprocessor system, it is not required to affect the
/// other processors.
// LLVM says "instruction requires: armv8"
#[cfg(target_arch = "aarch64")]
#[inline(always)]
pub unsafe fn __sevl() {
    hint(HINT_SEVL);
}

/// Generates a YIELD hint instruction.
///
/// This enables multithreading software to indicate to the hardware that it is
/// performing a task, for example a spin-lock, that could be swapped out to
/// improve overall system performance.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
// LLVM says "instruction requires: armv6k"
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
#[inline(always)]
pub unsafe fn __yield() {
    hint(HINT_YIELD);
}

/// Generates a DBG instruction.
///
/// This provides a hint to debugging and related systems. The argument must be
/// a constant integer from 0 to 15 inclusive. See implementation documentation
/// for the effect (if any) of this instruction and the meaning of the
/// argument. This is available only when compliling for AArch32.
// Section 10.1 of ACLE says that the supported arches are: 7, 7-M
// "The DBG hint instruction is added in ARMv7. It is UNDEFINED in the ARMv6 base architecture, and
// executes as a NOP instruction in ARMv6K and ARMv6T2." - ARM Architecture Reference Manual ARMv7-A
// and ARMv7-R edition (ARM DDI 0406C.c) sections D12.4.1 "ARM instruction set support" and D12.4.2
// "Thumb instruction set support"
#[cfg(target_feature = "v7")]
#[inline(always)]
#[rustc_args_required_const(0)]
pub unsafe fn __dbg(imm4: u32) {
    macro_rules! call {
        ($imm4:expr) => {
            asm!(concat!("DBG ", stringify!($imm4)) : : : : "volatile")
        }
    }

    match imm4 & 0b1111 {
        0 => call!(0),
        1 => call!(1),
        2 => call!(2),
        3 => call!(3),
        4 => call!(4),
        5 => call!(5),
        6 => call!(6),
        7 => call!(7),
        8 => call!(8),
        9 => call!(9),
        10 => call!(10),
        11 => call!(11),
        12 => call!(12),
        13 => call!(13),
        14 => call!(14),
        _ => call!(15),
    }
}

/// Generates an unspecified no-op instruction.
///
/// Note that not all architectures provide a distinguished NOP instruction. On
/// those that do, it is unspecified whether this intrinsic generates it or
/// another instruction. It is not guaranteed that inserting this instruction
/// will increase execution time.
#[inline(always)]
pub unsafe fn __nop() {
    asm!("NOP" : : : : "volatile")
}

extern "C" {
    #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.hint")]
    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.hint")]
    fn hint(_: i32);
}

// from LLVM 7.0.1's lib/Target/ARM/{ARMInstrThumb,ARMInstrInfo,ARMInstrThumb2}.td
const HINT_NOP: i32 = 0;
const HINT_YIELD: i32 = 1;
const HINT_WFE: i32 = 2;
const HINT_WFI: i32 = 3;
const HINT_SEV: i32 = 4;
const HINT_SEVL: i32 = 5;
<|endoftext|>