<commit_before>use std::collections::HashMap;

use ursa::cl::Proof as CryptoProof;

use super::schema::SchemaId;
use super::credential_definition::CredentialDefinitionId;
use super::revocation_registry_definition::RevocationRegistryId;
use indy_api_types::validation::Validatable;

#[derive(Debug, Serialize, Deserialize)]
pub struct Proof {
    pub proof: CryptoProof,
    pub requested_proof: RequestedProof,
    pub identifiers: Vec<Identifier>
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RequestedProof {
    pub revealed_attrs: HashMap<String, RevealedAttributeInfo>,
    pub revealed_attr_groups: HashMap<String, RevealedAttributeGroupInfo>,
    pub self_attested_attrs: HashMap<String, String>,
    pub unrevealed_attrs: HashMap<String, SubProofReferent>,
    pub predicates: HashMap<String, SubProofReferent>
}

impl Default for RequestedProof {
    fn default() -> Self {
        RequestedProof {
            revealed_attrs: HashMap::new(),
            revealed_attr_groups: HashMap::new(),
            self_attested_attrs: HashMap::new(),
            unrevealed_attrs: HashMap::new(),
            predicates: HashMap::new(),
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SubProofReferent {
    pub sub_proof_index: u32,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RevealedAttributeInfo {
    pub sub_proof_index: u32,
    pub raw: String,
    pub encoded: String
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RevealedAttributeGroupInfo {
    pub sub_proof_index: u32,
    pub values: HashMap<String, AttributeValue>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AttributeValue {
    pub raw: String,
    pub encoded: String
}

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
pub struct Identifier {
    pub schema_id: SchemaId,
    pub cred_def_id: CredentialDefinitionId,
    pub rev_reg_id: Option<RevocationRegistryId>,
    pub timestamp: Option<u64>
}

impl Validatable for Proof {}<commit_msg>Update libindy/src/domain/anoncreds/proof.rs<commit_after>use std::collections::HashMap;

use ursa::cl::Proof as CryptoProof;

use super::schema::SchemaId;
use super::credential_definition::CredentialDefinitionId;
use super::revocation_registry_definition::RevocationRegistryId;
use indy_api_types::validation::Validatable;

#[derive(Debug, Serialize, Deserialize)]
pub struct Proof {
    pub proof: CryptoProof,
    pub requested_proof: RequestedProof,
    pub identifiers: Vec<Identifier>
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RequestedProof {
    pub revealed_attrs: HashMap<String, RevealedAttributeInfo>,
    pub revealed_attr_groups: HashMap<String, RevealedAttributeGroupInfo>,
    pub self_attested_attrs: HashMap<String, String>,
    pub unrevealed_attrs: HashMap<String, SubProofReferent>,
    pub predicates: HashMap<String, SubProofReferent>
}

impl Default for RequestedProof {
    fn default() -> Self {
        RequestedProof {
            revealed_attrs: HashMap::new(),
            revealed_attr_groups: HashMap::new(),
            self_attested_attrs: HashMap::new(),
            unrevealed_attrs: HashMap::new(),
            predicates: HashMap::new(),
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SubProofReferent {
    pub sub_proof_index: u32,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RevealedAttributeInfo {
    pub sub_proof_index: u32,
    pub raw: String,
    pub encoded: String
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RevealedAttributeGroupInfo {
    pub sub_proof_index: u32,
    pub values: HashMap<String /* attribute name */, AttributeValue>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AttributeValue {
    pub raw: String,
    pub encoded: String
}

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
pub struct Identifier {
    pub schema_id: SchemaId,
    pub cred_def_id: CredentialDefinitionId,
    pub rev_reg_id: Option<RevocationRegistryId>,
    pub timestamp: Option<u64>
}

impl Validatable for Proof {}
<|endoftext|>


<commit_before>//! Common definitions for wayland
//!
//! This crate hosts common type and traits used to represent wayland messages
//! and routines in the `wayland-client` and `wayland-server` crates.
//!
//! This notably includes the `Interface` trait, which can exhaustively describe
//! any wayland interface. Its implementations are intented to be generated by the
//! `wayland-scanner` crate.
//!
//! The principal user-facing definition provided by this crate is the `Implementation`
//! trait, which as a user of `wayland-client` or `wayland-server` you will be using
//! to define objects able to handle the messages your program receives. Note that
//! this trait is auto-implemented for closures with appropriate signature, for
//! convenience.

#![warn(missing_docs)]

#[macro_use]
extern crate downcast_rs as downcast;
extern crate nix;
#[cfg(feature = "native_lib")]
extern crate wayland_sys;
#[cfg(feature = "native_lib")]
use std::os::raw::c_void;
#[cfg(feature = "native_lib")]
use wayland_sys::common as syscom;

use downcast::Downcast;

pub mod map;
pub mod socket;
pub mod wire;

/// A group of messages
///
/// This represents a group of message that can be serialized on the protocol wire.
/// Typically the set of events or requests of a single interface.
///
/// Implementations of this trait are supposed to be
/// generated using the `wayland-scanner` crate.
pub trait MessageGroup: Sized {
    /// Wire representation of this MessageGroup
    const MESSAGES: &'static [wire::MessageDesc];
    type Map;
    /// Whether this message is a destructor
    ///
    /// If it is, once send or receive the associated object cannot be used any more.
    fn is_destructor(&self) -> bool;
    /// Retrieve the child `Object` associated with this message if any
    fn child<Meta: self::map::ObjectMetadata>(
        opcode: u16,
        version: u32,
        meta: &Meta,
    ) -> Option<::map::Object<Meta>>;
    /// Construct a message from its raw representation
    fn from_raw(msg: wire::Message, map: &mut Self::Map) -> Result<Self, ()>;
    /// Turn this message into its raw representation
    fn into_raw(self, send_id: u32) -> wire::Message;
    #[cfg(feature = "native_lib")]
    /// Construct a message of this group from its C representation
    unsafe fn from_raw_c(obj: *mut c_void, opcode: u32, args: *const syscom::wl_argument)
        -> Result<Self, ()>;
    #[cfg(feature = "native_lib")]
    /// Build a C representation of this message
    ///
    /// It can only be accessed from the provided closure, and this consumes
    /// the message.
    fn as_raw_c_in<F, T>(self, f: F) -> T
    where
        F: FnOnce(u32, &mut [syscom::wl_argument]) -> T;
}

/// The description of a wayland interface
///
/// Implementations of this trait are supposed to be
/// generated using the `wayland-scanner` crate.
pub trait Interface: 'static {
    /// Set of requests associated to this interface
    ///
    /// Requests are messages from the client to the server
    type Request: MessageGroup + 'static;
    /// Set of events associated to this interface
    ///
    /// Events are messages from the server to the client
    type Event: MessageGroup + 'static;
    /// Name of this interface
    const NAME: &'static str;
    /// Maximum supported version of this interface
    const VERSION: u32;
    #[cfg(feature = "native_lib")]
    /// Pointer to the C representation of this interface
    fn c_interface() -> *const ::syscom::wl_interface;
}

/// Trait representing implementations for wayland objects
///
/// Several wayland objects require you to act when some messages
/// are received. You program this act by providing an object
/// implementing this trait.
///
/// The trait requires a single method: `self.receive(message, metadata)`.
/// the `message` argument will often be an enum of the possible messages,
/// and the `metadata` argument contains associated information. Typically
/// an handle to the wayland object that received this message.
///
/// The trait is automatically implemented for `FnMut(Msg, Meta)` closures.
///
/// This is mostly used as a trait object in `wayland-client` and `wayland-server`,
/// and thus also provide methods providing `Any`-like downcasting functionnality.
/// See also the `downcast_impl` freestanding function.
pub trait Implementation<Meta, Msg>: Downcast {
    /// Receive a message
    fn receive(&mut self, msg: Msg, meta: Meta);
}

impl_downcast!(Implementation<Meta, Msg>);

impl<Meta, Msg, F> Implementation<Meta, Msg> for F
where
    F: FnMut(Msg, Meta) + 'static,
{
    fn receive(&mut self, msg: Msg, meta: Meta) {
        (self)(msg, meta)
    }
}

/// Attempt to downcast a boxed `Implementation` trait object.
///
/// Similar to `Box::<Any>::downcast()`.
pub fn downcast_impl<Msg: 'static, Meta: 'static, T: Implementation<Meta, Msg>>(
    b: Box<Implementation<Meta, Msg>>,
) -> Result<Box<T>, Box<Implementation<Meta, Msg>>> {
    if b.is::<T>() {
        unsafe {
            let raw: *mut Implementation<Meta, Msg> = Box::into_raw(b);
            Ok(Box::from_raw(raw as *mut T))
        }
    } else {
        Err(b)
    }
}

/// Anonymous interface
///
/// A special Interface implementation representing an
/// handle to an object for which the interface is not known.
pub struct AnonymousObject;

/// An empty enum representing a MessageGroup with no messages
pub enum NoMessage {}

impl Interface for AnonymousObject {
    type Request = NoMessage;
    type Event = NoMessage;
    const NAME: &'static str = "<anonymous>";
    const VERSION: u32 = 0;
    #[cfg(feature = "native_lib")]
    fn c_interface() -> *const ::syscom::wl_interface {
        ::std::ptr::null()
    }
}

impl MessageGroup for NoMessage {
    const MESSAGES: &'static [wire::MessageDesc] = &[];
    type Map = ();
    fn is_destructor(&self) -> bool {
        match *self {}
    }
    fn child<M: self::map::ObjectMetadata>(_: u16, _: u32, _: &M) -> Option<::map::Object<M>> {
        None
    }
    fn from_raw(_: wire::Message, map: &mut ()) -> Result<Self, ()> {
        Err(())
    }
    fn into_raw(self, _: u32) -> wire::Message {
        match self {}
    }
    #[cfg(feature = "native_lib")]
    unsafe fn from_raw_c(
        _obj: *mut c_void,
        _opcode: u32,
        _args: *const syscom::wl_argument,
    ) -> Result<Self, ()> {
        Err(())
    }
    #[cfg(feature = "native_lib")]
    fn as_raw_c_in<F, T>(self, _f: F) -> T
    where
        F: FnOnce(u32, &mut [syscom::wl_argument]) -> T,
    {
        match self {}
    }
}
<commit_msg>commons: don't measure coverage for NoMessage<commit_after>//! Common definitions for wayland
//!
//! This crate hosts common type and traits used to represent wayland messages
//! and routines in the `wayland-client` and `wayland-server` crates.
//!
//! This notably includes the `Interface` trait, which can exhaustively describe
//! any wayland interface. Its implementations are intented to be generated by the
//! `wayland-scanner` crate.
//!
//! The principal user-facing definition provided by this crate is the `Implementation`
//! trait, which as a user of `wayland-client` or `wayland-server` you will be using
//! to define objects able to handle the messages your program receives. Note that
//! this trait is auto-implemented for closures with appropriate signature, for
//! convenience.

#![warn(missing_docs)]

#[macro_use]
extern crate downcast_rs as downcast;
extern crate nix;
#[cfg(feature = "native_lib")]
extern crate wayland_sys;
#[cfg(feature = "native_lib")]
use std::os::raw::c_void;
#[cfg(feature = "native_lib")]
use wayland_sys::common as syscom;

use downcast::Downcast;

pub mod map;
pub mod socket;
pub mod wire;

/// A group of messages
///
/// This represents a group of message that can be serialized on the protocol wire.
/// Typically the set of events or requests of a single interface.
///
/// Implementations of this trait are supposed to be
/// generated using the `wayland-scanner` crate.
pub trait MessageGroup: Sized {
    /// Wire representation of this MessageGroup
    const MESSAGES: &'static [wire::MessageDesc];
    type Map;
    /// Whether this message is a destructor
    ///
    /// If it is, once send or receive the associated object cannot be used any more.
    fn is_destructor(&self) -> bool;
    /// Retrieve the child `Object` associated with this message if any
    fn child<Meta: self::map::ObjectMetadata>(
        opcode: u16,
        version: u32,
        meta: &Meta,
    ) -> Option<::map::Object<Meta>>;
    /// Construct a message from its raw representation
    fn from_raw(msg: wire::Message, map: &mut Self::Map) -> Result<Self, ()>;
    /// Turn this message into its raw representation
    fn into_raw(self, send_id: u32) -> wire::Message;
    #[cfg(feature = "native_lib")]
    /// Construct a message of this group from its C representation
    unsafe fn from_raw_c(obj: *mut c_void, opcode: u32, args: *const syscom::wl_argument)
        -> Result<Self, ()>;
    #[cfg(feature = "native_lib")]
    /// Build a C representation of this message
    ///
    /// It can only be accessed from the provided closure, and this consumes
    /// the message.
    fn as_raw_c_in<F, T>(self, f: F) -> T
    where
        F: FnOnce(u32, &mut [syscom::wl_argument]) -> T;
}

/// The description of a wayland interface
///
/// Implementations of this trait are supposed to be
/// generated using the `wayland-scanner` crate.
pub trait Interface: 'static {
    /// Set of requests associated to this interface
    ///
    /// Requests are messages from the client to the server
    type Request: MessageGroup + 'static;
    /// Set of events associated to this interface
    ///
    /// Events are messages from the server to the client
    type Event: MessageGroup + 'static;
    /// Name of this interface
    const NAME: &'static str;
    /// Maximum supported version of this interface
    const VERSION: u32;
    #[cfg(feature = "native_lib")]
    /// Pointer to the C representation of this interface
    fn c_interface() -> *const ::syscom::wl_interface;
}

/// Trait representing implementations for wayland objects
///
/// Several wayland objects require you to act when some messages
/// are received. You program this act by providing an object
/// implementing this trait.
///
/// The trait requires a single method: `self.receive(message, metadata)`.
/// the `message` argument will often be an enum of the possible messages,
/// and the `metadata` argument contains associated information. Typically
/// an handle to the wayland object that received this message.
///
/// The trait is automatically implemented for `FnMut(Msg, Meta)` closures.
///
/// This is mostly used as a trait object in `wayland-client` and `wayland-server`,
/// and thus also provide methods providing `Any`-like downcasting functionnality.
/// See also the `downcast_impl` freestanding function.
pub trait Implementation<Meta, Msg>: Downcast {
    /// Receive a message
    fn receive(&mut self, msg: Msg, meta: Meta);
}

impl_downcast!(Implementation<Meta, Msg>);

impl<Meta, Msg, F> Implementation<Meta, Msg> for F
where
    F: FnMut(Msg, Meta) + 'static,
{
    fn receive(&mut self, msg: Msg, meta: Meta) {
        (self)(msg, meta)
    }
}

/// Attempt to downcast a boxed `Implementation` trait object.
///
/// Similar to `Box::<Any>::downcast()`.
pub fn downcast_impl<Msg: 'static, Meta: 'static, T: Implementation<Meta, Msg>>(
    b: Box<Implementation<Meta, Msg>>,
) -> Result<Box<T>, Box<Implementation<Meta, Msg>>> {
    if b.is::<T>() {
        unsafe {
            let raw: *mut Implementation<Meta, Msg> = Box::into_raw(b);
            Ok(Box::from_raw(raw as *mut T))
        }
    } else {
        Err(b)
    }
}

/// Anonymous interface
///
/// A special Interface implementation representing an
/// handle to an object for which the interface is not known.
pub struct AnonymousObject;

/// An empty enum representing a MessageGroup with no messages
pub enum NoMessage {}

impl Interface for AnonymousObject {
    type Request = NoMessage;
    type Event = NoMessage;
    const NAME: &'static str = "<anonymous>";
    const VERSION: u32 = 0;
    #[cfg(feature = "native_lib")]
    fn c_interface() -> *const ::syscom::wl_interface {
        ::std::ptr::null()
    }
}

#[cfg_attr(tarpaulin, skip)]
impl MessageGroup for NoMessage {
    const MESSAGES: &'static [wire::MessageDesc] = &[];
    type Map = ();
    fn is_destructor(&self) -> bool {
        match *self {}
    }
    fn child<M: self::map::ObjectMetadata>(_: u16, _: u32, _: &M) -> Option<::map::Object<M>> {
        None
    }
    fn from_raw(_: wire::Message, map: &mut ()) -> Result<Self, ()> {
        Err(())
    }
    fn into_raw(self, _: u32) -> wire::Message {
        match self {}
    }
    #[cfg(feature = "native_lib")]
    unsafe fn from_raw_c(
        _obj: *mut c_void,
        _opcode: u32,
        _args: *const syscom::wl_argument,
    ) -> Result<Self, ()> {
        Err(())
    }
    #[cfg(feature = "native_lib")]
    fn as_raw_c_in<F, T>(self, _f: F) -> T
    where
        F: FnOnce(u32, &mut [syscom::wl_argument]) -> T,
    {
        match self {}
    }
}
<|endoftext|>


<commit_before>use super::primitive::{Point2D, RectHV};

use std::iter;
use std::fmt;
use std::f64;
use std::vec::IntoIter;
use std::cmp::Ordering;
use super::super::symbol_tables::ST;
use super::super::stacks_and_queues::Queue;
use super::super::stacks_and_queues::resizing_array_queue::ResizingArrayQueue;

pub trait Point: Copy {
    type ValueType: Copy + PartialOrd = f64;
    // const DIMENSION: usize = 2;

    #[inline]
    fn get(&self, d: usize) -> Self::ValueType;

    #[inline]
    fn dimension() -> usize { 2 }
}

impl Point for Point2D {
    #[inline]
    fn get(&self, d: usize) -> f64 {
        if d == 0 {
            self.x
        } else if d == 1 {
            self.y
        } else {
            panic!("dimension not supported")
        }
    }
}

pub struct Node<K: Point, V> {
    pub key: K,
    pub val: V,
    pub left:  Option<Box<Node<K, V>>>,
    pub right: Option<Box<Node<K, V>>>,
    pub depth: usize
}

impl<K: Point, V> Node<K, V> {
    pub fn new(key: K, val: V, depth: usize) -> Node<K, V> {
        Node {
            key: key,
            val: val,
            left: None,
            right: None,
            // depth use (depth % k)-th dimension
            depth: depth
        }
    }

    fn size(&self) -> usize {
        let mut ret = 1;
        if self.left.is_some() {
            ret += self.left.as_ref().unwrap().size()
        }
        if self.right.is_some() {
            ret += self.right.as_ref().unwrap().size()
        }
        ret
    }

    #[inline]
    fn comparator_for_current_dim(&self) -> K::ValueType {
        // let dim = self.depth % <K as Point>::dimension();
        self.key.get(self.depth % <K as Point>::dimension())
    }
}

impl<K: Point + fmt::Debug, V: fmt::Debug> Node<K, V> {
    fn dump(&self, depth: usize, f: &mut fmt::Formatter, symbol: char) {
        if depth == 0 {
            writeln!(f, "\n{:?}[{:?}]", self.key, self.val).unwrap();
        } else {
            writeln!(f, "{}{}--{:?}[{:?}]", iter::repeat("|  ").take(depth-1).collect::<Vec<&str>>().concat(),
                     symbol, self.key, self.val).unwrap();
        }
        if self.left.is_some() {
            self.left.as_ref().unwrap().dump(depth + 1, f, '+');
        }
        if self.right.is_some() {
            self.right.as_ref().unwrap().dump(depth + 1, f, '`');
        }
    }
}

fn put<K: Point, V>(x: Option<Box<Node<K,V>>>, key: K, val: V, depth: usize) -> Option<Box<Node<K,V>>> {
    let mut x = x;
    if x.is_none() {
        return Some(Box::new(Node::new(key, val, depth)));
    }
    let depth = x.as_ref().unwrap().depth;
    let dim = x.as_ref().unwrap().depth % <K as Point>::dimension();

    let cmp = key.get(dim).partial_cmp(&x.as_ref().unwrap().key.get(dim)).unwrap();
    match cmp {
        Ordering::Less => {
            let left = x.as_mut().unwrap().left.take();
            x.as_mut().unwrap().left = put(left, key, val, depth + 1)
        },
        Ordering::Greater => {
            let right = x.as_mut().unwrap().right.take();
            x.as_mut().unwrap().right = put(right, key, val, depth + 1)
        },
        Ordering::Equal => {
            x.as_mut().unwrap().val = val
        }
    }
    x
}

fn delete_min<K: Point, V>(x: Option<Box<Node<K,V>>>) -> (Option<Box<Node<K,V>>>, Option<Box<Node<K,V>>>) {
    let mut x = x;
    if x.is_none() {
        return (None, None);
    }
    match x.as_mut().unwrap().left.take() {
        None           => (x.as_mut().unwrap().right.take(), x),
        left @ Some(_) => {
            let (t, deleted) = delete_min(left);
            x.as_mut().unwrap().left = t;
            (x, deleted)
        }
    }
}

fn delete<K: Point, V>(x: Option<Box<Node<K,V>>>, key: &K) -> Option<Box<Node<K,V>>> {
    if x.is_none() {
        return None;
    }

    let mut x = x;
    let dim = x.as_ref().unwrap().depth % <K as Point>::dimension();

    match key.get(dim).partial_cmp(&x.as_ref().unwrap().key.get(dim)).unwrap() {
        Ordering::Less => {
            let left = x.as_mut().unwrap().left.take();
            x.as_mut().unwrap().left = delete(left, key);
            return x;
        },
        Ordering::Greater => {
            let right = x.as_mut().unwrap().right.take();
            x.as_mut().unwrap().right = delete(right, key);
            return x;
        },
        Ordering::Equal => {
            if x.as_ref().unwrap().right.is_none() {
                return x.as_mut().unwrap().left.take();
            }
            if x.as_ref().unwrap().left.is_none() {
                return x.as_mut().unwrap().right.take();
            }

            // Save top
            let mut t = x;

            // split right into right without min, and the min
            let (right, right_min) = delete_min(t.as_mut().unwrap().right.take());
            x = right_min;
            x.as_mut().unwrap().right = right;
            x.as_mut().unwrap().left = t.as_mut().unwrap().left.take();
            x
        }
    }
}

pub struct KdTree<K: Point, V> {
    pub root: Option<Box<Node<K, V>>>
}

impl<K: Point, V> ST<K, V> for KdTree<K, V> {
    fn new() -> KdTree<K, V> {
        KdTree { root: None }
    }

    fn get(&self, key: &K) -> Option<&V> {
        let mut x = self.root.as_ref();
        while x.is_some() {
            let dim = x.as_ref().unwrap().depth % <K as Point>::dimension();
            match key.get(dim).partial_cmp(&x.unwrap().key.get(dim)).unwrap() {
                Ordering::Less => {
                    x = x.unwrap().left.as_ref();
                },
                Ordering::Greater => {
                    x = x.unwrap().right.as_ref();
                },
                Ordering::Equal  => {
                    return Some(&x.unwrap().val)
                }
            }
        }
        None
    }

    fn put(&mut self, key: K, val: V) {
        self.root = put(self.root.take(), key, val, 0);
    }

    fn delete(&mut self, key: &K) {
        self.root = delete(self.root.take(), key);
    }

    fn is_empty(&self) -> bool {
        self.root.is_none()
    }

    /// number of key-value pairs in the table
    fn size(&self) -> usize {
        if self.is_empty() {
            0
        } else {
            self.root.as_ref().unwrap().size()
        }
    }
}

impl<K: Point, V> KdTree<K, V> {
    pub fn keys<'a>(&'a self) -> ::std::vec::IntoIter<&'a K> {
        let mut queue: Vec<&'a K> = Vec::new();
        fn inorder<'a, K: Point, V>(x: Option<&'a Box<Node<K,V>>>, queue: &mut Vec<&'a K>) {
            if x.is_none() {
                return;
            }
            inorder(x.unwrap().left.as_ref(), queue);
            queue.push(&x.unwrap().key);
            inorder(x.unwrap().right.as_ref(), queue);
        };
        inorder(self.root.as_ref(), &mut queue);
        queue.into_iter()
    }
}

impl KdTree<Point2D, ()> {
    // add the point to the KdTree
    pub fn insert(&mut self, p: Point2D) {
        self.put(p, ());
    }

    /// find all Point2D keys that lie in a 2d range
    pub fn range_search<T: AsRef<RectHV>>(&self, rect: T) -> IntoIter<&Point2D> {
        let mut result = Vec::new();

        // use stack approach
        let mut stack = Vec::new();
        stack.push(self.root.as_ref());
        while !stack.is_empty() {
            let x = stack.pop().unwrap();

            if x.is_none() {
                continue;
            }

            let dim = x.as_ref().unwrap().depth % 2;

            // Check if point in node lies in given rectangle
            if rect.as_ref().contains(x.as_ref().unwrap().key) {
                result.push(&x.as_ref().unwrap().key)
            }
            // Recursively search left/bottom (if any could fall in rectangle)
            // Recursively search right/top (if any could fall in rectangle)
            if dim == 0 {
                if rect.as_ref().xmin < x.as_ref().unwrap().comparator_for_current_dim() {
                    stack.push(x.unwrap().left.as_ref())
                }
                if rect.as_ref().xmax > x.as_ref().unwrap().comparator_for_current_dim() {
                    stack.push(x.unwrap().right.as_ref())
                }
            } else {        // dim == 1: y
                if rect.as_ref().ymin < x.as_ref().unwrap().comparator_for_current_dim() {
                    stack.push(x.unwrap().left.as_ref())
                }
                if rect.as_ref().ymax > x.as_ref().unwrap().comparator_for_current_dim() {
                    stack.push(x.unwrap().right.as_ref())
                }
            }
        }
        result.into_iter()
    }

    /// number of keys that lie in a 2d range
    pub fn range_count<T: AsRef<RectHV>>(&self, rect: T) -> usize {
        self.range_search(rect).count()
    }

    pub fn nearest<T: AsRef<Point2D>>(&self, p: T) -> Option<&Point2D> {
        let mut result = None;
        let mut min_distance_squared = f64::MAX;
        let p = p.as_ref();

        let mut queue = ResizingArrayQueue::new();
        queue.enqueue(self.root.as_ref());
        while !queue.is_empty() {
            let x = queue.dequeue().unwrap();

            if x.is_none() {
                continue;
            }

            let dim = x.as_ref().unwrap().depth % 2;

            // Check distance from point in node to query point
            let dist = x.as_ref().unwrap().key.distance_squared_to(p);
            if dist < min_distance_squared {
                result = Some(&x.as_ref().unwrap().key);
                min_distance_squared = dist;
            }

            // Recursively search left/bottom (if it could contain a closer point)
            // Recursively search right/top (if it could contain a closer point)
            // TODO: pruning
            if dim == 0 {
                if p.x < x.as_ref().unwrap().comparator_for_current_dim() {
                    queue.enqueue(x.unwrap().left.as_ref());
                    queue.enqueue(x.unwrap().right.as_ref());
                } else {
                    queue.enqueue(x.unwrap().right.as_ref());
                    queue.enqueue(x.unwrap().left.as_ref());
                }
            } else {        // dim == 1: y
                if p.y < x.as_ref().unwrap().comparator_for_current_dim() {
                    queue.enqueue(x.unwrap().left.as_ref());
                    queue.enqueue(x.unwrap().right.as_ref());
                } else {
                    queue.enqueue(x.unwrap().right.as_ref());
                    queue.enqueue(x.unwrap().left.as_ref());
                }
            }
        }
        result

    }
}

impl<K: Point + fmt::Debug, V: fmt::Debug> fmt::Debug for KdTree<K, V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.root.is_none() {
            write!(f, "<empty tree>")
        } else {
            self.root.as_ref().unwrap().dump(0, f, ' ');
            Ok(())
        }
    }
}

#[test]
fn test_kd_tree_with_point_2d() {
    let mut t = KdTree::<Point2D, ()>::new();

    t.put(Point2D::new(0.7, 0.2), ());
    t.put(Point2D::new(0.5, 0.4), ());
    t.put(Point2D::new(0.2, 0.3), ());
    t.put(Point2D::new(0.4, 0.7), ());
    t.put(Point2D::new(0.9, 0.6), ());

    println!("got => {:?}", t);

    assert_eq!(5, t.range_search(RectHV::new(0.1, 0.1, 0.9, 0.9)).count());
    assert_eq!(1, t.range_search(RectHV::new(0.1, 0.1, 0.4, 0.4)).count());

    assert_eq!(&Point2D::new(0.2, 0.3), t.nearest(Point2D::new(0.1, 0.1)).unwrap());
}

// BUG, if equal key? then points missing
#[test]
fn test_kd_tree_with_point_2d_duplicated() {
    let mut t = KdTree::<Point2D, ()>::new();

    t.put(Point2D::new(0.7, 0.2), ());
    t.put(Point2D::new(0.5, 0.4), ());
    t.put(Point2D::new(0.2, 0.3), ());
    t.put(Point2D::new(0.2, 0.7), ());
    t.put(Point2D::new(0.4, 0.7), ());
    t.put(Point2D::new(0.4, 0.2), ());
    t.put(Point2D::new(0.9, 0.6), ());
    t.put(Point2D::new(0.7, 0.4), ());

    println!("got => {:?}", t);

    // assert_eq!(8, t.size());

    // assert_eq!(7, t.range_search(RectHV::new(0.1, 0.1, 0.9, 0.9)).count());
    assert_eq!(2, t.range_search(RectHV::new(0.1, 0.1, 0.4, 0.4)).count());
}
<commit_msg>kd_tree: fix bug when current dimension equals in get()/put()<commit_after>use super::primitive::{Point2D, RectHV};

use std::iter;
use std::fmt;
use std::f64;
use std::vec::IntoIter;
use std::cmp::Ordering;
use super::super::symbol_tables::ST;
use super::super::stacks_and_queues::Queue;
use super::super::stacks_and_queues::resizing_array_queue::ResizingArrayQueue;

pub trait Point: Copy {
    type ValueType: Copy + PartialOrd = f64;
    // const DIMENSION: usize = 2;

    #[inline]
    fn get(&self, d: usize) -> Self::ValueType;

    #[inline]
    fn dimension() -> usize { 2 }
}

impl Point for Point2D {
    #[inline]
    fn get(&self, d: usize) -> f64 {
        if d == 0 {
            self.x
        } else if d == 1 {
            self.y
        } else {
            panic!("dimension not supported")
        }
    }
}

pub struct Node<K: Point, V> {
    pub key: K,
    pub val: V,
    pub left:  Option<Box<Node<K, V>>>,
    pub right: Option<Box<Node<K, V>>>,
    pub depth: usize
}

impl<K: Point, V> Node<K, V> {
    pub fn new(key: K, val: V, depth: usize) -> Node<K, V> {
        Node {
            key: key,
            val: val,
            left: None,
            right: None,
            // depth use (depth % k)-th dimension
            depth: depth
        }
    }

    fn size(&self) -> usize {
        let mut ret = 1;
        if self.left.is_some() {
            ret += self.left.as_ref().unwrap().size()
        }
        if self.right.is_some() {
            ret += self.right.as_ref().unwrap().size()
        }
        ret
    }

    #[inline]
    fn comparator_for_current_dim(&self) -> K::ValueType {
        // let dim = self.depth % <K as Point>::dimension();
        self.key.get(self.depth % <K as Point>::dimension())
    }
}

impl<K: Point + fmt::Debug, V: fmt::Debug> Node<K, V> {
    fn dump(&self, depth: usize, f: &mut fmt::Formatter, symbol: char) {
        if depth == 0 {
            writeln!(f, "\n{:?}[{:?}]", self.key, self.val).unwrap();
        } else {
            writeln!(f, "{}{}--{:?}[{:?}]", iter::repeat("|  ").take(depth-1).collect::<Vec<&str>>().concat(),
                     symbol, self.key, self.val).unwrap();
        }
        if self.left.is_some() {
            self.left.as_ref().unwrap().dump(depth + 1, f, '+');
        }
        if self.right.is_some() {
            self.right.as_ref().unwrap().dump(depth + 1, f, '`');
        }
    }
}

fn put<K: Point, V>(x: Option<Box<Node<K,V>>>, key: K, val: V, depth: usize) -> Option<Box<Node<K,V>>> {
    let mut x = x;
    if x.is_none() {
        return Some(Box::new(Node::new(key, val, depth)));
    }
    let depth = x.as_ref().unwrap().depth;
    let dimension = <K as Point>::dimension();
    let current_dim = x.as_ref().unwrap().depth % dimension;
    let mut dim = current_dim;

    loop {
        let cmp = key.get(dim).partial_cmp(&x.as_ref().unwrap().key.get(dim)).unwrap();
        match cmp {
            Ordering::Less => {
                let left = x.as_mut().unwrap().left.take();
                x.as_mut().unwrap().left = put(left, key, val, depth + 1);
                break;
            },
            Ordering::Greater => {
                let right = x.as_mut().unwrap().right.take();
                x.as_mut().unwrap().right = put(right, key, val, depth + 1);
                break;
            },
            // when current dimension is equal, compare next non-equal dimension
            Ordering::Equal => {
                dim = (dim + 1) % dimension;
                if dim == current_dim {
                    x.as_mut().unwrap().val = val;
                    break;
                }
            }
        }
    }
    x
}

fn delete_min<K: Point, V>(x: Option<Box<Node<K,V>>>) -> (Option<Box<Node<K,V>>>, Option<Box<Node<K,V>>>) {
    let mut x = x;
    if x.is_none() {
        return (None, None);
    }
    match x.as_mut().unwrap().left.take() {
        None           => (x.as_mut().unwrap().right.take(), x),
        left @ Some(_) => {
            let (t, deleted) = delete_min(left);
            x.as_mut().unwrap().left = t;
            (x, deleted)
        }
    }
}

fn delete<K: Point, V>(x: Option<Box<Node<K,V>>>, key: &K) -> Option<Box<Node<K,V>>> {
    if x.is_none() {
        return None;
    }

    let mut x = x;
    let dim = x.as_ref().unwrap().depth % <K as Point>::dimension();

    match key.get(dim).partial_cmp(&x.as_ref().unwrap().key.get(dim)).unwrap() {
        Ordering::Less => {
            let left = x.as_mut().unwrap().left.take();
            x.as_mut().unwrap().left = delete(left, key);
            return x;
        },
        Ordering::Greater => {
            let right = x.as_mut().unwrap().right.take();
            x.as_mut().unwrap().right = delete(right, key);
            return x;
        },
        Ordering::Equal => {
            if x.as_ref().unwrap().right.is_none() {
                return x.as_mut().unwrap().left.take();
            }
            if x.as_ref().unwrap().left.is_none() {
                return x.as_mut().unwrap().right.take();
            }

            // Save top
            let mut t = x;

            // split right into right without min, and the min
            let (right, right_min) = delete_min(t.as_mut().unwrap().right.take());
            x = right_min;
            x.as_mut().unwrap().right = right;
            x.as_mut().unwrap().left = t.as_mut().unwrap().left.take();
            x
        }
    }
}

pub struct KdTree<K: Point, V> {
    pub root: Option<Box<Node<K, V>>>
}

impl<K: Point, V> ST<K, V> for KdTree<K, V> {
    fn new() -> KdTree<K, V> {
        assert!(K::dimension() >= 2);
        KdTree { root: None }
    }

    fn get(&self, key: &K) -> Option<&V> {
        let mut x = self.root.as_ref();
        let dimension = <K as Point>::dimension();
        let current_dim = x.as_ref().unwrap().depth % dimension;
        while x.is_some() {
            let mut dim = current_dim;
            loop {
                match key.get(dim).partial_cmp(&x.unwrap().key.get(dim)).unwrap() {
                    Ordering::Less => {
                        x = x.unwrap().left.as_ref();
                        break;
                    },
                    Ordering::Greater => {
                        x = x.unwrap().right.as_ref();
                        break;
                    },
                    Ordering::Equal  => {
                        dim = (dim + 1) % dimension;
                        if dim == current_dim {
                            return Some(&x.unwrap().val)
                        }
                    }
                }
            }
        }
        None
    }

    fn put(&mut self, key: K, val: V) {
        self.root = put(self.root.take(), key, val, 0);
    }

    fn delete(&mut self, key: &K) {
        self.root = delete(self.root.take(), key);
    }

    fn is_empty(&self) -> bool {
        self.root.is_none()
    }

    /// number of key-value pairs in the table
    fn size(&self) -> usize {
        if self.is_empty() {
            0
        } else {
            self.root.as_ref().unwrap().size()
        }
    }
}

impl<K: Point, V> KdTree<K, V> {
    pub fn keys<'a>(&'a self) -> ::std::vec::IntoIter<&'a K> {
        let mut queue: Vec<&'a K> = Vec::new();
        fn inorder<'a, K: Point, V>(x: Option<&'a Box<Node<K,V>>>, queue: &mut Vec<&'a K>) {
            if x.is_none() {
                return;
            }
            inorder(x.unwrap().left.as_ref(), queue);
            queue.push(&x.unwrap().key);
            inorder(x.unwrap().right.as_ref(), queue);
        };
        inorder(self.root.as_ref(), &mut queue);
        queue.into_iter()
    }
}

impl KdTree<Point2D, ()> {
    // add the point to the KdTree
    pub fn insert(&mut self, p: Point2D) {
        self.put(p, ());
    }

    /// find all Point2D keys that lie in a 2d range
    pub fn range_search<T: AsRef<RectHV>>(&self, rect: T) -> IntoIter<&Point2D> {
        let mut result = Vec::new();

        // use stack approach
        let mut stack = Vec::new();
        stack.push(self.root.as_ref());
        while !stack.is_empty() {
            let x = stack.pop().unwrap();

            if x.is_none() {
                continue;
            }

            let dim = x.as_ref().unwrap().depth % 2;

            // Check if point in node lies in given rectangle
            if rect.as_ref().contains(x.as_ref().unwrap().key) {
                result.push(&x.as_ref().unwrap().key)
            }
            // Recursively search left/bottom (if any could fall in rectangle)
            // Recursively search right/top (if any could fall in rectangle)
            if dim == 0 {
                if rect.as_ref().xmin < x.as_ref().unwrap().comparator_for_current_dim() {
                    stack.push(x.unwrap().left.as_ref())
                }
                if rect.as_ref().xmax > x.as_ref().unwrap().comparator_for_current_dim() {
                    stack.push(x.unwrap().right.as_ref())
                }
            } else {        // dim == 1: y
                if rect.as_ref().ymin < x.as_ref().unwrap().comparator_for_current_dim() {
                    stack.push(x.unwrap().left.as_ref())
                }
                if rect.as_ref().ymax > x.as_ref().unwrap().comparator_for_current_dim() {
                    stack.push(x.unwrap().right.as_ref())
                }
            }
        }
        result.into_iter()
    }

    /// number of keys that lie in a 2d range
    pub fn range_count<T: AsRef<RectHV>>(&self, rect: T) -> usize {
        self.range_search(rect).count()
    }

    pub fn nearest<T: AsRef<Point2D>>(&self, p: T) -> Option<&Point2D> {
        let mut result = None;
        let mut min_distance_squared = f64::MAX;
        let p = p.as_ref();

        let mut queue = ResizingArrayQueue::new();
        queue.enqueue(self.root.as_ref());
        while !queue.is_empty() {
            let x = queue.dequeue().unwrap();

            if x.is_none() {
                continue;
            }

            let dim = x.as_ref().unwrap().depth % 2;

            // Check distance from point in node to query point
            let dist = x.as_ref().unwrap().key.distance_squared_to(p);
            if dist < min_distance_squared {
                result = Some(&x.as_ref().unwrap().key);
                min_distance_squared = dist;
            }

            // Recursively search left/bottom (if it could contain a closer point)
            // Recursively search right/top (if it could contain a closer point)
            // TODO: pruning
            if dim == 0 {
                if p.x < x.as_ref().unwrap().comparator_for_current_dim() {
                    queue.enqueue(x.unwrap().left.as_ref());
                    queue.enqueue(x.unwrap().right.as_ref());
                } else {
                    queue.enqueue(x.unwrap().right.as_ref());
                    queue.enqueue(x.unwrap().left.as_ref());
                }
            } else {        // dim == 1: y
                if p.y < x.as_ref().unwrap().comparator_for_current_dim() {
                    queue.enqueue(x.unwrap().left.as_ref());
                    queue.enqueue(x.unwrap().right.as_ref());
                } else {
                    queue.enqueue(x.unwrap().right.as_ref());
                    queue.enqueue(x.unwrap().left.as_ref());
                }
            }
        }
        result

    }
}

impl<K: Point + fmt::Debug, V: fmt::Debug> fmt::Debug for KdTree<K, V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.root.is_none() {
            write!(f, "<empty tree>")
        } else {
            self.root.as_ref().unwrap().dump(0, f, ' ');
            Ok(())
        }
    }
}

#[test]
fn test_kd_tree_with_point_2d() {
    let mut t = KdTree::<Point2D, ()>::new();

    t.put(Point2D::new(0.7, 0.2), ());
    t.put(Point2D::new(0.5, 0.4), ());
    t.put(Point2D::new(0.2, 0.3), ());
    t.put(Point2D::new(0.4, 0.7), ());
    t.put(Point2D::new(0.9, 0.6), ());

    println!("got => {:?}", t);

    assert_eq!(5, t.range_search(RectHV::new(0.1, 0.1, 0.9, 0.9)).count());
    assert_eq!(1, t.range_search(RectHV::new(0.1, 0.1, 0.4, 0.4)).count());

    assert_eq!(&Point2D::new(0.2, 0.3), t.nearest(Point2D::new(0.1, 0.1)).unwrap());
}

#[test]
fn test_kd_tree_with_point_2d_duplicated() {
    let mut t = KdTree::<Point2D, ()>::new();

    t.put(Point2D::new(0.7, 0.2), ());
    t.put(Point2D::new(0.5, 0.4), ());
    t.put(Point2D::new(0.2, 0.3), ());
    t.put(Point2D::new(0.2, 0.7), ());
    t.put(Point2D::new(0.4, 0.7), ());
    t.put(Point2D::new(0.4, 0.2), ());
    t.put(Point2D::new(0.9, 0.6), ());
    t.put(Point2D::new(0.7, 0.4), ());

    println!("got => {:?}", t);

    assert_eq!(8, t.size());
    assert!(t.contains(&Point2D::new(0.7, 0.2)));
    assert!(t.contains(&Point2D::new(0.7, 0.4)));
    assert!(!t.contains(&Point2D::new(0.7, 0.3)));
    assert_eq!(8, t.range_search(RectHV::new(0.1, 0.1, 0.9, 0.9)).count());
    assert_eq!(2, t.range_search(RectHV::new(0.1, 0.1, 0.4, 0.4)).count());
}
<|endoftext|>


<commit_before>//! Checks for usage of  `&Vec[_]` and `&String`.

use crate::utils::ptr::get_spans;
use crate::utils::{
    is_allowed, is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg,
    span_lint_and_then, walk_ptrs_hir_ty,
};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{
    BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind,
    Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::MultiSpan;
use std::borrow::Cow;

declare_clippy_lint! {
    /// **What it does:** This lint checks for function arguments of type `&String`
    /// or `&Vec` unless the references are mutable. It will also suggest you
    /// replace `.clone()` calls with the appropriate `.to_owned()`/`to_string()`
    /// calls.
    ///
    /// **Why is this bad?** Requiring the argument to be of the specific size
    /// makes the function less useful for no benefit; slices in the form of `&[T]`
    /// or `&str` usually suffice and can be obtained from other types, too.
    ///
    /// **Known problems:** The lint does not follow data. So if you have an
    /// argument `x` and write `let y = x; y.clone()` the lint will not suggest
    /// changing that `.clone()` to `.to_owned()`.
    ///
    /// Other functions called from this function taking a `&String` or `&Vec`
    /// argument may also fail to compile if you change the argument. Applying
    /// this lint on them will fix the problem, but they may be in other crates.
    ///
    /// One notable example of a function that may cause issues, and which cannot
    /// easily be changed due to beinng in the standard library is `Vec::contains`.
    /// when called on a `Vec<Vec<T>>`. If a `&Vec` is passed to that method then
    /// it will compile, but if a `&[T]` is passed then it will not compile.
    ///
    /// ```ignore
    /// fn cannot_take_a_slice(v: &Vec<u8>) -> bool {
    ///     let vec_of_vecs: Vec<Vec<u8>> = some_other_fn();
    ///
    ///     vec_of_vecs.contains(v)
    /// }
    /// ```
    ///
    /// Also there may be `fn(&Vec)`-typed references pointing to your function.
    /// If you have them, you will get a compiler error after applying this lint's
    /// suggestions. You then have the choice to undo your changes or change the
    /// type of the reference.
    ///
    /// Note that if the function is part of your public interface, there may be
    /// other crates referencing it, of which you may not be aware. Carefully
    /// deprecate the function before applying the lint suggestions in this case.
    ///
    /// **Example:**
    /// ```ignore
    /// // Bad
    /// fn foo(&Vec<u32>) { .. }
    ///
    /// // Good
    /// fn foo(&[u32]) { .. }
    /// ```
    pub PTR_ARG,
    style,
    "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively"
}

declare_clippy_lint! {
    /// **What it does:** This lint checks for equality comparisons with `ptr::null`
    ///
    /// **Why is this bad?** It's easier and more readable to use the inherent
    /// `.is_null()`
    /// method instead
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// // Bad
    /// if x == ptr::null {
    ///     ..
    /// }
    ///
    /// // Good
    /// if x.is_null() {
    ///     ..
    /// }
    /// ```
    pub CMP_NULL,
    style,
    "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead."
}

declare_clippy_lint! {
    /// **What it does:** This lint checks for functions that take immutable
    /// references and return mutable ones.
    ///
    /// **Why is this bad?** This is trivially unsound, as one can create two
    /// mutable references from the same (immutable!) source.
    /// This [error](https://github.com/rust-lang/rust/issues/39465)
    /// actually lead to an interim Rust release 1.15.1.
    ///
    /// **Known problems:** To be on the conservative side, if there's at least one
    /// mutable reference with the output lifetime, this lint will not trigger.
    /// In practice, this case is unlikely anyway.
    ///
    /// **Example:**
    /// ```ignore
    /// fn foo(&Foo) -> &mut Bar { .. }
    /// ```
    pub MUT_FROM_REF,
    correctness,
    "fns that create mutable refs from immutable ref args"
}

declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF]);

impl<'tcx> LateLintPass<'tcx> for Ptr {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
        if let ItemKind::Fn(ref sig, _, body_id) = item.kind {
            check_fn(cx, &sig.decl, item.hir_id, Some(body_id));
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
        if let ImplItemKind::Fn(ref sig, body_id) = item.kind {
            let parent_item = cx.tcx.hir().get_parent_item(item.hir_id);
            if let Some(Node::Item(it)) = cx.tcx.hir().find(parent_item) {
                if let ItemKind::Impl { of_trait: Some(_), .. } = it.kind {
                    return; // ignore trait impls
                }
            }
            check_fn(cx, &sig.decl, item.hir_id, Some(body_id));
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
        if let TraitItemKind::Fn(ref sig, ref trait_method) = item.kind {
            let body_id = if let TraitFn::Provided(b) = *trait_method {
                Some(b)
            } else {
                None
            };
            check_fn(cx, &sig.decl, item.hir_id, body_id);
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if let ExprKind::Binary(ref op, ref l, ref r) = expr.kind {
            if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(l) || is_null_path(r)) {
                span_lint(
                    cx,
                    CMP_NULL,
                    expr.span,
                    "Comparing with null is better expressed by the `.is_null()` method",
                );
            }
        }
    }
}

#[allow(clippy::too_many_lines)]
fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option<BodyId>) {
    let fn_def_id = cx.tcx.hir().local_def_id(fn_id);
    let sig = cx.tcx.fn_sig(fn_def_id);
    let fn_ty = sig.skip_binder();
    let body = opt_body_id.map(|id| cx.tcx.hir().body(id));

    for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
        // Honor the allow attribute on parameters. See issue 5644.
        if let Some(body) = &body {
            if is_allowed(cx, PTR_ARG, body.params[idx].hir_id) {
                continue;
            }
        }

        if let ty::Ref(_, ty, Mutability::Not) = ty.kind {
            if is_type_diagnostic_item(cx, ty, sym!(vec_type)) {
                let mut ty_snippet = None;
                if_chain! {
                    if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;
                    if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
                    then {
                        let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
                            GenericArg::Type(ty) => Some(ty),
                            _ => None,
                        }).collect();
                        if types.len() == 1 {
                            ty_snippet = snippet_opt(cx, types[0].span);
                        }
                    }
                };
                if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
                    span_lint_and_then(
                        cx,
                        PTR_ARG,
                        arg.span,
                        "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \
                         with non-Vec-based slices.",
                        |diag| {
                            if let Some(ref snippet) = ty_snippet {
                                diag.span_suggestion(
                                    arg.span,
                                    "change this to",
                                    format!("&[{}]", snippet),
                                    Applicability::Unspecified,
                                );
                            }
                            for (clonespan, suggestion) in spans {
                                diag.span_suggestion(
                                    clonespan,
                                    &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
                                        Cow::Owned(format!("change `{}` to", x))
                                    }),
                                    suggestion.into(),
                                    Applicability::Unspecified,
                                );
                            }
                        },
                    );
                }
            } else if is_type_diagnostic_item(cx, ty, sym!(string_type)) {
                if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) {
                    span_lint_and_then(
                        cx,
                        PTR_ARG,
                        arg.span,
                        "writing `&String` instead of `&str` involves a new object where a slice will do.",
                        |diag| {
                            diag.span_suggestion(arg.span, "change this to", "&str".into(), Applicability::Unspecified);
                            for (clonespan, suggestion) in spans {
                                diag.span_suggestion_short(
                                    clonespan,
                                    &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
                                        Cow::Owned(format!("change `{}` to", x))
                                    }),
                                    suggestion.into(),
                                    Applicability::Unspecified,
                                );
                            }
                        },
                    );
                }
            } else if match_type(cx, ty, &paths::COW) {
                if_chain! {
                    if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.kind;
                    if let TyKind::Path(ref path) = ty.kind;
                    if let QPath::Resolved(None, ref pp) = *path;
                    if let [ref bx] = *pp.segments;
                    if let Some(ref params) = bx.args;
                    if !params.parenthesized;
                    if let Some(inner) = params.args.iter().find_map(|arg| match arg {
                        GenericArg::Type(ty) => Some(ty),
                        _ => None,
                    });
                    then {
                        let replacement = snippet_opt(cx, inner.span);
                        if let Some(r) = replacement {
                            span_lint_and_sugg(
                                cx,
                                PTR_ARG,
                                arg.span,
                                "using a reference to `Cow` is not recommended.",
                                "change this to",
                                "&".to_owned() + &r,
                                Applicability::Unspecified,
                            );
                        }
                    }
                }
            }
        }
    }

    if let FnRetTy::Return(ref ty) = decl.output {
        if let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty) {
            let mut immutables = vec![];
            for (_, ref mutbl, ref argspan) in decl
                .inputs
                .iter()
                .filter_map(|ty| get_rptr_lm(ty))
                .filter(|&(lt, _, _)| lt.name == out.name)
            {
                if *mutbl == Mutability::Mut {
                    return;
                }
                immutables.push(*argspan);
            }
            if immutables.is_empty() {
                return;
            }
            span_lint_and_then(
                cx,
                MUT_FROM_REF,
                ty.span,
                "mutable borrow from immutable input(s)",
                |diag| {
                    let ms = MultiSpan::from_spans(immutables);
                    diag.span_note(ms, "immutable borrow here");
                },
            );
        }
    }
}

fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
    if let TyKind::Rptr(ref lt, ref m) = ty.kind {
        Some((lt, m.mutbl, ty.span))
    } else {
        None
    }
}

fn is_null_path(expr: &Expr<'_>) -> bool {
    if let ExprKind::Call(ref pathexp, ref args) = expr.kind {
        if args.is_empty() {
            if let ExprKind::Path(ref path) = pathexp.kind {
                return match_qpath(path, &paths::PTR_NULL) || match_qpath(path, &paths::PTR_NULL_MUT);
            }
        }
    }
    false
}
<commit_msg>fix typo pointed out in review comment<commit_after>//! Checks for usage of  `&Vec[_]` and `&String`.

use crate::utils::ptr::get_spans;
use crate::utils::{
    is_allowed, is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg,
    span_lint_and_then, walk_ptrs_hir_ty,
};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{
    BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind,
    Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::MultiSpan;
use std::borrow::Cow;

declare_clippy_lint! {
    /// **What it does:** This lint checks for function arguments of type `&String`
    /// or `&Vec` unless the references are mutable. It will also suggest you
    /// replace `.clone()` calls with the appropriate `.to_owned()`/`to_string()`
    /// calls.
    ///
    /// **Why is this bad?** Requiring the argument to be of the specific size
    /// makes the function less useful for no benefit; slices in the form of `&[T]`
    /// or `&str` usually suffice and can be obtained from other types, too.
    ///
    /// **Known problems:** The lint does not follow data. So if you have an
    /// argument `x` and write `let y = x; y.clone()` the lint will not suggest
    /// changing that `.clone()` to `.to_owned()`.
    ///
    /// Other functions called from this function taking a `&String` or `&Vec`
    /// argument may also fail to compile if you change the argument. Applying
    /// this lint on them will fix the problem, but they may be in other crates.
    ///
    /// One notable example of a function that may cause issues, and which cannot
    /// easily be changed due to being in the standard library is `Vec::contains`.
    /// when called on a `Vec<Vec<T>>`. If a `&Vec` is passed to that method then
    /// it will compile, but if a `&[T]` is passed then it will not compile.
    ///
    /// ```ignore
    /// fn cannot_take_a_slice(v: &Vec<u8>) -> bool {
    ///     let vec_of_vecs: Vec<Vec<u8>> = some_other_fn();
    ///
    ///     vec_of_vecs.contains(v)
    /// }
    /// ```
    ///
    /// Also there may be `fn(&Vec)`-typed references pointing to your function.
    /// If you have them, you will get a compiler error after applying this lint's
    /// suggestions. You then have the choice to undo your changes or change the
    /// type of the reference.
    ///
    /// Note that if the function is part of your public interface, there may be
    /// other crates referencing it, of which you may not be aware. Carefully
    /// deprecate the function before applying the lint suggestions in this case.
    ///
    /// **Example:**
    /// ```ignore
    /// // Bad
    /// fn foo(&Vec<u32>) { .. }
    ///
    /// // Good
    /// fn foo(&[u32]) { .. }
    /// ```
    pub PTR_ARG,
    style,
    "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` instead, respectively"
}

declare_clippy_lint! {
    /// **What it does:** This lint checks for equality comparisons with `ptr::null`
    ///
    /// **Why is this bad?** It's easier and more readable to use the inherent
    /// `.is_null()`
    /// method instead
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```ignore
    /// // Bad
    /// if x == ptr::null {
    ///     ..
    /// }
    ///
    /// // Good
    /// if x.is_null() {
    ///     ..
    /// }
    /// ```
    pub CMP_NULL,
    style,
    "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead."
}

declare_clippy_lint! {
    /// **What it does:** This lint checks for functions that take immutable
    /// references and return mutable ones.
    ///
    /// **Why is this bad?** This is trivially unsound, as one can create two
    /// mutable references from the same (immutable!) source.
    /// This [error](https://github.com/rust-lang/rust/issues/39465)
    /// actually lead to an interim Rust release 1.15.1.
    ///
    /// **Known problems:** To be on the conservative side, if there's at least one
    /// mutable reference with the output lifetime, this lint will not trigger.
    /// In practice, this case is unlikely anyway.
    ///
    /// **Example:**
    /// ```ignore
    /// fn foo(&Foo) -> &mut Bar { .. }
    /// ```
    pub MUT_FROM_REF,
    correctness,
    "fns that create mutable refs from immutable ref args"
}

declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF]);

