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

mod convert;

pub use convert::{FromLossy, IntoLossy};

use log::error;

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

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

impl From<bool> for DataBlob {

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

impl From<i64> for DataBlob {

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

impl From<f32> for DataBlob {

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

impl From<Vec<u8>> for DataBlob {

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

impl From<String> for DataBlob {

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

impl KeyValue {

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

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

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

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

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

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

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

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

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

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

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

        // TODO: `ctime` is actually not creation time on Linux (it is the inode
        // change time). `StatEntry` is lacking in this regard and mixes just
        // mixes the two.
        let ctime_micros = match metadata.created().ok().map(micros) {
            Some(Ok(ctime_micros)) => Some(ctime_micros),
            Some(Err(err)) => {
                error!("failed to convert creation time: {}", err);
                None
            },
            None => None,
        };

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

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

impl std::fmt::Display for MicrosError {

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

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

impl std::error::Error for MicrosError {

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

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

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

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

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

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

/// Converts system time into epoch microseconds.
///
/// Because most GRR messages use epoch microseconds for representing timestamps
/// this function be be useful to convert from more idiomatic representations.
///
/// # Examples
///
/// ```
/// use rrg_proto::micros;
///
/// assert_eq!(micros(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn micros(time: std::time::SystemTime) -> Result<u64, MicrosError> {
    let time_micros = time.duration_since(std::time::UNIX_EPOCH)?.as_micros();
    Ok(std::convert::TryInto::try_into(time_micros)?)
}
<commit_msg>Separate metadata creation and inode change time.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

mod convert;

pub use convert::{FromLossy, IntoLossy};

use log::error;

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

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

impl From<bool> for DataBlob {

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

impl From<i64> for DataBlob {

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

impl From<f32> for DataBlob {

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

impl From<Vec<u8>> for DataBlob {

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

impl From<String> for DataBlob {

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

impl KeyValue {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

impl std::fmt::Display for MicrosError {

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

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

impl std::error::Error for MicrosError {

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

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

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

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

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

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

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


<commit_before>//! The [Axis Variations](https://docs.microsoft.com/en-us/typography/opentype/spec/avar) table

use font_types::Tag;

/// 'avar'
pub const TAG: Tag = Tag::new(b"avar");

include!("../../generated/generated_avar.rs");

impl<'a> Avar<'a> {
    // TODO: see comment in Post::traverse_string_data
    #[cfg(feature = "traversal")]
    fn traverse_segment_maps(&self) -> FieldType<'a> {
        FieldType::I8(-42) // meaningless value
    }
}

impl<'a> SegmentMaps<'a> {
    /// Applies the piecewise linear mapping to the specified coordinate.
    pub fn apply(&self, coord: Fixed) -> Fixed {
        let mut prev = AxisValueMap {
            from_coordinate: Default::default(),
            to_coordinate: Default::default(),
        };
        for (i, axis_value_map) in self.axis_value_maps().iter().enumerate() {
            use core::cmp::Ordering::*;
            let from = axis_value_map.from_coordinate().to_fixed();
            match from.cmp(&coord) {
                Equal => return axis_value_map.to_coordinate().to_fixed(),
                Greater => {
                    if i == 0 {
                        return coord;
                    }
                    let to = axis_value_map.to_coordinate().to_fixed();
                    let prev_from = prev.from_coordinate().to_fixed();
                    let prev_to = prev.to_coordinate().to_fixed();
                    return prev_to + (to - prev_to).mul_div(coord - prev_from, from - prev_from);
                }
                _ => {}
            }
            prev = axis_value_map.clone();
        }
        coord
    }
}

impl<'a> VarSize for SegmentMaps<'a> {
    type Size = u16;

    fn read_len_at(data: FontData, pos: usize) -> Option<usize> {
        Some(data.read_at::<u16>(pos).ok()? as usize * 4)
    }
}

#[cfg(test)]
mod tests {
    use crate::{test_data, FontRef, TableProvider};
    use font_types::{F2Dot14, Fixed};

    #[test]
    fn segment_maps() {
        let font = FontRef::new(test_data::test_fonts::VAZIRMATN_VAR).unwrap();
        let avar = font.avar().unwrap();
        assert_eq!(avar.axis_count(), 1);
        fn from_to(from: f32, to: f32) -> (F2Dot14, F2Dot14) {
            (F2Dot14::from_f32(from), F2Dot14::from_f32(to))
        }
        let expected_segment_maps = &[vec![
            from_to(-1.0, -1.0),
            from_to(-0.6667, -0.5),
            from_to(-0.3333, -0.25),
            from_to(0.0, 0.0),
            from_to(0.2, 0.3674),
            from_to(0.4, 0.52246),
            from_to(0.6, 0.67755),
            from_to(0.8, 0.83875),
            from_to(1.0, 1.0),
        ]];
        let segment_maps = avar
            .axis_segment_maps()
            .iter()
            .map(|segment_map| {
                segment_map
                    .unwrap()
                    .axis_value_maps()
                    .iter()
                    .map(|axis_value_map| {
                        (
                            axis_value_map.from_coordinate(),
                            axis_value_map.to_coordinate(),
                        )
                    })
                    .collect::<Vec<_>>()
            })
            .collect::<Vec<_>>();
        assert_eq!(&segment_maps, expected_segment_maps);
    }

    #[test]
    fn piecewise_linear() {
        let font = FontRef::new(test_data::test_fonts::VAZIRMATN_VAR).unwrap();
        let avar = font.avar().unwrap();
        let segment_map = avar.axis_segment_maps().get(0).unwrap().unwrap();
        let coords = [-1.0, -0.5, 0.0, 0.5, 1.0];
        let expected_result = [-1.0, -0.375, 0.0, 0.600006103515625, 1.0];
        assert_eq!(
            &expected_result[..],
            &coords
                .iter()
                .map(|coord| segment_map.apply(Fixed::from_f64(*coord)).to_f64())
                .collect::<Vec<_>>()
        );
    }
}
<commit_msg>replace magic number with AxisValueMap::RAW_BYTE_LEN<commit_after>//! The [Axis Variations](https://docs.microsoft.com/en-us/typography/opentype/spec/avar) table

use font_types::Tag;

/// 'avar'
pub const TAG: Tag = Tag::new(b"avar");

include!("../../generated/generated_avar.rs");

impl<'a> Avar<'a> {
    // TODO: see comment in Post::traverse_string_data
    #[cfg(feature = "traversal")]
    fn traverse_segment_maps(&self) -> FieldType<'a> {
        FieldType::I8(-42) // meaningless value
    }
}

impl<'a> SegmentMaps<'a> {
    /// Applies the piecewise linear mapping to the specified coordinate.
    pub fn apply(&self, coord: Fixed) -> Fixed {
        let mut prev = AxisValueMap {
            from_coordinate: Default::default(),
            to_coordinate: Default::default(),
        };
        for (i, axis_value_map) in self.axis_value_maps().iter().enumerate() {
            use core::cmp::Ordering::*;
            let from = axis_value_map.from_coordinate().to_fixed();
            match from.cmp(&coord) {
                Equal => return axis_value_map.to_coordinate().to_fixed(),
                Greater => {
                    if i == 0 {
                        return coord;
                    }
                    let to = axis_value_map.to_coordinate().to_fixed();
                    let prev_from = prev.from_coordinate().to_fixed();
                    let prev_to = prev.to_coordinate().to_fixed();
                    return prev_to + (to - prev_to).mul_div(coord - prev_from, from - prev_from);
                }
                _ => {}
            }
            prev = axis_value_map.clone();
        }
        coord
    }
}

impl<'a> VarSize for SegmentMaps<'a> {
    type Size = u16;

    fn read_len_at(data: FontData, pos: usize) -> Option<usize> {
        Some(data.read_at::<u16>(pos).ok()? as usize * AxisValueMap::RAW_BYTE_LEN)
    }
}

#[cfg(test)]
mod tests {
    use crate::{test_data, FontRef, TableProvider};
    use font_types::{F2Dot14, Fixed};

    #[test]
    fn segment_maps() {
        let font = FontRef::new(test_data::test_fonts::VAZIRMATN_VAR).unwrap();
        let avar = font.avar().unwrap();
        assert_eq!(avar.axis_count(), 1);
        fn from_to(from: f32, to: f32) -> (F2Dot14, F2Dot14) {
            (F2Dot14::from_f32(from), F2Dot14::from_f32(to))
        }
        let expected_segment_maps = &[vec![
            from_to(-1.0, -1.0),
            from_to(-0.6667, -0.5),
            from_to(-0.3333, -0.25),
            from_to(0.0, 0.0),
            from_to(0.2, 0.3674),
            from_to(0.4, 0.52246),
            from_to(0.6, 0.67755),
            from_to(0.8, 0.83875),
            from_to(1.0, 1.0),
        ]];
        let segment_maps = avar
            .axis_segment_maps()
            .iter()
            .map(|segment_map| {
                segment_map
                    .unwrap()
                    .axis_value_maps()
                    .iter()
                    .map(|axis_value_map| {
                        (
                            axis_value_map.from_coordinate(),
                            axis_value_map.to_coordinate(),
                        )
                    })
                    .collect::<Vec<_>>()
            })
            .collect::<Vec<_>>();
        assert_eq!(&segment_maps, expected_segment_maps);
    }