impl<'tcx> LateLintPass<'tcx> for Ptr {
    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
        if let ItemKind::Fn(ref sig, _, body_id) = item.kind {
            check_fn(cx, &sig.decl, item.hir_id, Some(body_id));
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
        if let ImplItemKind::Fn(ref sig, body_id) = item.kind {
            let parent_item = cx.tcx.hir().get_parent_item(item.hir_id);
            if let Some(Node::Item(it)) = cx.tcx.hir().find(parent_item) {
                if let ItemKind::Impl { of_trait: Some(_), .. } = it.kind {
                    return; // ignore trait impls
                }
            }
            check_fn(cx, &sig.decl, item.hir_id, Some(body_id));
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
        if let TraitItemKind::Fn(ref sig, ref trait_method) = item.kind {
            let body_id = if let TraitFn::Provided(b) = *trait_method {
                Some(b)
            } else {
                None
            };
            check_fn(cx, &sig.decl, item.hir_id, body_id);
        }
    }

    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if let ExprKind::Binary(ref op, ref l, ref r) = expr.kind {
            if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(l) || is_null_path(r)) {
                span_lint(
                    cx,
                    CMP_NULL,
                    expr.span,
                    "Comparing with null is better expressed by the `.is_null()` method",
                );
            }
        }
    }
}

#[allow(clippy::too_many_lines)]
fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option<BodyId>) {
    let fn_def_id = cx.tcx.hir().local_def_id(fn_id);
    let sig = cx.tcx.fn_sig(fn_def_id);
    let fn_ty = sig.skip_binder();
    let body = opt_body_id.map(|id| cx.tcx.hir().body(id));

    for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
        // Honor the allow attribute on parameters. See issue 5644.
        if let Some(body) = &body {
            if is_allowed(cx, PTR_ARG, body.params[idx].hir_id) {
                continue;
            }
        }

        if let ty::Ref(_, ty, Mutability::Not) = ty.kind {
            if is_type_diagnostic_item(cx, ty, sym!(vec_type)) {
                let mut ty_snippet = None;
                if_chain! {
                    if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;
                    if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
                    then {
                        let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
                            GenericArg::Type(ty) => Some(ty),
                            _ => None,
                        }).collect();
                        if types.len() == 1 {
                            ty_snippet = snippet_opt(cx, types[0].span);
                        }
                    }
                };
                if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
                    span_lint_and_then(
                        cx,
                        PTR_ARG,
                        arg.span,
                        "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \
                         with non-Vec-based slices.",
                        |diag| {
                            if let Some(ref snippet) = ty_snippet {
                                diag.span_suggestion(
                                    arg.span,
                                    "change this to",
                                    format!("&[{}]", snippet),
                                    Applicability::Unspecified,
                                );
                            }
                            for (clonespan, suggestion) in spans {
                                diag.span_suggestion(
                                    clonespan,
                                    &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
                                        Cow::Owned(format!("change `{}` to", x))
                                    }),
                                    suggestion.into(),
                                    Applicability::Unspecified,
                                );
                            }
                        },
                    );
                }
            } else if is_type_diagnostic_item(cx, ty, sym!(string_type)) {
                if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) {
                    span_lint_and_then(
                        cx,
                        PTR_ARG,
                        arg.span,
                        "writing `&String` instead of `&str` involves a new object where a slice will do.",
                        |diag| {
                            diag.span_suggestion(arg.span, "change this to", "&str".into(), Applicability::Unspecified);
                            for (clonespan, suggestion) in spans {
                                diag.span_suggestion_short(
                                    clonespan,
                                    &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
                                        Cow::Owned(format!("change `{}` to", x))
                                    }),
                                    suggestion.into(),
                                    Applicability::Unspecified,
                                );
                            }
                        },
                    );
                }
            } else if match_type(cx, ty, &paths::COW) {
                if_chain! {
                    if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.kind;
                    if let TyKind::Path(ref path) = ty.kind;
                    if let QPath::Resolved(None, ref pp) = *path;
                    if let [ref bx] = *pp.segments;
                    if let Some(ref params) = bx.args;
                    if !params.parenthesized;
                    if let Some(inner) = params.args.iter().find_map(|arg| match arg {
                        GenericArg::Type(ty) => Some(ty),
                        _ => None,
                    });
                    then {
                        let replacement = snippet_opt(cx, inner.span);
                        if let Some(r) = replacement {
                            span_lint_and_sugg(
                                cx,
                                PTR_ARG,
                                arg.span,
                                "using a reference to `Cow` is not recommended.",
                                "change this to",
                                "&".to_owned() + &r,
                                Applicability::Unspecified,
                            );
                        }
                    }
                }
            }
        }
    }

    if let FnRetTy::Return(ref ty) = decl.output {
        if let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty) {
            let mut immutables = vec![];
            for (_, ref mutbl, ref argspan) in decl
                .inputs
                .iter()
                .filter_map(|ty| get_rptr_lm(ty))
                .filter(|&(lt, _, _)| lt.name == out.name)
            {
                if *mutbl == Mutability::Mut {
                    return;
                }
                immutables.push(*argspan);
            }
            if immutables.is_empty() {
                return;
            }
            span_lint_and_then(
                cx,
                MUT_FROM_REF,
                ty.span,
                "mutable borrow from immutable input(s)",
                |diag| {
                    let ms = MultiSpan::from_spans(immutables);
                    diag.span_note(ms, "immutable borrow here");
                },
            );
        }
    }
}

fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
    if let TyKind::Rptr(ref lt, ref m) = ty.kind {
        Some((lt, m.mutbl, ty.span))
    } else {
        None
    }
}

fn is_null_path(expr: &Expr<'_>) -> bool {
    if let ExprKind::Call(ref pathexp, ref args) = expr.kind {
        if args.is_empty() {
            if let ExprKind::Path(ref path) = pathexp.kind {
                return match_qpath(path, &paths::PTR_NULL) || match_qpath(path, &paths::PTR_NULL_MUT);
            }
        }
    }
    false
}
<|endoftext|>


<commit_before>macro_rules! cstr {
    ($lit:expr) => {
        {
            use std::ffi::CStr;
            use libc::c_char;
            CStr::from_bytes_with_nul_unchecked(concat!($lit, "\0").as_bytes()).as_ptr() as *const c_char
        }
    }
}

mod context;
mod function;
mod instructions;
mod symboltable;
mod target;
mod types;
mod valueref;

use std::process::{Output, Command};
use llvm::core::*;

use bytecode::{ByteCodeModule};
use self::valueref::ValueRef;
use self::function::{gen_function, gen_function_sig, add_libc_functions};
use self::context::Context;

pub struct CodeGenOptions
{
    pub build_dir: String,
    pub program_name: String,
    pub dump_ir: bool,
    pub optimize: bool,
}