    #[test]
    fn piecewise_linear() {
        let font = FontRef::new(test_data::test_fonts::VAZIRMATN_VAR).unwrap();
        let avar = font.avar().unwrap();
        let segment_map = avar.axis_segment_maps().get(0).unwrap().unwrap();
        let coords = [-1.0, -0.5, 0.0, 0.5, 1.0];
        let expected_result = [-1.0, -0.375, 0.0, 0.600006103515625, 1.0];
        assert_eq!(
            &expected_result[..],
            &coords
                .iter()
                .map(|coord| segment_map.apply(Fixed::from_f64(*coord)).to_f64())
                .collect::<Vec<_>>()
        );
    }
}
<|endoftext|>


<commit_before>// extern crate bindgen;
#[cfg(target_env = "msvc")]
extern crate cc;
extern crate pkg_config;
extern crate num_cpus;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

// Automatically write bindings to libsass
//#[allow(dead_code)]
//fn write_bindings() {
//    let bindings = bindgen::Builder::default()
//        .header("libsass/include/sass.h")
//        .clang_arg("-Ilibsass/include")
//        // To avoid a test failing
//        .blacklist_type("max_align_t")
//        // we do static linking so it should be fine
//        // https://github.com/rust-lang/rust/issues/36927
//        .rustified_enum(".*")
//        .generate()
//        .expect("Unable to generate bindings");
//
//    // Write the bindings to the $OUT_DIR/bindings.rs file.
//    let out_path = PathBuf::from("src");
//    bindings
//        .write_to_file(out_path.join("bindings.rs"))
//        .expect("Couldn't write bindings!");
//}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => panic!("\n{} failed with {}\n", stringify!($e), e),
    })
}

fn cp_r(dir: &Path, dest: &Path) {
    for entry in t!(fs::read_dir(dir)) {
        let entry = t!(entry);
        let path = entry.path();
        let dst = dest.join(path.file_name().expect("Failed to get filename of path"));
        if t!(fs::metadata(&path)).is_file() {
            t!(fs::copy(path, dst));
        } else {
            t!(fs::create_dir_all(&dst));
            cp_r(&path, &dst);
        }
    }
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().expect("Failed to get the current directory").join("libsass")
}

#[cfg(target_os = "linux")]
fn _compile(libprobe: fn(&str) -> bool) {
    if libprobe("stdc++") {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    } else if libprobe("c++_shared") {
        println!("cargo:rustc-link-lib=dylib=c++_shared");
    } else if libprobe("c++") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else {
        panic!("no c++ library found");
    }
}

#[cfg(not(target_os = "linux"))]
fn _compile(libprobe: fn(&str) -> bool) {
    if libprobe("c++_shared") {
        println!("cargo:rustc-link-lib=dylib=c++_shared");
    } else if libprobe("c++") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else if libprobe("stdc++") {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    } else {
        panic!("no c++ library found");
    }
}

// linux/unix
#[cfg(not(target_env = "msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let dest = PathBuf::from(env::var_os("OUT_DIR").expect("OUT_DIR not found"));
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);
    let is_bsd = target.contains("dragonfly")
        || target.contains("freebsd")
        || target.contains("netbsd")
        || target.contains("openbsd");
    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or_else(|_| num_cpus::get().to_string());
    let r = Command::new(if is_bsd { "gmake" } else { "make" })
        .current_dir(&build)
        .args(&["--jobs", &jobs])
        .output()
        .expect("Failed to run make/gmake. Do you have it installed?");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("lib").display()
    );
    println!("cargo:rustc-link-lib=static=sass");

    let libprobe = | lib: &str | -> bool {
      Command::new("cc")
        .arg("-xc++")
        .arg("-o/dev/null")
        .arg(format!("-l{}",lib))
        .arg("-shared")
        .stderr(Stdio::null())
        .status()
        .expect("Failed to run cc. Do you have it installed?")
        .success()
    };
    _compile(libprobe);
}

// windows
#[cfg(target_env = "msvc")]
fn compile() {
    let src = get_libsass_folder();
    let target = env::var("TARGET").expect("TARGET not found in environment");
    let msvc_platform = if target.contains("x86_64") {
        "Win64"
    } else {
        "Win32"
    };
    let dest = PathBuf::from(env::var_os("OUT_DIR").expect("OUT_DIR not found in environment"));
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);

    // Find an instance of devenv.exe from Visual Studio IDE in order to upgrade
    // libsass.sln to the current available IDE. Do nothing if no devenv.exe found
    let d = cc::windows_registry::find(target.as_str(), "devenv.exe");
    if let Some(mut d) = d {
        let d = d
            .args(&["/upgrade", "win\\libsass.sln"])
            .current_dir(&build)
            .output()
            .expect("Failed to run devenv. Do you have it installed?");
        if !d.status.success() {
            let err = String::from_utf8_lossy(&d.stderr);
            let out = String::from_utf8_lossy(&d.stdout);
            println!("Upgrade error:\nSTDERR:{}\nSTDOUT:{}", err, out);
        }
    }

    let search = Command::new("where")
        .args(&["msbuild.exe"])
        .output()
        .expect("Failed to run where: Could not search for msbuild.exe on path.");
    let mut msbuild = if search.status.success() {
        Command::new("msbuild.exe")
    } else {
        cc::windows_registry::find(target.as_str(), "msbuild.exe")
            .expect("Could not find msbuild.exe on the registry")
    };

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or_else(|_| num_cpus::get().to_string());

    let r = msbuild
        .args(&[
            "win\\libsass.sln",
            "/p:LIBSASS_STATIC_LIB=1",
            "/p:Configuration=Release",
            "/p:WholeProgramOptimization=false",
            format!("/m:{}", jobs).as_str(),
            format!("/p:Platform={}", msvc_platform).as_str(),
        ])
        .current_dir(&build)
        .output()
        .expect("Failed to run msbuild. Do you have it installed?");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("win").join("bin").display()
    );
    println!("cargo:rustc-link-lib=static=libsass");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if pkg_config::find_library("libsass").is_ok() {
        return;
    }

    if !get_libsass_folder().join("Makefile").exists() {
        eprintln!("
            Could not find libsass source
            Try running `git submodule update --init` if you are building from the repository
        ");
        std::process::exit(1);
    }

    compile();
}
<commit_msg>Greatly improve build speed on Windows<commit_after>// extern crate bindgen;
#[cfg(target_env = "msvc")]
extern crate cc;
extern crate pkg_config;
extern crate num_cpus;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

// Automatically write bindings to libsass
//#[allow(dead_code)]
//fn write_bindings() {
//    let bindings = bindgen::Builder::default()
//        .header("libsass/include/sass.h")
//        .clang_arg("-Ilibsass/include")
//        // To avoid a test failing
//        .blacklist_type("max_align_t")
//        // we do static linking so it should be fine
//        // https://github.com/rust-lang/rust/issues/36927
//        .rustified_enum(".*")
//        .generate()
//        .expect("Unable to generate bindings");
//
//    // Write the bindings to the $OUT_DIR/bindings.rs file.
//    let out_path = PathBuf::from("src");
//    bindings
//        .write_to_file(out_path.join("bindings.rs"))
//        .expect("Couldn't write bindings!");
//}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => panic!("\n{} failed with {}\n", stringify!($e), e),
    })
}

fn cp_r(dir: &Path, dest: &Path) {
    for entry in t!(fs::read_dir(dir)) {
        let entry = t!(entry);
        let path = entry.path();
        let dst = dest.join(path.file_name().expect("Failed to get filename of path"));
        if t!(fs::metadata(&path)).is_file() {
            t!(fs::copy(path, dst));
        } else {
            t!(fs::create_dir_all(&dst));
            cp_r(&path, &dst);
        }
    }
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().expect("Failed to get the current directory").join("libsass")
}

#[cfg(target_os = "linux")]
fn _compile(libprobe: fn(&str) -> bool) {
    if libprobe("stdc++") {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    } else if libprobe("c++_shared") {
        println!("cargo:rustc-link-lib=dylib=c++_shared");
    } else if libprobe("c++") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else {
        panic!("no c++ library found");
    }
}

#[cfg(not(target_os = "linux"))]
fn _compile(libprobe: fn(&str) -> bool) {
    if libprobe("c++_shared") {
        println!("cargo:rustc-link-lib=dylib=c++_shared");
    } else if libprobe("c++") {
        println!("cargo:rustc-link-lib=dylib=c++");
    } else if libprobe("stdc++") {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    } else {
        panic!("no c++ library found");
    }
}

// linux/unix
#[cfg(not(target_env = "msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let dest = PathBuf::from(env::var_os("OUT_DIR").expect("OUT_DIR not found"));
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);
    let is_bsd = target.contains("dragonfly")
        || target.contains("freebsd")
        || target.contains("netbsd")
        || target.contains("openbsd");
    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or_else(|_| num_cpus::get().to_string());
    let r = Command::new(if is_bsd { "gmake" } else { "make" })
        .current_dir(&build)
        .args(&["--jobs", &jobs])
        .output()
        .expect("Failed to run make/gmake. Do you have it installed?");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("lib").display()
    );
    println!("cargo:rustc-link-lib=static=sass");