fn llvm_init()
{
    unsafe {
        use llvm::initialization::*;
        use llvm::target::*;
        LLVM_InitializeAllTargetInfos();
        LLVM_InitializeAllTargets();
        LLVM_InitializeAllTargetMCs();
        LLVM_InitializeAllAsmPrinters();
        LLVM_InitializeAllAsmParsers();

        let pass_registry = LLVMGetGlobalPassRegistry();
        LLVMInitializeCore(pass_registry);
        LLVMInitializeTransformUtils(pass_registry);
        LLVMInitializeScalarOpts(pass_registry);
        LLVMInitializeObjCARCOpts(pass_registry);
        LLVMInitializeVectorization(pass_registry);
        LLVMInitializeInstCombine(pass_registry);
        LLVMInitializeIPO(pass_registry);
        LLVMInitializeInstrumentation(pass_registry);
        LLVMInitializeAnalysis(pass_registry);
        LLVMInitializeIPA(pass_registry);
        LLVMInitializeCodeGen(pass_registry);
        LLVMInitializeTarget(pass_registry);
    }
}

pub fn llvm_code_generation(bc_mod: &ByteCodeModule) -> Result<Context, String>
{
    llvm_init();

    let mut ctx = Context::new(&bc_mod.name)?;

    unsafe {
        add_libc_functions(&mut ctx);

        for (glob_name, glob_val) in &bc_mod.globals {
            let v = ValueRef::from_const(&ctx, glob_val);
            ctx.add_variable(glob_name, v);
        }

        for func in bc_mod.functions.values() {
            if func.sig.name == bc_mod.main_function_name() {
                gen_function_sig(&mut ctx, &func.sig, Some("main"));
            } else {
                gen_function_sig(&mut ctx, &func.sig, None);
            }
        }

        for func in bc_mod.functions.values() {
            gen_function(&mut ctx, func);
        }

        ctx.verify()?;
    }

    Ok(ctx)
}

pub fn link(ctx: &Context, opts: &CodeGenOptions) -> Result<(), String>
{
    let obj_file = unsafe{
        ctx.gen_object_file(&opts)?
    };

    let program_path = format!("{}/{}", opts.build_dir, opts.program_name);

    let mut cmd = Command::new("gcc");
    cmd.arg("-o").arg(&program_path).arg(obj_file).arg("-lcobraruntime");

    println!("  Linking {}", program_path);
    let output: Output = cmd
        .output()
        .map_err(|e| format!("Unable to spawn the linker: {}", e))?;

    if !output.status.success() {
        let out = String::from_utf8(output.stderr).expect("Invalid stdout from ld");
        let msg = format!("Linking {} failed:\n{}", program_path, out);
        return Err(msg);
    }

    Ok(())
}
<commit_msg>Do not link to cobraruntime<commit_after>macro_rules! cstr {
    ($lit:expr) => {
        {
            use std::ffi::CStr;
            use libc::c_char;
            CStr::from_bytes_with_nul_unchecked(concat!($lit, "\0").as_bytes()).as_ptr() as *const c_char
        }
    }
}

mod context;
mod function;
mod instructions;
mod symboltable;
mod target;
mod types;
mod valueref;

use std::process::{Output, Command};
use llvm::core::*;

use bytecode::{ByteCodeModule};
use self::valueref::ValueRef;
use self::function::{gen_function, gen_function_sig, add_libc_functions};
use self::context::Context;

pub struct CodeGenOptions
{
    pub build_dir: String,
    pub program_name: String,
    pub dump_ir: bool,
    pub optimize: bool,
}

fn llvm_init()
{
    unsafe {
        use llvm::initialization::*;
        use llvm::target::*;
        LLVM_InitializeAllTargetInfos();
        LLVM_InitializeAllTargets();
        LLVM_InitializeAllTargetMCs();
        LLVM_InitializeAllAsmPrinters();
        LLVM_InitializeAllAsmParsers();

        let pass_registry = LLVMGetGlobalPassRegistry();
        LLVMInitializeCore(pass_registry);
        LLVMInitializeTransformUtils(pass_registry);
        LLVMInitializeScalarOpts(pass_registry);
        LLVMInitializeObjCARCOpts(pass_registry);
        LLVMInitializeVectorization(pass_registry);
        LLVMInitializeInstCombine(pass_registry);
        LLVMInitializeIPO(pass_registry);
        LLVMInitializeInstrumentation(pass_registry);
        LLVMInitializeAnalysis(pass_registry);
        LLVMInitializeIPA(pass_registry);
        LLVMInitializeCodeGen(pass_registry);
        LLVMInitializeTarget(pass_registry);
    }
}

pub fn llvm_code_generation(bc_mod: &ByteCodeModule) -> Result<Context, String>
{
    llvm_init();

    let mut ctx = Context::new(&bc_mod.name)?;

    unsafe {
        add_libc_functions(&mut ctx);

        for (glob_name, glob_val) in &bc_mod.globals {
            let v = ValueRef::from_const(&ctx, glob_val);
            ctx.add_variable(glob_name, v);
        }

        for func in bc_mod.functions.values() {
            if func.sig.name == bc_mod.main_function_name() {
                gen_function_sig(&mut ctx, &func.sig, Some("main"));
            } else {
                gen_function_sig(&mut ctx, &func.sig, None);
            }
        }

        for func in bc_mod.functions.values() {
            gen_function(&mut ctx, func);
        }

        ctx.verify()?;
    }

    Ok(ctx)
}