    let libprobe = | lib: &str | -> bool {
      Command::new("cc")
        .arg("-xc++")
        .arg("-o/dev/null")
        .arg(format!("-l{}",lib))
        .arg("-shared")
        .stderr(Stdio::null())
        .status()
        .expect("Failed to run cc. Do you have it installed?")
        .success()
    };
    _compile(libprobe);
}

// windows
#[cfg(target_env = "msvc")]
fn compile() {
    let src = get_libsass_folder();
    let target = env::var("TARGET").expect("TARGET not found in environment");
    let msvc_platform = if target.contains("x86_64") {
        "Win64"
    } else {
        "Win32"
    };
    let dest = PathBuf::from(env::var_os("OUT_DIR").expect("OUT_DIR not found in environment"));
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);

    // Find an instance of devenv.exe from Visual Studio IDE in order to upgrade
    // libsass.sln to the current available IDE. Do nothing if no devenv.exe found
    let d = cc::windows_registry::find(target.as_str(), "devenv.exe");
    if let Some(mut d) = d {
        let d = d
            .args(&["/upgrade", "win\\libsass.sln"])
            .current_dir(&build)
            .output()
            .expect("Failed to run devenv. Do you have it installed?");
        if !d.status.success() {
            let err = String::from_utf8_lossy(&d.stderr);
            let out = String::from_utf8_lossy(&d.stdout);
            println!("Upgrade error:\nSTDERR:{}\nSTDOUT:{}", err, out);
        }
    }

    let search = Command::new("where")
        .args(&["msbuild.exe"])
        .output()
        .expect("Failed to run where: Could not search for msbuild.exe on path.");
    let mut msbuild = if search.status.success() {
        Command::new("msbuild.exe")
    } else {
        cc::windows_registry::find(target.as_str(), "msbuild.exe")
            .expect("Could not find msbuild.exe on the registry")
    };

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or_else(|_| num_cpus::get().to_string());

    let r = msbuild
        .args(&[
            "win\\libsass.sln",
            "/p:LIBSASS_STATIC_LIB=1",
            "/p:Configuration=Release",
            "/p:WholeProgramOptimization=false",
            "/p:UseMultiToolTask=true",
            format!("/m:{}", jobs).as_str(),
            format!("/p:Platform={}", msvc_platform).as_str(),
        ])
        .current_dir(&build)
        .output()
        .expect("Failed to run msbuild. Do you have it installed?");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("win").join("bin").display()
    );
    println!("cargo:rustc-link-lib=static=libsass");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if pkg_config::find_library("libsass").is_ok() {
        return;
    }

    if !get_libsass_folder().join("Makefile").exists() {
        eprintln!("
            Could not find libsass source
            Try running `git submodule update --init` if you are building from the repository
        ");
        std::process::exit(1);
    }

    compile();
}
<|endoftext|>


<commit_before>#[derive(Eq, PartialEq)]
enum Move {
    Rock,
    Paper,
    Scissors,
}

enum GameResult {
    Human,
    Computer,
    Draw,
}

struct Game {
    frequencies: (u32, u32, u32),
}

impl Move {
    fn beaten_by(&self) ->  Move {
        match *self {
            Move::Rock => Move::Paper,
            Move::Paper => Move::Scissors,
            Move::Scissors => Move::Rock,
        }
    }
}

impl Game {
    fn new() -> Game {
        Game{frequencies: (0, 0, 0)}
    }

    fn increment_frequency(&mut self, m: &Move) {
        match *m {
            Move::Rock => { self.frequencies.0 += 1; },
            Move::Paper => { self.frequencies.1 += 1; },
            Move::Scissors => { self.frequencies.2 += 1; },
        };
    }

    fn play(&mut self, human: Move) -> GameResult {
        let computer = Move::Paper;
        let best_answer = human.beaten_by();

        self.increment_frequency(&best_answer);

        if best_answer == computer {
            GameResult::Computer
        } else if computer.beaten_by() == human {
            GameResult::Human
        } else {
            GameResult::Draw
        }
    }
}

fn main() {
   let mut game = Game::new();

   let result = match game.play(Move::Paper) {
       GameResult::Human => "Human wins!",
       GameResult::Computer => "Computer wins!",
       GameResult::Draw => "Draw!",
   };

   println!("{}", result);
}
<commit_msg>Added game loop<commit_after>use std::io;

#[derive(Eq, PartialEq)]
enum Move {
    Rock,
    Paper,
    Scissors,
}

enum GameResult {
    Human,
    Computer,
    Draw,
}

struct Game {
    frequencies: (u32, u32, u32),
}

impl Move {
    fn beaten_by(&self) ->  Move {
        match *self {
            Move::Rock => Move::Paper,
            Move::Paper => Move::Scissors,
            Move::Scissors => Move::Rock,
        }
    }
}

impl Game {
    fn new() -> Game {
        Game{frequencies: (0, 0, 0)}
    }

    fn increment_frequency(&mut self, m: &Move) {
        match *m {
            Move::Rock => { self.frequencies.0 += 1; },
            Move::Paper => { self.frequencies.1 += 1; },
            Move::Scissors => { self.frequencies.2 += 1; },
        };
    }

    fn pick(&self) -> Move {
        Move::Paper
    }

    fn play(&mut self, human: &Move) -> GameResult {
        let computer = self.pick();
        let best_answer = human.beaten_by();

        self.increment_frequency(&best_answer);

        if best_answer == computer {
            GameResult::Computer
        } else if computer.beaten_by() == *human {
            GameResult::Human
        } else {
            GameResult::Draw
        }
    }
}

fn main() {
   let mut game = Game::new();

   loop {
       println!("Enter a guess (r, p, s);");

       let mut input = String::new();

       io::stdin()
           .read_line(&mut input)
           .ok()
           .expect("Cuold not read input.");

       let human = match input.trim() {
           "r" => Move::Rock,
           "p" => Move::Paper,
           "s" => Move::Scissors,
           _ => { continue; },
       };

       let result = match game.play(&human) {
           GameResult::Human => "Human wins!",
           GameResult::Computer => "Computer wins!",
           GameResult::Draw => "Draw!",
       };

       println!("{}", result);
   }
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use lsp_types::{
    CodeActionProviderCapability, CodeLensOptions, CompletionOptions,
    DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability,
    ImplementationProviderCapability, RenameOptions, RenameProviderCapability, ServerCapabilities,
    SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
    TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
};

pub fn server_capabilities() -> ServerCapabilities {
    ServerCapabilities {
        text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
            open_close: Some(true),
            change: Some(TextDocumentSyncKind::Full),
            will_save: None,
            will_save_wait_until: None,
            save: None,
        })),
        hover_provider: Some(true),
        completion_provider: Some(CompletionOptions {
            resolve_provider: None,
            trigger_characters: Some(vec![":".to_string(), ".".to_string()]),
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        }),
        signature_help_provider: Some(SignatureHelpOptions {
            trigger_characters: Some(vec!["(".to_string(), ",".to_string(), ")".to_string()]),
            retrigger_characters: None,
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        }),
        declaration_provider: None,
        definition_provider: Some(true),
        type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
        implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
        references_provider: Some(true),
        document_highlight_provider: Some(true),
        document_symbol_provider: Some(true),
        workspace_symbol_provider: Some(true),
        code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
        code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
        document_formatting_provider: Some(true),
        document_range_formatting_provider: None,
        document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
            first_trigger_character: "=".to_string(),
            more_trigger_character: Some(vec![".".to_string(), ">".to_string()]),
        }),
        selection_range_provider: Some(GenericCapability::default()),
        folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
        rename_provider: Some(RenameProviderCapability::Options(RenameOptions {
            prepare_provider: Some(true),
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        })),
        document_link_provider: None,
        color_provider: None,
        execute_command_provider: None,
        workspace: None,
    }
}
<commit_msg>Do not trigger signature help on close<commit_after>//! FIXME: write short doc here

use lsp_types::{
    CodeActionProviderCapability, CodeLensOptions, CompletionOptions,
    DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability,
    ImplementationProviderCapability, RenameOptions, RenameProviderCapability, ServerCapabilities,
    SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
    TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
};

pub fn server_capabilities() -> ServerCapabilities {
    ServerCapabilities {
        text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
            open_close: Some(true),
            change: Some(TextDocumentSyncKind::Full),
            will_save: None,
            will_save_wait_until: None,
            save: None,
        })),
        hover_provider: Some(true),
        completion_provider: Some(CompletionOptions {
            resolve_provider: None,
            trigger_characters: Some(vec![":".to_string(), ".".to_string()]),
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        }),
        signature_help_provider: Some(SignatureHelpOptions {
            trigger_characters: Some(vec!["(".to_string(), ",".to_string()]),
            retrigger_characters: None,
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        }),
        declaration_provider: None,
        definition_provider: Some(true),
        type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
        implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
        references_provider: Some(true),
        document_highlight_provider: Some(true),
        document_symbol_provider: Some(true),
        workspace_symbol_provider: Some(true),
        code_action_provider: Some(CodeActionProviderCapability::Simple(true)),
        code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
        document_formatting_provider: Some(true),
        document_range_formatting_provider: None,
        document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
            first_trigger_character: "=".to_string(),
            more_trigger_character: Some(vec![".".to_string(), ">".to_string()]),
        }),
        selection_range_provider: Some(GenericCapability::default()),
        folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
        rename_provider: Some(RenameProviderCapability::Options(RenameOptions {
            prepare_provider: Some(true),
            work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
        })),
        document_link_provider: None,
        color_provider: None,
        execute_command_provider: None,
        workspace: None,
    }
}
<|endoftext|>


<commit_before>use std::sync::atomic;
use std::sync::atomic::{AtomicUsize,AtomicIsize,AtomicBool,AtomicPtr};

// Core RMC
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) }
}

// RMC objects
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;

macro_rules! atomic_methods {
    ($ty:ty, $outty:ty, $rmc_name:ident, $atomic_name:ident) => [
    pub fn new(v: $ty) -> $outty { $rmc_name { v: $atomic_name::new(v) } }
    pub fn load(&self) -> $ty { self.v.load(LOAD_ORDER) }
    pub fn store(&self, val: $ty) { self.v.store(val, STORE_ORDER) }
    pub fn swap(&self, val: $ty) -> $ty { self.v.swap(val, RMW_ORDER) }
    pub fn compare_and_swap(&self, old: $ty, new: $ty) -> $ty {
        self.v.compare_and_swap(old, new, RMW_ORDER)
    }
    ]
}
macro_rules! atomic_methods_arithmetic {
    ($ty:ty) => [
    pub fn fetch_add(&self, val: $ty) -> $ty { self.v.fetch_add(val, RMW_ORDER) }
    pub fn fetch_sub(&self, val: $ty) -> $ty { self.v.fetch_sub(val, RMW_ORDER) }
    ]
}
macro_rules! atomic_methods_logical {
    ($ty:ty) => [
    pub fn fetch_and(&self, val: $ty) -> $ty { self.v.fetch_and(val, RMW_ORDER) }
    pub fn fetch_or(&self, val: $ty) -> $ty { self.v.fetch_or(val, RMW_ORDER) }
    pub fn fetch_xor(&self, val: $ty) -> $ty { self.v.fetch_xor(val, RMW_ORDER) }
    ]
}

pub struct RmcUsize { v: AtomicUsize, }
unsafe impl Sync for RmcUsize {}
impl RmcUsize {
    atomic_methods!(usize, RmcUsize, RmcUsize, AtomicUsize);
    atomic_methods_arithmetic!(usize);
    atomic_methods_logical!(usize);
}

pub struct RmcIsize { v: AtomicIsize, }
unsafe impl Sync for RmcIsize {}
impl RmcIsize {
    atomic_methods!(isize, RmcIsize, RmcIsize, AtomicIsize);
    atomic_methods_arithmetic!(isize);
    atomic_methods_logical!(isize);
}

pub struct RmcBool { v: AtomicBool, }
unsafe impl Sync for RmcBool {}
impl RmcBool {
    atomic_methods!(bool, RmcBool, RmcBool, AtomicBool);
    atomic_methods_logical!(bool);
    pub fn fetch_nand(&self, val: bool) -> bool { self.v.fetch_nand(val, RMW_ORDER) }
}

pub struct RmcPtr<T> { v: atomic::AtomicPtr<T>, }
unsafe impl<T> Sync for RmcPtr<T> {}
impl<T> RmcPtr<T> {
    atomic_methods!(*mut T, RmcPtr<T>, RmcPtr, AtomicPtr);
}
<commit_msg>Fix rust wrappers so stuff gets inlined properly.<commit_after>use std::sync::atomic;
use std::sync::atomic::{AtomicUsize,AtomicIsize,AtomicBool,AtomicPtr};

// Core RMC
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) }
}

// RMC objects
pub const STORE_ORDER: atomic::Ordering = atomic::Ordering::Relaxed;
pub const LOAD_ORDER: atomic::Ordering = atomic::Ordering::Relaxed;
pub const RMW_ORDER: atomic::Ordering = atomic::Ordering::Relaxed;

macro_rules! atomic_methods {
    ($ty:ty, $outty:ty, $rmc_name:ident, $atomic_name:ident) => [
    #[inline] pub fn new(v: $ty) -> $outty { $rmc_name { v: $atomic_name::new(v) } }
    #[inline] pub fn load(&self) -> $ty { self.v.load(LOAD_ORDER) }
    #[inline] pub fn store(&self, val: $ty) { self.v.store(val, STORE_ORDER) }
    #[inline] pub fn swap(&self, val: $ty) -> $ty { self.v.swap(val, RMW_ORDER) }
    #[inline] pub fn compare_and_swap(&self, old: $ty, new: $ty) -> $ty {
        self.v.compare_and_swap(old, new, RMW_ORDER)
    }
    ]
}
macro_rules! atomic_methods_arithmetic {
    ($ty:ty) => [
    #[inline] pub fn fetch_add(&self, val: $ty) -> $ty { self.v.fetch_add(val, RMW_ORDER) }
    #[inline] pub fn fetch_sub(&self, val: $ty) -> $ty { self.v.fetch_sub(val, RMW_ORDER) }
    ]
}
macro_rules! atomic_methods_logical {
    ($ty:ty) => [
    #[inline] pub fn fetch_and(&self, val: $ty) -> $ty { self.v.fetch_and(val, RMW_ORDER) }
    #[inline] pub fn fetch_or(&self, val: $ty) -> $ty { self.v.fetch_or(val, RMW_ORDER) }
    #[inline] pub fn fetch_xor(&self, val: $ty) -> $ty { self.v.fetch_xor(val, RMW_ORDER) }
    ]
}

pub struct RmcUsize { v: AtomicUsize, }
unsafe impl Sync for RmcUsize {}
impl RmcUsize {
    atomic_methods!(usize, RmcUsize, RmcUsize, AtomicUsize);
    atomic_methods_arithmetic!(usize);
    atomic_methods_logical!(usize);
}

pub struct RmcIsize { v: AtomicIsize, }
unsafe impl Sync for RmcIsize {}
impl RmcIsize {
    atomic_methods!(isize, RmcIsize, RmcIsize, AtomicIsize);
    atomic_methods_arithmetic!(isize);
    atomic_methods_logical!(isize);
}

pub struct RmcBool { v: AtomicBool, }
unsafe impl Sync for RmcBool {}
impl RmcBool {
    atomic_methods!(bool, RmcBool, RmcBool, AtomicBool);
    atomic_methods_logical!(bool);
    pub fn fetch_nand(&self, val: bool) -> bool { self.v.fetch_nand(val, RMW_ORDER) }
}

pub struct RmcPtr<T> { v: atomic::AtomicPtr<T>, }
unsafe impl<T> Sync for RmcPtr<T> {}
impl<T> RmcPtr<T> {
    atomic_methods!(*mut T, RmcPtr<T>, RmcPtr, AtomicPtr);
}
<|endoftext|>


<commit_before>//! Procedural macro implementing `#[derive(Enum)]`
//!
//! This is supposed to used with `enum-map` crate, which provides the
//! actual usage documentation.

#![recursion_limit = "128"]

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

mod derive_enum;
mod derive_struct;

use proc_macro2::TokenStream;
use syn::{Data, DeriveInput, Type};