pub fn link(ctx: &Context, opts: &CodeGenOptions) -> Result<(), String>
{
    let obj_file = unsafe{
        ctx.gen_object_file(&opts)?
    };

    let program_path = format!("{}/{}", opts.build_dir, opts.program_name);

    let mut cmd = Command::new("gcc");
    cmd.arg("-o").arg(&program_path).arg(obj_file);

    println!("  Linking {}", program_path);
    let output: Output = cmd
        .output()
        .map_err(|e| format!("Unable to spawn the linker: {}", e))?;

    if !output.status.success() {
        let out = String::from_utf8(output.stderr).expect("Invalid stdout from ld");
        let msg = format!("Linking {} failed:\n{}", program_path, out);
        return Err(msg);
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::f32;

use signal::Signal;
use render::render_spec::{RenderSpec, RenderSpecFactory};
use render::reference::tree_renderer::TreeRenderer;
use tree::node::{Node, NodeOp};
use tree::send::Send;
use tree::tree::Tree;

use super::approx_equal::assert_similar_audio;

/// Try to render a single 440 Hz sine wave through the reference tree_renderer
fn get_basic_sine(render_spec: RenderSpec, n_samples: u32) -> Vec<f32> {
    let mut tree = TreeRenderer::new(render_spec);
    let exit_node = Node::new_rc(NodeOp::OpAt);
    tree.watch_nodes(&vec![exit_node.clone()]);

    // inject the sine wave directly into the output
    let wave = Signal::new(1.0, 440.0*2.0*f32::consts::PI, 0.0, 0.0, 0.0);
    tree.add_send(
        Send::new_srcsend(
            wave,
            exit_node.clone()
        )
    );

    let mut samples = vec![];
    for _ in 0..n_samples {
        samples.push(tree.step()[0]);
    }
    samples
}

#[test]
pub fn test_basic_sine() {
    let render_spec = RenderSpecFactory::new().sample_rate(44100).finalize();
    let n_samples = 100;
    let actual = get_basic_sine(render_spec, n_samples);
    let mut reference = vec![];
    for i in 0..n_samples {
        let t = (i as f32) / 44100.0;
        reference.push((440.0*2.0*f32::consts::PI * t).cos());
    }

    assert_similar_audio(&reference, &actual);
}

<commit_msg>Adjust 'test_basic_sine' to test amplitude and phase as well<commit_after>use std::f32;

use signal::Signal;
use render::render_spec::{RenderSpec, RenderSpecFactory};
use render::reference::tree_renderer::TreeRenderer;
use tree::node::{Node, NodeOp};
use tree::send::Send;
use tree::tree::Tree;

use super::approx_equal::assert_similar_audio;

/// Try to render a single 440 Hz sine wave through the reference tree_renderer
fn get_basic_sine(render_spec: RenderSpec, n_samples: u32) -> Vec<f32> {
    let mut tree = TreeRenderer::new(render_spec);
    let exit_node = Node::new_rc(NodeOp::OpAt);
    tree.watch_nodes(&vec![exit_node.clone()]);

    // inject the sine wave directly into the output
    let wave = Signal::new(3.0, 440.0*2.0*f32::consts::PI, 0.5*f32::consts::PI, 0.0, 0.0);
    tree.add_send(
        Send::new_srcsend(
            wave,
            exit_node.clone()
        )
    );

    let mut samples = vec![];
    for _ in 0..n_samples {
        samples.push(tree.step()[0]);
    }
    samples
}

#[test]
pub fn test_basic_sine() {
    let render_spec = RenderSpecFactory::new().sample_rate(44100).finalize();
    let n_samples = 100;
    let actual = get_basic_sine(render_spec, n_samples);
    let mut reference = vec![];
    for i in 0..n_samples {
        let t = (i as f32) / 44100.0;
        reference.push(3.0*(440.0*2.0*f32::consts::PI * t).sin());
    }

    assert_similar_audio(&reference, &actual);
}

<|endoftext|>


<commit_before>use glium::{Frame, VertexBuffer, Blend, Surface};
use glium::Display;
use glium::index::{IndexBuffer, PrimitiveType};
use glium::draw_parameters::DrawParameters;
use glium::draw_parameters::LinearBlendingFactor::*;
use glium::draw_parameters::BlendingFunction::*;
use glium::uniforms::{Uniforms, UniformsStorage, AsUniformValue};

use nalgebra::Norm;
use texturegen::GeneratorView;
use texturegen::process::{Process, Setting, BlendType};

use {SimContext, Selection, Node, Vect, input_pos, output_pos};
use super::{RenderContext, Vertex, vert};
use State::*;
use math::*;

pub fn render(display: &Display, rctx: &mut RenderContext, gen: GeneratorView<Node>, ctx: &SimContext) {
    let mut target = display.draw();
    target.clear_color(0.0157, 0.0173, 0.0204, 1.);
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let dims = display.get_framebuffer_dimensions();
    for (_, data) in gen.iter() {
        let pos = flip_y(data.pos);
        let corner_pos = pos - Vect::new(ctx.node_width, ctx.node_width) * 0.5;
        let matrix = rctx.cam * translation(corner_pos.x, corner_pos.y);
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        draw(&mut target, &rctx, "back", "plain", &uniforms, &draw_params);
        let matrix = rctx.cam * translation(corner_pos.x + 0.05, corner_pos.y + 0.05) * scale(0.9, 0.9);
        let program = data.shader.borrow();
        let program = program.as_ref().expect("Node didn't have shader.");
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        let model = rctx.models.get("node").unwrap();
        target.draw(&model.vertices, &model.indices, &program, &uniforms, &draw_params).expect("Drawing node failed.");

        let mut draw = |things: &[_]| {
            for p in things {
                let p = pos + flip_y(*p) - Vect::new(ctx.thingy_size, ctx.thingy_size) * 0.5;
                let matrix = rctx.cam * translation(p.x, p.y) * scale(ctx.thingy_size, ctx.thingy_size);
                let uniforms = uniform! {
                    matrix: *matrix.as_ref(),
                };
                draw(&mut target, &rctx, "node", "plain", &uniforms, &draw_params);
            }
        };
        draw(&data.outputs.borrow());
        draw(&data.inputs.borrow());
    }
    let mut lines = Vec::with_capacity(gen.connections());
    if let Some(AddingEdge) = ctx.state {
        if let Some(Selection::Output(trg)) = ctx.selected {
            let src = output_pos(&gen, trg, ctx.thingy_size);
            let trg = Vect::new(ctx.mouse_pos.x, -ctx.mouse_pos.y);
            add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
        }
    }
    for (src, trg) in gen.iter_connections() {
        let src = output_pos(&gen, src, ctx.thingy_size);
        let trg = input_pos(&gen, trg, ctx.thingy_size);
        let trg = Vect::new(trg[0], trg[1] + ctx.thingy_size);
        add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
    }
    let vertices = VertexBuffer::new(display, &lines).unwrap();
    let indices = (0..lines.len() as u32).collect::<Vec<_>>();
    let indices = IndexBuffer::new(display, PrimitiveType::LinesList, &indices).unwrap();
    let matrix = rctx.cam * translation(0., 0.);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
    };
    let program = rctx.programs.get("plain").unwrap();
    target.draw(&vertices, &indices, program, &uniforms, &draw_params).unwrap();

    if let Some(s) = ctx.selected {
        if let Some(node) = s.node() {
            let set = if let Selection::Setting(_, s) = s {
                Some(s)
            } else {
                None
            };
            let node = gen.get(node).expect("Selection should always point to real node.").0;
            let settings = node.settings();
            let size = 23.;
            for (i, setting) in settings.iter().enumerate() {
                if set == Some(i) {
                    continue;
                }
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = setting.to_string();
                string.push_str(": ");
                string.push_str(&node.setting(setting).to_string());
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
            if let Some(i) = set {
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = settings[i].to_string();
                string.push_str(": ");
                match node.setting(settings[i]) {
                    Setting::Blend(ref b) => {
                        let bb = rctx.fonts.bounding_box("anka", size, &string).unwrap();
                        string.push_str(&format!("{:?}", b));
                        let max = from_window_to_screen(dims, [bb.max.x, bb.max.y]);
                        let pos = pos + Vect::new(max.x * 1.5, -1. / 20.);
                        for (i, blend) in BlendType::iter_variants().enumerate() {
                            let blend = format!("{:?}", blend);
                            let pos = pos + Vect::new(0., -(i as f32 / 20.));
                            rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &blend);
                        }
                    },
                    _ => {
                        if let Some(Writing) = ctx.state {
                            let ch = if 0 % 120 < 60 { //TODO: Fix Me
                                '|'
                            } else {
                                ' '
                            };
                            if ctx.text.is_empty() {
                                string.push(ch);
                            } else {
                                let (a, b) = ctx.text.split_at(ctx.caret);
                                string.push_str(&format!("{}{}{}", a, ch, b));
                            }
                        }
                    }
                }
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
        }
    }
    target.finish().unwrap();
}

fn draw<A, B>(target: &mut Frame, rctx: &RenderContext, model: &str, program: &str, uniforms: &UniformsStorage<A, B>, draw_params: &DrawParameters)
    where A: AsUniformValue,
          B: Uniforms,
{
    let model = rctx.models.get(model).unwrap();
    let program = rctx.programs.get(program).unwrap();
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params).unwrap();
}

fn add_arrow(lines: &mut Vec<Vertex>, src: Vect, trg: Vect, len: f32, theta: f32) {
    lines.push(vert(src.x, src.y));
    lines.push(vert(trg.x, trg.y));
    let vec = (src - trg).normalize();
    let mut add_part = |theta: f32| {
        let (sin, cos) = theta.sin_cos();
        let arrow = Vect::new(
            vec.x * cos - vec.y * sin,
            vec.x * sin + vec.y * cos);
        lines.push(vert(trg.x, trg.y));
        let v = trg + (arrow * len);
        lines.push(vert(v.x, v.y));
    };
    add_part(theta);
    add_part(-theta);
}
<commit_msg>hyödyllistä<commit_after>use glium::{Frame, VertexBuffer, Blend, Surface};
use glium::Display;
use glium::index::{IndexBuffer, PrimitiveType};
use glium::draw_parameters::DrawParameters;
use glium::draw_parameters::LinearBlendingFactor::*;
use glium::draw_parameters::BlendingFunction::*;
use glium::uniforms::{Uniforms, UniformsStorage, AsUniformValue};

use nalgebra::Norm;
use texturegen::GeneratorView;
use texturegen::process::{Process, Setting, BlendType};

use {SimContext, Selection, Node, Vect, input_pos, output_pos};
use super::{RenderContext, Vertex, vert};
use State::*;
use math::*;

pub fn render(display: &Display, rctx: &mut RenderContext, gen: GeneratorView<Node>, ctx: &SimContext) {
    let mut target = display.draw();
    target.clear_color(0.0157, 0.0173, 0.0204, 1.);
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let dims = display.get_framebuffer_dimensions();
        draw(&mut target, &rctx, "back", "plain", &uniforms, &draw_params);
        let matrix = rctx.cam * translation(corner_pos.x + 0.05, corner_pos.y + 0.05) * scale(0.9, 0.9);
        let program = data.shader.borrow();
        let program = program.as_ref().expect("Node didn't have shader.");
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        let model = rctx.models.get("node").unwrap();
        target.draw(&model.vertices, &model.indices, &program, &uniforms, &draw_params).expect("Drawing node failed.");

        let mut draw = |things: &[_]| {
            for p in things {
                let p = pos + flip_y(*p) - Vect::new(ctx.thingy_size, ctx.thingy_size) * 0.5;
                let matrix = rctx.cam * translation(p.x, p.y) * scale(ctx.thingy_size, ctx.thingy_size);
                let uniforms = uniform! {
                    matrix: *matrix.as_ref(),
                };
                draw(&mut target, &rctx, "node", "plain", &uniforms, &draw_params);
            }
        };
        draw(&data.outputs.borrow());
        draw(&data.inputs.borrow());
    }
    let mut lines = Vec::with_capacity(gen.connections());
    if let Some(AddingEdge) = ctx.state {
        if let Some(Selection::Output(trg)) = ctx.selected {
            let src = output_pos(&gen, trg, ctx.thingy_size);
            let trg = Vect::new(ctx.mouse_pos.x, -ctx.mouse_pos.y);
            add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
        }
    }
    for (src, trg) in gen.iter_connections() {
        let src = output_pos(&gen, src, ctx.thingy_size);
        let trg = input_pos(&gen, trg, ctx.thingy_size);
        let trg = Vect::new(trg[0], trg[1] + ctx.thingy_size);
        add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
    }
    let vertices = VertexBuffer::new(display, &lines).unwrap();
    let indices = (0..lines.len() as u32).collect::<Vec<_>>();
    let indices = IndexBuffer::new(display, PrimitiveType::LinesList, &indices).unwrap();
    let matrix = rctx.cam * translation(0., 0.);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
    };
    let program = rctx.programs.get("plain").unwrap();
    target.draw(&vertices, &indices, program, &uniforms, &draw_params).unwrap();

    if let Some(s) = ctx.selected {
        if let Some(node) = s.node() {
            let set = if let Selection::Setting(_, s) = s {
                Some(s)
            } else {
                None
            };
            let node = gen.get(node).expect("Selection should always point to real node.").0;
            let settings = node.settings();
            let size = 23.;
            for (i, setting) in settings.iter().enumerate() {
                if set == Some(i) {
                    continue;
                }
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = setting.to_string();
                string.push_str(": ");
                string.push_str(&node.setting(setting).to_string());
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
            if let Some(i) = set {
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = settings[i].to_string();
                string.push_str(": ");
                match node.setting(settings[i]) {
                    Setting::Blend(ref b) => {
                        let bb = rctx.fonts.bounding_box("anka", size, &string).unwrap();
                        string.push_str(&format!("{:?}", b));
                        let max = from_window_to_screen(dims, [bb.max.x, bb.max.y]);
                        let pos = pos + Vect::new(max.x * 1.5, -1. / 20.);
                        for (i, blend) in BlendType::iter_variants().enumerate() {
                            let blend = format!("{:?}", blend);
                            let pos = pos + Vect::new(0., -(i as f32 / 20.));
                            rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &blend);
                        }
                    },
                    _ => {
                        if let Some(Writing) = ctx.state {
                            let ch = if 0 % 120 < 60 { //TODO: Fix Me
                                '|'
                            } else {
                                ' '
                            };
                            if ctx.text.is_empty() {
                                string.push(ch);
                            } else {
                                let (a, b) = ctx.text.split_at(ctx.caret);
                                string.push_str(&format!("{}{}{}", a, ch, b));
                            }
                        }
                    }
                }
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
        }
    }
    target.finish().unwrap();
}

fn draw<A, B>(target: &mut Frame, rctx: &RenderContext, model: &str, program: &str, uniforms: &UniformsStorage<A, B>, draw_params: &DrawParameters)
    where A: AsUniformValue,
          B: Uniforms,
{
    let model = rctx.models.get(model).unwrap();
    let program = rctx.programs.get(program).unwrap();
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params).unwrap();
}

fn add_arrow(lines: &mut Vec<Vertex>, src: Vect, trg: Vect, len: f32, theta: f32) {
    lines.push(vert(src.x, src.y));
    lines.push(vert(trg.x, trg.y));
    let vec = (src - trg).normalize();
    let mut add_part = |theta: f32| {
        let (sin, cos) = theta.sin_cos();
        let arrow = Vect::new(
            vec.x * cos - vec.y * sin,
            vec.x * sin + vec.y * cos);
        lines.push(vert(trg.x, trg.y));
        let v = trg + (arrow * len);
        lines.push(vert(v.x, v.y));
    };
    add_part(theta);
    add_part(-theta);
}
<|endoftext|>