/// Procedural derive generating `enum_map::Enum` implementation.
///
/// # Examples
///
/// ## Enums Without Payload
/// ```
/// # extern crate enum_map;
/// use enum_map::Enum;
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum A {
///     B,
///     C,
///     D,
/// }
///
/// assert_eq!(A::B.into_usize(), 0);
/// assert_eq!(A::C.into_usize(), 1);
/// assert_eq!(A::D.into_usize(), 2);
///
/// assert_eq!(A::from_usize(0), A::B);
/// assert_eq!(A::from_usize(1), A::C);
/// assert_eq!(A::from_usize(2), A::D);
/// ```
///
/// ## Enums With Payload
///
/// ```
/// # extern crate enum_map;
/// use enum_map::Enum;
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum A {
///     B,
///     C,
///     D,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum X {
///     Y,
///     Z,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum Foo {
///     Bar(bool, A),
///     Empty,
///     Baz { fa: A, fx: X },
/// }
///
/// assert_eq!(Foo::Bar(false, A::B).into_usize(), 0);
/// assert_eq!(Foo::Bar(false, A::D).into_usize(), 4);
/// assert_eq!(Foo::Bar(true, A::B).into_usize(), 1);
/// assert_eq!(Foo::Bar(true, A::C).into_usize(), 3);
/// assert_eq!(Foo::Empty.into_usize(), 6);
/// assert_eq!(Foo::Baz { fa: A::B, fx: X::Y }.into_usize(), 7);
/// assert_eq!(Foo::Baz { fa: A::B, fx: X::Z }.into_usize(), 10);
/// assert_eq!(Foo::Baz { fa: A::D, fx: X::Y }.into_usize(), 9);
///
/// assert_eq!(Foo::from_usize(0), Foo::Bar(false, A::B));
/// assert_eq!(Foo::from_usize(4), Foo::Bar(false, A::D));
/// assert_eq!(Foo::from_usize(1), Foo::Bar(true, A::B));
/// assert_eq!(Foo::from_usize(3), Foo::Bar(true, A::C));
/// assert_eq!(Foo::from_usize(6), Foo::Empty);
/// assert_eq!(Foo::from_usize(7), Foo::Baz { fa: A::B, fx: X::Y });
/// assert_eq!(Foo::from_usize(10), Foo::Baz { fa: A::B, fx: X::Z });
/// assert_eq!(Foo::from_usize(9), Foo::Baz { fa: A::D, fx: X::Y });
///
/// ```
///
/// ## Structs
///
/// ```
/// # extern crate enum_map;
/// use enum_map::Enum;
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum A {
///     B,
///     C,
///     D,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum X {
///     Y,
///     Z,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// struct Foo {
///     bar: bool,
///     baz: A,
///     end: X,
/// }
///
/// assert_eq!(Foo { bar: false, baz: A::B, end: X::Y }.into_usize(), 0);
/// assert_eq!(Foo { bar: true, baz: A::B, end: X::Y }.into_usize(), 1);
/// assert_eq!(Foo { bar: false, baz: A::D, end: X::Y }.into_usize(), 4);
/// assert_eq!(Foo { bar: true, baz: A::C, end: X::Z }.into_usize(), 9);
///
/// assert_eq!(Foo::from_usize(0), Foo { bar: false, baz: A::B, end: X::Y });
/// assert_eq!(Foo::from_usize(1), Foo { bar: true, baz: A::B, end: X::Y });
/// assert_eq!(Foo::from_usize(4), Foo { bar: false, baz: A::D, end: X::Y });
/// assert_eq!(Foo::from_usize(9), Foo { bar: true, baz: A::C, end: X::Z });
/// ```
///
/// ## Tuple Structs
///
/// ```
/// # extern crate enum_map;
/// use enum_map::Enum;
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum A {
///     B,
///     C,
///     D,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum X {
///     Y,
///     Z,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// struct Foo(bool, A, X);
///
/// assert_eq!(Foo(false, A::B, X::Y ).into_usize(), 0);
/// assert_eq!(Foo(true, A::B, X::Y ).into_usize(), 1);
/// assert_eq!(Foo(false, A::D, X::Y ).into_usize(), 4);
/// assert_eq!(Foo(true, A::C, X::Z ).into_usize(), 9);
///
/// assert_eq!(Foo::from_usize(0), Foo(false, A::B, X::Y ));
/// assert_eq!(Foo::from_usize(1), Foo(true, A::B, X::Y ));
/// assert_eq!(Foo::from_usize(4), Foo(false, A::D, X::Y ));
/// assert_eq!(Foo::from_usize(9), Foo(true, A::C, X::Z ));
#[proc_macro_derive(Enum)]
pub fn derive_enum_map(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();

    let result = match input.data {
        Data::Enum(data_enum) => derive_enum::generate(input.ident, data_enum),
        Data::Struct(data_struct) => derive_struct::generate(input.ident, data_struct),
        _ => quote! { compile_error! {"#[derive(Enum)] is only defined for enums and structs"} },
    };

    result.into()
}

fn type_length(ty: &Type) -> TokenStream {
    quote! {
        <#ty as ::enum_map::Enum>::LENGTH
    }
}
<commit_msg>Fix whitespace in Enum derive documentation<commit_after>//! Procedural macro implementing `#[derive(Enum)]`
//!
//! This is supposed to used with `enum-map` crate, which provides the
//! actual usage documentation.

#![recursion_limit = "128"]

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

mod derive_enum;
mod derive_struct;

use proc_macro2::TokenStream;
use syn::{Data, DeriveInput, Type};

/// Procedural derive generating `enum_map::Enum` implementation.
///
/// # Examples
///
/// ## Enums Without Payload
/// ```
/// # extern crate enum_map;
/// use enum_map::Enum;
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum A {
///     B,
///     C,
///     D,
/// }
///
/// assert_eq!(A::B.into_usize(), 0);
/// assert_eq!(A::C.into_usize(), 1);
/// assert_eq!(A::D.into_usize(), 2);
///
/// assert_eq!(A::from_usize(0), A::B);
/// assert_eq!(A::from_usize(1), A::C);
/// assert_eq!(A::from_usize(2), A::D);
/// ```
///
/// ## Enums With Payload
///
/// ```
/// # extern crate enum_map;
/// use enum_map::Enum;
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum A {
///     B,
///     C,
///     D,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum X {
///     Y,
///     Z,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum Foo {
///     Bar(bool, A),
///     Empty,
///     Baz { fa: A, fx: X },
/// }
///
/// assert_eq!(Foo::Bar(false, A::B).into_usize(), 0);
/// assert_eq!(Foo::Bar(false, A::D).into_usize(), 4);
/// assert_eq!(Foo::Bar(true, A::B).into_usize(), 1);
/// assert_eq!(Foo::Bar(true, A::C).into_usize(), 3);
/// assert_eq!(Foo::Empty.into_usize(), 6);
/// assert_eq!(Foo::Baz { fa: A::B, fx: X::Y }.into_usize(), 7);
/// assert_eq!(Foo::Baz { fa: A::B, fx: X::Z }.into_usize(), 10);
/// assert_eq!(Foo::Baz { fa: A::D, fx: X::Y }.into_usize(), 9);
///
/// assert_eq!(Foo::from_usize(0), Foo::Bar(false, A::B));
/// assert_eq!(Foo::from_usize(4), Foo::Bar(false, A::D));
/// assert_eq!(Foo::from_usize(1), Foo::Bar(true, A::B));
/// assert_eq!(Foo::from_usize(3), Foo::Bar(true, A::C));
/// assert_eq!(Foo::from_usize(6), Foo::Empty);
/// assert_eq!(Foo::from_usize(7), Foo::Baz { fa: A::B, fx: X::Y });
/// assert_eq!(Foo::from_usize(10), Foo::Baz { fa: A::B, fx: X::Z });
/// assert_eq!(Foo::from_usize(9), Foo::Baz { fa: A::D, fx: X::Y });
///
/// ```
///
/// ## Structs
///
/// ```
/// # extern crate enum_map;
/// use enum_map::Enum;
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum A {
///     B,
///     C,
///     D,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum X {
///     Y,
///     Z,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// struct Foo {
///     bar: bool,
///     baz: A,
///     end: X,
/// }
///
/// assert_eq!(Foo { bar: false, baz: A::B, end: X::Y }.into_usize(), 0);
/// assert_eq!(Foo { bar: true, baz: A::B, end: X::Y }.into_usize(), 1);
/// assert_eq!(Foo { bar: false, baz: A::D, end: X::Y }.into_usize(), 4);
/// assert_eq!(Foo { bar: true, baz: A::C, end: X::Z }.into_usize(), 9);
///
/// assert_eq!(Foo::from_usize(0), Foo { bar: false, baz: A::B, end: X::Y });
/// assert_eq!(Foo::from_usize(1), Foo { bar: true, baz: A::B, end: X::Y });
/// assert_eq!(Foo::from_usize(4), Foo { bar: false, baz: A::D, end: X::Y });
/// assert_eq!(Foo::from_usize(9), Foo { bar: true, baz: A::C, end: X::Z });
/// ```
///
/// ## Tuple Structs
///
/// ```
/// # extern crate enum_map;
/// use enum_map::Enum;
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum A {
///     B,
///     C,
///     D,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// enum X {
///     Y,
///     Z,
/// }
///
/// #[derive(Enum, Debug, PartialEq, Eq)]
/// struct Foo(bool, A, X);
///
/// assert_eq!(Foo(false, A::B, X::Y ).into_usize(), 0);
/// assert_eq!(Foo(true, A::B, X::Y ).into_usize(), 1);
/// assert_eq!(Foo(false, A::D, X::Y ).into_usize(), 4);
/// assert_eq!(Foo(true, A::C, X::Z ).into_usize(), 9);
///
/// assert_eq!(Foo::from_usize(0), Foo(false, A::B, X::Y));
/// assert_eq!(Foo::from_usize(1), Foo(true, A::B, X::Y));
/// assert_eq!(Foo::from_usize(4), Foo(false, A::D, X::Y));
/// assert_eq!(Foo::from_usize(9), Foo(true, A::C, X::Z));
#[proc_macro_derive(Enum)]
pub fn derive_enum_map(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();

    let result = match input.data {
        Data::Enum(data_enum) => derive_enum::generate(input.ident, data_enum),
        Data::Struct(data_struct) => derive_struct::generate(input.ident, data_struct),
        _ => quote! { compile_error! {"#[derive(Enum)] is only defined for enums and structs"} },
    };

    result.into()
}

fn type_length(ty: &Type) -> TokenStream {
    quote! {
        <#ty as ::enum_map::Enum>::LENGTH
    }
}
<|endoftext|>


<commit_before>use fraction::Number;
use square_matrix::SquareMatrix;

#[derive(Debug, Clone, Copy)]
pub struct Point {
    pub x: i64,
    pub y: i64,
}

//
// Singularity
//

impl<T> SquareMatrix<T> where T: Number<T> {
    pub fn is_singular(&self) -> bool {
        self.determinant() == T::zero()
    }
}

//
// Area & volume
//

pub fn triangle_area(a: Point, b: Point, c: Point) -> f64 {
    triangle_area_signed(a, b, c).abs()
}

fn triangle_area_signed(a: Point, b: Point, c: Point) -> f64 {
    let matrix = SquareMatrix::from_vec(&vec![
        a.x, a.y, 1,
        b.x, b.y, 1,
        c.x, c.y, 1,
    ]);

    matrix.determinant() as f64 / 2.
}

// The triangle_area function can be generalized to the volume of a tetrahedron, and further to the
// volume of a simplex defined by d+1 points in d dimensions.
pub fn simplex_volume(points: &Vec<Vec<i64>>) -> f64 {
    simplex_volume_signed(points).abs()
}

fn simplex_volume_signed(points: &Vec<Vec<i64>>) -> f64 {
    let d = points.len() - 1;

    let mut matrix_vec = Vec::with_capacity((d + 1) * (d + 1));
    for point in points {
        matrix_vec.extend_from_slice(&point);
        matrix_vec.push(1);
    }

    let matrix = SquareMatrix::from_vec(&matrix_vec);
    matrix.determinant() as f64 / factorial(d) as f64
}

fn factorial(n: usize) -> usize {
    (2..n+1).fold(1, |f, i| f * i)
}

//
// Collinearity & coplanarity
//

pub fn collinear(a: Point, b: Point, c: Point) -> bool {
    triangle_area(a, b, c) == 0.
}

// Again, the collinear function can be generalized to determine if d+1 points are coplanar in d
// dimensions.
pub fn coplanar(points: &Vec<Vec<i64>>) -> bool {
    simplex_volume(points) == 0.
}

//
// Side of a point relative to a line or plane
//

#[derive(Debug, PartialEq)]
pub enum LineSide {
    Left,
    Right,
    On,
}

// Does c lie to the left, to the right, or on the directed line that passes through a before b?
// Note that "left" and "right" are not relative to the x-axis, but to the direction of the line.
pub fn line_side(a: Point, b: Point, c: Point) -> LineSide {
    match triangle_area_signed(a, b, c) {
        area if area > 0. => LineSide::Left,
        area if area < 0. => LineSide::Right,
        _ => LineSide::On,
    }
}

#[derive(Debug, PartialEq)]
pub enum PlaneSide {
    A,
    B,
    On,
}

// The line_side function can be generalized to answering if a point lies on one side, on the other
// side, or on an oriented plane defined by d points in d dimensions.
pub fn plane_side(plane: &Vec<Vec<i64>>, point: &Vec<i64>) -> PlaneSide {
    let mut points = plane.clone();
    points.push(point.clone());

    match simplex_volume_signed(&points) {
        area if area > 0. => PlaneSide::A,
        area if area < 0. => PlaneSide::B,
        _ => PlaneSide::On,
    }
}

//
// Side of a point relative to a circle
//

#[derive(Debug, PartialEq)]
pub enum CircleSide {
    Inside,
    Outside,
    On,
}

pub fn circle_side(circle: [Point; 3], point: Point) -> CircleSide {
    let [c0, c1, c2] = circle;

    let matrix = SquareMatrix::from_vec(&vec![
        c0.x, c0.y, c0.x.pow(2) + c0.y.pow(2), 1,
        c1.x, c1.y, c1.x.pow(2) + c1.y.pow(2), 1,
        c2.x, c2.y, c2.x.pow(2) + c2.y.pow(2), 1,
        point.x, point.y, point.x.pow(2) + point.y.pow(2), 1,
    ]);

    match matrix.determinant() {
        d if d > 0 => CircleSide::Inside,
        d if d < 0 => CircleSide::Outside,
        _ => CircleSide::On,
    }
}

//
// Intersection between line and line segment
//

pub fn intersects(line: [Point; 2], segment: [Point; 2]) -> bool {
    line_side(line[0], line[1], segment[0]) != line_side(line[0], line[1], segment[1])
}
<commit_msg>[determinant/rust] Use i32 instead of i64<commit_after>use fraction::Number;
use square_matrix::SquareMatrix;

#[derive(Debug, Clone, Copy)]
pub struct Point {
    pub x: i32,
    pub y: i32,
}

//
// Singularity
//

impl<T> SquareMatrix<T> where T: Number<T> {
    pub fn is_singular(&self) -> bool {
        self.determinant() == T::zero()
    }
}

//
// Area & volume
//

pub fn triangle_area(a: Point, b: Point, c: Point) -> f32 {
    triangle_area_signed(a, b, c).abs()
}

fn triangle_area_signed(a: Point, b: Point, c: Point) -> f32 {
    let matrix = SquareMatrix::from_vec(&vec![
        a.x, a.y, 1,
        b.x, b.y, 1,
        c.x, c.y, 1,
    ]);

    matrix.determinant() as f32 / 2.
}

// The triangle_area function can be generalized to the volume of a tetrahedron, and further to the
// volume of a simplex defined by d+1 points in d dimensions.
pub fn simplex_volume(points: &Vec<Vec<i32>>) -> f32 {
    simplex_volume_signed(points).abs()
}

fn simplex_volume_signed(points: &Vec<Vec<i32>>) -> f32 {
    let d = points.len() - 1;

    let mut matrix_vec = Vec::with_capacity((d + 1) * (d + 1));
    for point in points {
        matrix_vec.extend_from_slice(&point);
        matrix_vec.push(1);
    }

    let matrix = SquareMatrix::from_vec(&matrix_vec);
    matrix.determinant() as f32 / factorial(d) as f32
}

fn factorial(n: usize) -> usize {
    (2..n+1).fold(1, |f, i| f * i)
}

//
// Collinearity & coplanarity
//

pub fn collinear(a: Point, b: Point, c: Point) -> bool {
    triangle_area(a, b, c) == 0.
}

// Again, the collinear function can be generalized to determine if d+1 points are coplanar in d
// dimensions.
pub fn coplanar(points: &Vec<Vec<i32>>) -> bool {
    simplex_volume(points) == 0.
}

//
// Side of a point relative to a line or plane
//

#[derive(Debug, PartialEq)]
pub enum LineSide {
    Left,
    Right,
    On,
}

// Does c lie to the left, to the right, or on the directed line that passes through a before b?
// Note that "left" and "right" are not relative to the x-axis, but to the direction of the line.
pub fn line_side(a: Point, b: Point, c: Point) -> LineSide {
    match triangle_area_signed(a, b, c) {
        area if area > 0. => LineSide::Left,
        area if area < 0. => LineSide::Right,
        _ => LineSide::On,
    }
}

#[derive(Debug, PartialEq)]
pub enum PlaneSide {
    A,
    B,
    On,
}

// The line_side function can be generalized to answering if a point lies on one side, on the other
// side, or on an oriented plane defined by d points in d dimensions.
pub fn plane_side(plane: &Vec<Vec<i32>>, point: &Vec<i32>) -> PlaneSide {
    let mut points = plane.clone();
    points.push(point.clone());

    match simplex_volume_signed(&points) {
        area if area > 0. => PlaneSide::A,
        area if area < 0. => PlaneSide::B,
        _ => PlaneSide::On,
    }
}

//
// Side of a point relative to a circle
//

#[derive(Debug, PartialEq)]
pub enum CircleSide {
    Inside,
    Outside,
    On,
}

pub fn circle_side(circle: [Point; 3], point: Point) -> CircleSide {
    let [c0, c1, c2] = circle;

    let matrix = SquareMatrix::from_vec(&vec![
        c0.x, c0.y, c0.x.pow(2) + c0.y.pow(2), 1,
        c1.x, c1.y, c1.x.pow(2) + c1.y.pow(2), 1,
        c2.x, c2.y, c2.x.pow(2) + c2.y.pow(2), 1,
        point.x, point.y, point.x.pow(2) + point.y.pow(2), 1,
    ]);

    match matrix.determinant() {
        d if d > 0 => CircleSide::Inside,
        d if d < 0 => CircleSide::Outside,
        _ => CircleSide::On,
    }
}

//
// Intersection between line and line segment
//

pub fn intersects(line: [Point; 2], segment: [Point; 2]) -> bool {
    line_side(line[0], line[1], segment[0]) != line_side(line[0], line[1], segment[1])
}
<|endoftext|>


<commit_before>extern crate bio;
extern crate argparse;
use std::io;
use std::io::Write;
use std::cmp;
use bio::io::fasta;
use std::fmt;
use std::fs::File;
use argparse::{ArgumentParser, StoreTrue, Store, Print, Collect};

const EXIT_FILE_IO_ERROR: i32 = 1;
const EXIT_COMMAND_LINE_ERROR: i32 = 2;
const EXIT_FASTA_PARSE_ERROR: i32 = 3;
static PROGRAM_NAME: &'static str = "biotool";

fn exit_with_error(status: i32, message: &String) -> () {
    writeln!(&mut std::io::stderr(),
             "{} ERROR: {}!",
             PROGRAM_NAME,
             message)
        .unwrap();
    std::process::exit(status);
}

#[derive(Debug, PartialEq)]
pub struct FastaStats {
    min_len: u64,
    average_len: u64,
    max_len: u64,
    total: u64,
    num_seqs: u64,
}

#[derive(Debug)]
pub enum StatsResult {
    StatsNone,
    StatsSome(FastaStats),
    StatsError(io::Error),
}

impl FastaStats {
    pub fn new<R: io::Read>(minlen: u64, reader: R) -> Result<Option<FastaStats>, io::Error> {
        let fasta_reader = fasta::Reader::new(reader);
        let mut num_seqs: u64 = 0;
        let mut total: u64 = 0;
        let mut max_len: u64 = 0;
        let mut min_len: u64 = 0;
        let mut this_len: u64;

        for next in fasta_reader.records() {
            match next {
                Ok(record) => {
                    this_len = record.seq().len() as u64;
                    if this_len >= minlen {
                        num_seqs += 1;
                        total += this_len;
                        if num_seqs == 1 {
                            max_len = this_len;
                            min_len = this_len;
                        } else {
                            max_len = cmp::max(max_len, this_len);
                            min_len = cmp::min(min_len, this_len);
                        }
                    }
                }
                // Err(error) => return StatsResult::StatsError(error)
                Err(error) => return Err(error),
            }
        }
        if num_seqs > 0 {
            let average_len = ((total as f64) / (num_seqs as f64)).floor() as u64;
            Ok(Some(FastaStats {
                min_len: min_len,
                average_len: average_len,
                max_len: max_len,
                total: total,
                num_seqs: num_seqs,
            }))
        } else {
            Ok(None)
        }
    }
}

impl fmt::Display for FastaStats {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}\t{}\t{}\t{}\t{}",
               self.num_seqs,
               self.total,
               self.min_len,
               self.average_len,
               self.max_len)
    }
}

struct Options {
    verbose: bool,
    minlen: u64,
    fasta_files: Vec<String>,
}

fn parse_options() -> Options {
    let mut options = Options {
        verbose: false,
        minlen: 0,
        fasta_files: Vec::new(),
    };
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Print fasta stats");
        ap.refer(&mut options.verbose)
            .add_option(&["-v", "--verbose"],
                        StoreTrue,
                        "Print more stuff about what's happening");
        ap.refer(&mut options.minlen)
            .add_option(&["--minlen"],
                        Store,
                        "Minimum length sequence to include in stats");
        ap.refer(&mut options.fasta_files)
            .add_argument(&"fasta_files", Collect, "Input FASTA files");
        ap.add_option(&["--version"],
                      Print(env!("CARGO_PKG_VERSION").to_string()),
                      "Show version");
        match ap.parse_args() {
            Ok(()) => (),
            Err(0) => {
                // Help and version commands
                std::process::exit(0);
            }
            Err(_error_code) => {
                // Parse error
                std::process::exit(EXIT_COMMAND_LINE_ERROR);
            }
        }
    }
    return options;
}

fn compute_print_stats<R: io::Read>(options: &Options, filename: &String, reader: R) -> () {
    match FastaStats::new(options.minlen, reader) {
        // StatsResult::StatsSome(stats) => {
        Ok(Some(stats)) => {
            println!("{}\t{}", filename, stats);
        }
        Ok(None) => {
            println!("{}\t0\t0\t-\t-\t-", filename);
        }
        Err(error) => exit_with_error(EXIT_FASTA_PARSE_ERROR, &format!("{}", error)),
    }
}

fn main() {
    let options = parse_options();
    println!("FILENAME\tTOTAL\tNUMSEQ\tMIN\tAVG\tMAX");
    if options.fasta_files.len() == 0 {
        compute_print_stats(&options, &String::from("stdin"), io::stdin());
    } else {
        for filename in &options.fasta_files {
            match File::open(filename) {
                Ok(file) => {
                    compute_print_stats(&options, filename, file);
                }
                Err(error) => exit_with_error(EXIT_FILE_IO_ERROR, &format!("{}", error)),
            }
        }
    }
}

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

    fn test_fastastats_ok(minlen: u64, input: &String, expected: Option<FastaStats>) -> () {
        match FastaStats::new(minlen, input.as_bytes()) {
            Ok(result) => {
                if result != expected {
                    panic!(format!("expected {:?} got {:?}", expected, result))
                }
            }
            Err(_error) => panic!(format!("expected {:?} got Err(..)", expected)),
        }
    }

    // io::Error does not currently implement PartialEq, so we resort to
    // just checking for the existence of an error, not its actual content.
    // Hopefully this will be fixed in Rust soon:
    // https://github.com/rust-lang/rust/issues/34158
    fn test_fastastats_err(minlen: u64, input: &String) -> () {
        let comp = FastaStats::new(minlen, input.as_bytes());
        match comp {
            Ok(result) => panic!(format!("expected Err(..) got {:?}", result)),
            Err(_error) => (),
        }
    }

    #[test]
    fn test_zero_byte_input() {
        test_fastastats_ok(0, &String::from(""), None)
    }

    #[test]
    fn test_single_newline_input() {
        test_fastastats_err(0, &String::from("\n"))
    }

    #[test]
    fn test_single_greater_than_input() {
        test_fastastats_ok(0,
                           &String::from(">"),
                           Some(FastaStats {
                               min_len: 0,
                               average_len: 0,
                               max_len: 0,
                               total: 0,
                               num_seqs: 1,
                           }))
    }

    #[test]
    fn one_sequence() {
        test_fastastats_ok(0,
                           &String::from(">header\nATGC\nA"),
                           Some(FastaStats {
                               min_len: 5,
                               average_len: 5,
                               max_len: 5,
                               total: 5,
                               num_seqs: 1,
                           }))
    }

    #[test]
    fn two_sequence() {
        test_fastastats_ok(0,
                           &String::from(">header1\nATGC\nAGG\n>header2\nTT\n"),
                           Some(FastaStats {
                               min_len: 2,
                               average_len: 4,
                               max_len: 7,
                               total: 9,
                               num_seqs: 2,
                           }))
    }

    #[test]
    fn no_header() {
        test_fastastats_err(0, &String::from("no header\n"))
    }

    #[test]
    fn minlen_less_than_all() {
        test_fastastats_ok(2,
                           &String::from(">header1\nATGC\nAGG\n>header2\nTT\n"),
                           Some(FastaStats {
                               min_len: 2,
                               average_len: 4,
                               max_len: 7,
                               total: 9,
                               num_seqs: 2,
                           }))
    }

    #[test]
    fn minlen_greater_than_one() {
        test_fastastats_ok(3,
                           &String::from(">header1\nATGC\nAGG\n>header2\nTT\n"),
                           Some(FastaStats {
                               min_len: 7,
                               average_len: 7,
                               max_len: 7,
                               total: 7,
                               num_seqs: 1,
                           }))
    }

    #[test]
    fn minlen_greater_than_all() {
        test_fastastats_ok(8,
                           &String::from(">header1\nATGC\nAGG\n>header2\nTT\n"),
                           None)
    }
}
<commit_msg>remove redundant 'test' from some test case names<commit_after>extern crate bio;
extern crate argparse;
use std::io;
use std::io::Write;
use std::cmp;
use bio::io::fasta;
use std::fmt;
use std::fs::File;
use argparse::{ArgumentParser, StoreTrue, Store, Print, Collect};

const EXIT_FILE_IO_ERROR: i32 = 1;
const EXIT_COMMAND_LINE_ERROR: i32 = 2;
const EXIT_FASTA_PARSE_ERROR: i32 = 3;
static PROGRAM_NAME: &'static str = "biotool";

fn exit_with_error(status: i32, message: &String) -> () {
    writeln!(&mut std::io::stderr(),
             "{} ERROR: {}!",
             PROGRAM_NAME,
             message)
        .unwrap();
    std::process::exit(status);
}

#[derive(Debug, PartialEq)]
pub struct FastaStats {
    min_len: u64,
    average_len: u64,
    max_len: u64,
    total: u64,
    num_seqs: u64,
}

#[derive(Debug)]
pub enum StatsResult {
    StatsNone,
    StatsSome(FastaStats),
    StatsError(io::Error),
}

impl FastaStats {
    pub fn new<R: io::Read>(minlen: u64, reader: R) -> Result<Option<FastaStats>, io::Error> {
        let fasta_reader = fasta::Reader::new(reader);
        let mut num_seqs: u64 = 0;
        let mut total: u64 = 0;
        let mut max_len: u64 = 0;
        let mut min_len: u64 = 0;
        let mut this_len: u64;

        for next in fasta_reader.records() {
            match next {
                Ok(record) => {
                    this_len = record.seq().len() as u64;
                    if this_len >= minlen {
                        num_seqs += 1;
                        total += this_len;
                        if num_seqs == 1 {
                            max_len = this_len;
                            min_len = this_len;
                        } else {
                            max_len = cmp::max(max_len, this_len);
                            min_len = cmp::min(min_len, this_len);
                        }
                    }
                }
                // Err(error) => return StatsResult::StatsError(error)
                Err(error) => return Err(error),
            }
        }
        if num_seqs > 0 {
            let average_len = ((total as f64) / (num_seqs as f64)).floor() as u64;
            Ok(Some(FastaStats {
                min_len: min_len,
                average_len: average_len,
                max_len: max_len,
                total: total,
                num_seqs: num_seqs,
            }))
        } else {
            Ok(None)
        }
    }
}

impl fmt::Display for FastaStats {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}\t{}\t{}\t{}\t{}",
               self.num_seqs,
               self.total,
               self.min_len,
               self.average_len,
               self.max_len)
    }
}

struct Options {
    verbose: bool,
    minlen: u64,
    fasta_files: Vec<String>,
}

fn parse_options() -> Options {
    let mut options = Options {
        verbose: false,
        minlen: 0,
        fasta_files: Vec::new(),
    };
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Print fasta stats");
        ap.refer(&mut options.verbose)
            .add_option(&["-v", "--verbose"],
                        StoreTrue,
                        "Print more stuff about what's happening");
        ap.refer(&mut options.minlen)
            .add_option(&["--minlen"],
                        Store,
                        "Minimum length sequence to include in stats");
        ap.refer(&mut options.fasta_files)
            .add_argument(&"fasta_files", Collect, "Input FASTA files");
        ap.add_option(&["--version"],
                      Print(env!("CARGO_PKG_VERSION").to_string()),
                      "Show version");
        match ap.parse_args() {
            Ok(()) => (),
            Err(0) => {
                // Help and version commands
                std::process::exit(0);
            }
            Err(_error_code) => {
                // Parse error
                std::process::exit(EXIT_COMMAND_LINE_ERROR);
            }
        }
    }
    return options;
}

fn compute_print_stats<R: io::Read>(options: &Options, filename: &String, reader: R) -> () {
    match FastaStats::new(options.minlen, reader) {
        // StatsResult::StatsSome(stats) => {
        Ok(Some(stats)) => {
            println!("{}\t{}", filename, stats);
        }
        Ok(None) => {
            println!("{}\t0\t0\t-\t-\t-", filename);
        }
        Err(error) => exit_with_error(EXIT_FASTA_PARSE_ERROR, &format!("{}", error)),
    }
}

fn main() {
    let options = parse_options();
    println!("FILENAME\tTOTAL\tNUMSEQ\tMIN\tAVG\tMAX");
    if options.fasta_files.len() == 0 {
        compute_print_stats(&options, &String::from("stdin"), io::stdin());
    } else {
        for filename in &options.fasta_files {
            match File::open(filename) {
                Ok(file) => {
                    compute_print_stats(&options, filename, file);
                }
                Err(error) => exit_with_error(EXIT_FILE_IO_ERROR, &format!("{}", error)),
            }
        }
    }
}

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

    fn test_fastastats_ok(minlen: u64, input: &String, expected: Option<FastaStats>) -> () {
        match FastaStats::new(minlen, input.as_bytes()) {
            Ok(result) => {
                if result != expected {
                    panic!(format!("expected {:?} got {:?}", expected, result))
                }
            }
            Err(_error) => panic!(format!("expected {:?} got Err(..)", expected)),
        }
    }

    // io::Error does not currently implement PartialEq, so we resort to
    // just checking for the existence of an error, not its actual content.
    // Hopefully this will be fixed in Rust soon:
    // https://github.com/rust-lang/rust/issues/34158
    fn test_fastastats_err(minlen: u64, input: &String) -> () {
        let comp = FastaStats::new(minlen, input.as_bytes());
        match comp {
            Ok(result) => panic!(format!("expected Err(..) got {:?}", result)),
            Err(_error) => (),
        }
    }

    #[test]
    fn zero_byte_input() {
        test_fastastats_ok(0, &String::from(""), None)
    }

    #[test]
    fn single_newline_input() {
        test_fastastats_err(0, &String::from("\n"))
    }

    #[test]
    fn single_greater_than_input() {
        test_fastastats_ok(0,
                           &String::from(">"),
                           Some(FastaStats {
                               min_len: 0,
                               average_len: 0,
                               max_len: 0,
                               total: 0,
                               num_seqs: 1,
                           }))
    }

    #[test]
    fn one_sequence() {
        test_fastastats_ok(0,
                           &String::from(">header\nATGC\nA"),
                           Some(FastaStats {
                               min_len: 5,
                               average_len: 5,
                               max_len: 5,
                               total: 5,
                               num_seqs: 1,
                           }))
    }

    #[test]
    fn two_sequence() {
        test_fastastats_ok(0,
                           &String::from(">header1\nATGC\nAGG\n>header2\nTT\n"),
                           Some(FastaStats {
                               min_len: 2,
                               average_len: 4,
                               max_len: 7,
                               total: 9,
                               num_seqs: 2,
                           }))
    }

    #[test]
    fn no_header() {
        test_fastastats_err(0, &String::from("no header\n"))
    }

    #[test]
    fn minlen_less_than_all() {
        test_fastastats_ok(2,
                           &String::from(">header1\nATGC\nAGG\n>header2\nTT\n"),
                           Some(FastaStats {
                               min_len: 2,
                               average_len: 4,
                               max_len: 7,
                               total: 9,
                               num_seqs: 2,
                           }))
    }

    #[test]
    fn minlen_greater_than_one() {
        test_fastastats_ok(3,
                           &String::from(">header1\nATGC\nAGG\n>header2\nTT\n"),
                           Some(FastaStats {
                               min_len: 7,
                               average_len: 7,
                               max_len: 7,
                               total: 7,
                               num_seqs: 1,
                           }))
    }

    #[test]
    fn minlen_greater_than_all() {
        test_fastastats_ok(8,
                           &String::from(">header1\nATGC\nAGG\n>header2\nTT\n"),
                           None)
    }
}
<|endoftext|>