<commit_before>extern crate polydraw;

use polydraw::Application;
use polydraw::devel::{Scene, Poly, DevelRenderer};
use polydraw::geom::point::Point;
use polydraw::draw::RGB;

fn letter_poly() -> Poly {
   let a_outer = [
      (409, 596),
      (529, 232),
      (566, 222),
      (603, 214),
      (640, 208),
      (658, 207),
      (675, 206),
      (710, 208),
      (743, 213),
      (775, 220),
      (806, 231),
      (835, 245),
      (862, 262),
      (887, 282),
      (910, 304),
      (931, 330),
      (950, 358),
      (966, 389),
      (980, 423),
      (991, 460),
      (999, 499),
      (1003, 541),
      (1005, 585),
      (1005, 791),
      (836, 791),
      (791, 792),
      (747, 794),
      (703, 797),
      (660, 801),
      (619, 807),
      (578, 813),
      (538, 821),
      (500, 830),
      (463, 840),
      (426, 852),
      (391, 864),
      (357, 877),
      (325, 892),
      (294, 907),
      (264, 923),
      (235, 941),
      (208, 959),
      (183, 978),
      (159, 999),
      (136, 1020),
      (115, 1042),
      (96, 1064),
      (78, 1088),
      (62, 1112),
      (48, 1138),
      (35, 1164),
      (25, 1190),
      (16, 1218),
      (9, 1246),
      (4, 1275),
      (1, 1305),
      (0, 1335),
      (1, 1361),
      (2, 1387),
      (5, 1412),
      (9, 1436),
      (15, 1459),
      (21, 1481),
      (28, 1502),
      (36, 1523),
      (45, 1543),
      (56, 1562),
      (67, 1580),
      (79, 1598),
      (92, 1614),
      (105, 1630),
      (120, 1645),
      (135, 1659),
      (151, 1673),
      (168, 1685),
      (185, 1697),
      (203, 1708),
      (222, 1717),
      (241, 1727),
      (261, 1735),
      (282, 1742),
      (303, 1749),
      (324, 1754),
      (346, 1759),
      (368, 1763),
      (391, 1766),
      (414, 1768),
      (461, 1770),
      (507, 1768),
      (551, 1764),
      (594, 1756),
      (637, 1746),
      (677, 1734),
      (717, 1720),
      (755, 1704),
      (792, 1686),
      (827, 1667),
      (860, 1648),
      (891, 1628),
      (920, 1607),
      (946, 1586),
      (971, 1566),
      (993, 1546),
      (1012, 1526),
      (1084, 1740),
      (1691, 1740),
      (1691, 1579),
      (1455, 1470),
      (1455, 540),
      (1454, 506),
      (1452, 473),
      (1448, 441),
      (1443, 410),
      (1437, 381),
      (1429, 352),
      (1420, 325),
      (1409, 299),
      (1397, 274),
      (1384, 250),
      (1370, 228),
      (1354, 206),
      (1337, 186),
      (1319, 166),
      (1300, 148),
      (1280, 131),
      (1258, 115),
      (1236, 100),
      (1212, 86),
      (1187, 73),
      (1162, 61),
      (1135, 50),
      (1107, 41),
      (1078, 32),
      (1049, 25),
      (1018, 18),
      (987, 12),
      (955, 8),
      (922, 4),
      (888, 2),
      (853, 0),
      (818, 0),
      (774, 1),
      (728, 3),
      (682, 7),
      (634, 12),
      (586, 18),
      (537, 25),
      (489, 34),
      (441, 43),
      (393, 53),
      (347, 64),
      (302, 76),
      (259, 89),
      (217, 101),
      (178, 115),
      (142, 129),
      (109, 142),
      (109, 596),
   ];

   let a_inner = [
      (1001, 1418),
      (952, 1435),
      (926, 1443),
      (899, 1450),
      (870, 1457),
      (840, 1462),
      (809, 1465),
      (776, 1466),
      (746, 1465),
      (716, 1463),
      (688, 1458),
      (660, 1452),
      (634, 1444),
      (610, 1434),
      (587, 1423),
      (566, 1409),
      (547, 1394),
      (530, 1377),
      (515, 1357),
      (503, 1337),
      (493, 1314),
      (486, 1289),
      (482, 1262),
      (480, 1234),
      (480, 1218),
      (482, 1202),
      (484, 1187),
      (487, 1173),
      (491, 1159),
      (496, 1146),
      (501, 1134),
      (507, 1122),
      (514, 1111),
      (522, 1101),
      (530, 1091),
      (540, 1082),
      (560, 1064),
      (583, 1050),
      (608, 1037),
      (635, 1026),
      (665, 1017),
      (697, 1010),
      (730, 1004),
      (765, 1000),
      (802, 998),
      (840, 998),
      (1005, 998),
   ];

   let outer = points_from_coords(&a_outer);

   let inner = points_from_coords(&a_inner);

   let poly = Poly::new_with_holes(
      outer,
      vec![
         inner,
      ],
      RGB::new(255, 255, 255),
   );

   poly
}

fn points_from_coords(coords: &[(i64, i64)]) -> Vec<Point> {
   let mut points = Vec::new();

   for &(x, y) in coords.iter() {
      points.push(Point::new(x + 120, y + 120))
   }

   points
}

fn main() {
   let mut scene = Scene::new();

   scene.push(letter_poly());

   let mut renderer = DevelRenderer::new(scene);

   Application::new()
      .renderer(&mut renderer)
      .title("Letter")
      .size(1200, 800)
      .run();
}
<commit_msg>Make the letter example suitable for wider range<commit_after>extern crate polydraw;

use polydraw::Application;
use polydraw::devel::{Scene, Poly, DevelRenderer};
use polydraw::geom::point::Point;
use polydraw::draw::RGB;

fn letter_poly() -> Poly {
   let data = [vec![
      (409, 596),
      (529, 232),
      (566, 222),
      (603, 214),
      (640, 208),
      (658, 207),
      (675, 206),
      (710, 208),
      (743, 213),
      (775, 220),
      (806, 231),
      (835, 245),
      (862, 262),
      (887, 282),
      (910, 304),
      (931, 330),
      (950, 358),
      (966, 389),
      (980, 423),
      (991, 460),
      (999, 499),
      (1003, 541),
      (1005, 585),
      (1005, 791),
      (836, 791),
      (791, 792),
      (747, 794),
      (703, 797),
      (660, 801),
      (619, 807),
      (578, 813),
      (538, 821),
      (500, 830),
      (463, 840),
      (426, 852),
      (391, 864),
      (357, 877),
      (325, 892),
      (294, 907),
      (264, 923),
      (235, 941),
      (208, 959),
      (183, 978),
      (159, 999),
      (136, 1020),
      (115, 1042),
      (96, 1064),
      (78, 1088),
      (62, 1112),
      (48, 1138),
      (35, 1164),
      (25, 1190),
      (16, 1218),
      (9, 1246),
      (4, 1275),
      (1, 1305),
      (0, 1335),
      (1, 1361),
      (2, 1387),
      (5, 1412),
      (9, 1436),
      (15, 1459),
      (21, 1481),
      (28, 1502),
      (36, 1523),
      (45, 1543),
      (56, 1562),
      (67, 1580),
      (79, 1598),
      (92, 1614),
      (105, 1630),
      (120, 1645),
      (135, 1659),
      (151, 1673),
      (168, 1685),
      (185, 1697),
      (203, 1708),
      (222, 1717),
      (241, 1727),
      (261, 1735),
      (282, 1742),
      (303, 1749),
      (324, 1754),
      (346, 1759),
      (368, 1763),
      (391, 1766),
      (414, 1768),
      (461, 1770),
      (507, 1768),
      (551, 1764),
      (594, 1756),
      (637, 1746),
      (677, 1734),
      (717, 1720),
      (755, 1704),
      (792, 1686),
      (827, 1667),
      (860, 1648),
      (891, 1628),
      (920, 1607),
      (946, 1586),
      (971, 1566),
      (993, 1546),
      (1012, 1526),
      (1084, 1740),
      (1691, 1740),
      (1691, 1579),
      (1455, 1470),
      (1455, 540),
      (1454, 506),
      (1452, 473),
      (1448, 441),
      (1443, 410),
      (1437, 381),
      (1429, 352),
      (1420, 325),
      (1409, 299),
      (1397, 274),
      (1384, 250),
      (1370, 228),
      (1354, 206),
      (1337, 186),
      (1319, 166),
      (1300, 148),
      (1280, 131),
      (1258, 115),
      (1236, 100),
      (1212, 86),
      (1187, 73),
      (1162, 61),
      (1135, 50),
      (1107, 41),
      (1078, 32),
      (1049, 25),
      (1018, 18),
      (987, 12),
      (955, 8),
      (922, 4),
      (888, 2),
      (853, 0),
      (818, 0),
      (774, 1),
      (728, 3),
      (682, 7),
      (634, 12),
      (586, 18),
      (537, 25),
      (489, 34),
      (441, 43),
      (393, 53),
      (347, 64),
      (302, 76),
      (259, 89),
      (217, 101),
      (178, 115),
      (142, 129),
      (109, 142),
      (109, 596),
   ],
   vec![
      (1001, 1418),
      (952, 1435),
      (926, 1443),
      (899, 1450),
      (870, 1457),
      (840, 1462),
      (809, 1465),
      (776, 1466),
      (746, 1465),
      (716, 1463),
      (688, 1458),
      (660, 1452),
      (634, 1444),
      (610, 1434),
      (587, 1423),
      (566, 1409),
      (547, 1394),
      (530, 1377),
      (515, 1357),
      (503, 1337),
      (493, 1314),
      (486, 1289),
      (482, 1262),
      (480, 1234),
      (480, 1218),
      (482, 1202),
      (484, 1187),
      (487, 1173),
      (491, 1159),
      (496, 1146),
      (501, 1134),
      (507, 1122),
      (514, 1111),
      (522, 1101),
      (530, 1091),
      (540, 1082),
      (560, 1064),
      (583, 1050),
      (608, 1037),
      (635, 1026),
      (665, 1017),
      (697, 1010),
      (730, 1004),
      (765, 1000),
      (802, 998),
      (840, 998),
      (1005, 998),
   ]];

   let outer = points_from_coords(&data[0]);

   let mut inner = Vec::new();

   for inner_data in &data[1..] {
      inner.push(
         points_from_coords(inner_data)
      );
   }

   let poly = Poly::new_with_holes(
      outer, inner, RGB::new(255, 255, 255),
   );

   poly
}

fn points_from_coords(coords: &[(i64, i64)]) -> Vec<Point> {
   let mut points = Vec::new();

   for &(x, y) in coords.iter() {
      points.push(Point::new(x + 120, y + 120))
   }

   points
}

fn main() {
   let mut scene = Scene::new();

   scene.push(letter_poly());

   let mut renderer = DevelRenderer::new(scene);

   Application::new()
      .renderer(&mut renderer)
      .title("Letter")
      .size(1200, 800)
      .run();
}
<|endoftext|>


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

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

impl From<bool> for DataBlob {

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

impl From<i64> for DataBlob {

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

impl From<f32> for DataBlob {

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

impl From<Vec<u8>> for DataBlob {

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

impl From<String> for DataBlob {

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

impl KeyValue {

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

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

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

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

        AttributedDict {
            dat: iter.into_iter().map(pair).collect(),
        }
    }
}

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

impl std::fmt::Display for MicrosError {

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

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

impl std::error::Error for MicrosError {

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

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

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

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

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

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

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

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

impl From<bool> for DataBlob {

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

impl From<i64> for DataBlob {

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

impl From<f32> for DataBlob {

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

impl From<Vec<u8>> for DataBlob {

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

impl From<String> for DataBlob {

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

impl KeyValue {

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

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

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

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

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

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

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

impl std::fmt::Display for MicrosError {

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

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

impl std::error::Error for MicrosError {

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

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

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

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

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

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

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


<commit_before>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

#![warn(missing_docs)]
#![recursion_limit = "2048"]

//! TRust-DNS Protocol library

extern crate chrono;
extern crate data_encoding;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate futures;
#[cfg(feature = "openssl")]
extern crate openssl;
extern crate rand;
#[cfg(feature = "ring")]
extern crate ring;
#[macro_use]
extern crate tokio_core;
extern crate tokio_io;
#[cfg(feature = "ring")]
extern crate untrusted;

use std::marker::PhantomData;
use std::net::SocketAddr;

use futures::sync::mpsc::{UnboundedSender, SendError};

mod dns_handle;
pub mod error;
pub mod op;
pub mod rr;
mod retry_dns_handle;
#[cfg(feature = "dnssec")]
mod secure_dns_handle;
pub mod serialize;
pub mod tcp;
pub mod udp;

pub use dns_handle::{BasicDnsHandle, DnsFuture, DnsHandle, DnsStreamHandle, StreamHandle};
pub use retry_dns_handle::RetryDnsHandle;
#[cfg(feature = "dnssec")]
pub use secure_dns_handle::SecureDnsHandle;
use op::Message;
use error::*;

// TODO: change to Sink
/// A sender to which serialized DNS Messages can be sent
#[derive(Clone)]
pub struct BufStreamHandle<E> where E: FromProtoError {
    sender: UnboundedSender<(Vec<u8>, SocketAddr)>,
    phantom: PhantomData<E>
}

impl<E> BufStreamHandle<E> where E: FromProtoError {
    /// Constructs a new BufStreamHandle with the associated ProtoError
    pub fn new(sender: UnboundedSender<(Vec<u8>, SocketAddr)>) -> Self {
        BufStreamHandle { sender, phantom: PhantomData::<E> }
    }

    /// see [`futures::sync::mpsc::UnboundedSender`]
    pub fn unbounded_send(&self, msg: (Vec<u8>, SocketAddr)) -> Result<(), SendError<(Vec<u8>, SocketAddr)>> {
        self.sender.unbounded_send(msg)
    }
}

// TODO: change to Sink
/// A sender to which a Message can be sent
pub type MessageStreamHandle = UnboundedSender<Message>;

/// A buffering stream bound to a `SocketAddr`
pub struct BufDnsStreamHandle<E> where E: FromProtoError {
    name_server: SocketAddr,
    sender: BufStreamHandle<E>,
}

impl<E> BufDnsStreamHandle<E> where E: FromProtoError {
    /// Constructs a new Buffered Stream Handle, used for sending data to the DNS peer.
    ///
    /// # Arguments
    ///
    /// * `name_server` - the address of the DNS server
    /// * `sender` - the handle being used to send data to the server
    pub fn new(name_server: SocketAddr, sender: BufStreamHandle<E>) -> Self {
        BufDnsStreamHandle {
            name_server: name_server,
            sender: sender,
        }
    }
}

impl<E> DnsStreamHandle for BufDnsStreamHandle<E>
where
    E: FromProtoError
{
    type Error = E;

    fn send(&mut self, buffer: Vec<u8>) -> Result<(), E> {
        let name_server: SocketAddr = self.name_server;
        let sender: &mut _ = &mut self.sender;
        sender.sender.unbounded_send((buffer, name_server)).map_err(|e| {
            E::from(
                ProtoErrorKind::Msg(format!("mpsc::SendError {}", e)).into()
            )
        })
    }
}<commit_msg>Fix warning about unused data_encoding dependency with --no-default-features<commit_after>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

#![warn(missing_docs)]
#![recursion_limit = "2048"]

//! TRust-DNS Protocol library

extern crate chrono;
#[cfg(any(feature = "openssl", feature = "ring"))]
extern crate data_encoding;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate futures;
#[cfg(feature = "openssl")]
extern crate openssl;
extern crate rand;
#[cfg(feature = "ring")]
extern crate ring;
#[macro_use]
extern crate tokio_core;
extern crate tokio_io;
#[cfg(feature = "ring")]
extern crate untrusted;

use std::marker::PhantomData;
use std::net::SocketAddr;

use futures::sync::mpsc::{UnboundedSender, SendError};

mod dns_handle;
pub mod error;
pub mod op;
pub mod rr;
mod retry_dns_handle;
#[cfg(feature = "dnssec")]
mod secure_dns_handle;
pub mod serialize;
pub mod tcp;
pub mod udp;

pub use dns_handle::{BasicDnsHandle, DnsFuture, DnsHandle, DnsStreamHandle, StreamHandle};
pub use retry_dns_handle::RetryDnsHandle;
#[cfg(feature = "dnssec")]
pub use secure_dns_handle::SecureDnsHandle;
use op::Message;
use error::*;

// TODO: change to Sink
/// A sender to which serialized DNS Messages can be sent
#[derive(Clone)]
pub struct BufStreamHandle<E> where E: FromProtoError {
    sender: UnboundedSender<(Vec<u8>, SocketAddr)>,
    phantom: PhantomData<E>
}

impl<E> BufStreamHandle<E> where E: FromProtoError {
    /// Constructs a new BufStreamHandle with the associated ProtoError
    pub fn new(sender: UnboundedSender<(Vec<u8>, SocketAddr)>) -> Self {
        BufStreamHandle { sender, phantom: PhantomData::<E> }
    }

    /// see [`futures::sync::mpsc::UnboundedSender`]
    pub fn unbounded_send(&self, msg: (Vec<u8>, SocketAddr)) -> Result<(), SendError<(Vec<u8>, SocketAddr)>> {
        self.sender.unbounded_send(msg)
    }
}

// TODO: change to Sink
/// A sender to which a Message can be sent
pub type MessageStreamHandle = UnboundedSender<Message>;

/// A buffering stream bound to a `SocketAddr`
pub struct BufDnsStreamHandle<E> where E: FromProtoError {
    name_server: SocketAddr,
    sender: BufStreamHandle<E>,
}

impl<E> BufDnsStreamHandle<E> where E: FromProtoError {
    /// Constructs a new Buffered Stream Handle, used for sending data to the DNS peer.
    ///
    /// # Arguments
    ///
    /// * `name_server` - the address of the DNS server
    /// * `sender` - the handle being used to send data to the server
    pub fn new(name_server: SocketAddr, sender: BufStreamHandle<E>) -> Self {
        BufDnsStreamHandle {
            name_server: name_server,
            sender: sender,
        }
    }
}

impl<E> DnsStreamHandle for BufDnsStreamHandle<E>
where
    E: FromProtoError
{
    type Error = E;

    fn send(&mut self, buffer: Vec<u8>) -> Result<(), E> {
        let name_server: SocketAddr = self.name_server;
        let sender: &mut _ = &mut self.sender;
        sender.sender.unbounded_send((buffer, name_server)).map_err(|e| {
            E::from(
                ProtoErrorKind::Msg(format!("mpsc::SendError {}", e)).into()
            )
        })
    }
}<|endoftext|>


<commit_before>//! Generator of Rust-Qt crates.
//!
//! See [README](https://github.com/rust-qt/cpp_to_rust/tree/master/qt_generator/qt_generator)
//! for more information.

#![allow(clippy::collapsible_if)]

use crate::lib_configs::create_config;
use itertools::Itertools;
use log::{error, info};
use qt_ritual_common::all_crate_names;
use ritual::processor;
use ritual::workspace::Workspace;
use ritual_common::errors::{FancyUnwrap, Result};
use ritual_common::file_utils::canonicalize;
use ritual_common::file_utils::path_to_str;
use std::path::PathBuf;
use structopt::StructOpt;
mod detect_signal_argument_types;
mod detect_signals_and_slots;
mod doc_decoder;
mod doc_parser;
mod fix_header_names;
mod lib_configs;
mod slot_wrappers;
mod versions;

mod test_moqt;

use flexi_logger::{Duplicate, LevelFilter, LogSpecification, Logger};

#[derive(Debug, StructOpt)]
/// Generates rust_qt crates using ritual.
/// See https://github.com/rust-qt/cpp_to_rust for more details.
struct Options {
    #[structopt(parse(from_os_str))]
    /// Directory for output and temporary files
    workspace: PathBuf,
    #[structopt(long = "local-paths")]
    /// Write local paths to `ritual` crates in generated `Cargo.toml`
    local_paths: Option<bool>,
    #[structopt(long = "delete-database")]
    /// Delete previously created database before processing
    delete_database: bool,
    #[structopt(short = "c", long = "crates", required = true)]
    /// Crates to process (e.g. `qt_core`)
    crates: Vec<String>,
    #[structopt(short = "o", long = "operations", required = true)]
    /// Operations to perform
    operations: Vec<String>,
}

fn run(options: Options) -> Result<()> {
    let workspace_path = canonicalize(options.workspace)?;

    let mut workspace = Workspace::new(workspace_path.clone())?;

    Logger::with(LogSpecification::default(LevelFilter::Trace).build())
        .log_to_file()
        .directory(path_to_str(&workspace.log_path())?)
        .print_message()
        .duplicate_to_stderr(Duplicate::Info)
        .start()
        .unwrap_or_else(|e| panic!("Logger initialization failed: {}", e));

    info!("Workspace: {}", workspace_path.display());

    if let Some(local_paths) = options.local_paths {
        workspace.set_write_dependencies_local_paths(local_paths)?;
    }

    let mut was_any_action = false;

    let final_crates = if options.crates.iter().any(|x| *x == "all") {
        all_crate_names().to_vec()
    } else {
        options.crates.iter().map(|s| s.as_str()).collect()
    };

    let operations = options
        .operations
        .iter()
        .map(|s| s.to_lowercase())
        .collect_vec();

    if operations.is_empty() {
        error!("No action requested. Run \"qt_generator --help\".");
        return Ok(());
    }

    for crate_name in &final_crates {
        if options.delete_database {
            workspace.delete_database_if_exists(&crate_name)?;
        }

        let config = create_config(&crate_name)?;
        was_any_action = true;
        processor::process(&mut workspace, &config, &operations)?;
    }

    //workspace.save_data()?;
    if was_any_action {
        info!("qt_generator finished");
    } else {
        error!("No action requested. Run \"qt_generator --help\".");
    }
    Ok(())
}

pub fn main() {
    run(Options::from_args()).fancy_unwrap();
}

#[test]
fn qt_ritual_test1() {
    assert_eq!(true, true);
}
<commit_msg>add cfg(test) for test_moqt module<commit_after>//! Generator of Rust-Qt crates.
//!
//! See [README](https://github.com/rust-qt/cpp_to_rust/tree/master/qt_generator/qt_generator)
//! for more information.

#![allow(clippy::collapsible_if)]

use crate::lib_configs::create_config;
use itertools::Itertools;
use log::{error, info};
use qt_ritual_common::all_crate_names;
use ritual::processor;
use ritual::workspace::Workspace;
use ritual_common::errors::{FancyUnwrap, Result};
use ritual_common::file_utils::canonicalize;
use ritual_common::file_utils::path_to_str;
use std::path::PathBuf;
use structopt::StructOpt;
mod detect_signal_argument_types;
mod detect_signals_and_slots;
mod doc_decoder;
mod doc_parser;
mod fix_header_names;
mod lib_configs;
mod slot_wrappers;
mod versions;

#[cfg(test)]
mod test_moqt;

use flexi_logger::{Duplicate, LevelFilter, LogSpecification, Logger};

#[derive(Debug, StructOpt)]
/// Generates rust_qt crates using ritual.
/// See https://github.com/rust-qt/cpp_to_rust for more details.
struct Options {
    #[structopt(parse(from_os_str))]
    /// Directory for output and temporary files
    workspace: PathBuf,
    #[structopt(long = "local-paths")]
    /// Write local paths to `ritual` crates in generated `Cargo.toml`
    local_paths: Option<bool>,
    #[structopt(long = "delete-database")]
    /// Delete previously created database before processing
    delete_database: bool,
    #[structopt(short = "c", long = "crates", required = true)]
    /// Crates to process (e.g. `qt_core`)
    crates: Vec<String>,
    #[structopt(short = "o", long = "operations", required = true)]
    /// Operations to perform
    operations: Vec<String>,
}

fn run(options: Options) -> Result<()> {
    let workspace_path = canonicalize(options.workspace)?;

    let mut workspace = Workspace::new(workspace_path.clone())?;

    Logger::with(LogSpecification::default(LevelFilter::Trace).build())
        .log_to_file()
        .directory(path_to_str(&workspace.log_path())?)
        .print_message()
        .duplicate_to_stderr(Duplicate::Info)
        .start()
        .unwrap_or_else(|e| panic!("Logger initialization failed: {}", e));

    info!("Workspace: {}", workspace_path.display());

    if let Some(local_paths) = options.local_paths {
        workspace.set_write_dependencies_local_paths(local_paths)?;
    }

    let mut was_any_action = false;

    let final_crates = if options.crates.iter().any(|x| *x == "all") {
        all_crate_names().to_vec()
    } else {
        options.crates.iter().map(|s| s.as_str()).collect()
    };

    let operations = options
        .operations
        .iter()
        .map(|s| s.to_lowercase())
        .collect_vec();

    if operations.is_empty() {
        error!("No action requested. Run \"qt_generator --help\".");
        return Ok(());
    }

    for crate_name in &final_crates {
        if options.delete_database {
            workspace.delete_database_if_exists(&crate_name)?;
        }

        let config = create_config(&crate_name)?;
        was_any_action = true;
        processor::process(&mut workspace, &config, &operations)?;
    }

    //workspace.save_data()?;
    if was_any_action {
        info!("qt_generator finished");
    } else {
        error!("No action requested. Run \"qt_generator --help\".");
    }
    Ok(())
}

pub fn main() {
    run(Options::from_args()).fancy_unwrap();
}

#[test]
fn qt_ritual_test1() {
    assert_eq!(true, true);
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
// Copyright 2017 Paul Dicker.
// Copyright 2014-2017 Melissa O'Neill and PCG Project contributors
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! PCG random number generators

use core::fmt;
use rand_core::{impls, le, Error, RngCore, SeedableRng};
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};

// This is the default multiplier used by PCG for 64-bit state.
const MULTIPLIER: u64 = 6364136223846793005;

/// A PCG random number generator (XSH RR 64/32 (LCG) variant).
///
/// Permuted Congruential Generator with 64-bit state, internal Linear
/// Congruential Generator, and 32-bit output via "xorshift high (bits),
/// random rotation" output function.
///
/// This is a 64-bit LCG with explicitly chosen stream with the PCG-XSH-RR
/// output function. This combination is the standard `pcg32`.
///
/// Despite the name, this implementation uses 16 bytes (128 bit) space
/// comprising 64 bits of state and 64 bits stream selector. These are both set
/// by `SeedableRng`, using a 128-bit seed.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Lcg64Xsh32 {
    state: u64,
    increment: u64,
}

/// [`Lcg64Xsh32`] is also officially known as `pcg32`.
pub type Pcg32 = Lcg64Xsh32;

impl Lcg64Xsh32 {
    /// Multi-step advance functions (jump-ahead, jump-back)
    ///
    /// The method used here is based on Brown, "Random Number Generation
    /// with Arbitrary Stride,", Transactions of the American Nuclear
    /// Society (Nov. 1994).  The algorithm is very similar to fast
    /// exponentiation.
    ///
    /// Even though delta is an unsigned integer, we can pass a
    /// signed integer to go backwards, it just goes "the long way round".
    #[inline]
    pub fn advance(&mut self, delta: u64) {
        let mut acc_mult: u64 = 1;
        let mut acc_plus: u64 = 0;
        let mut cur_mult = MULTIPLIER;
        let mut cur_plus = self.increment;
        let mut mdelta = delta.wrapping_mul(2);

        while mdelta > 0 {
            if (mdelta & 1) != 0 {
                acc_mult = acc_mult.wrapping_mul(cur_mult);
                acc_plus = acc_plus.wrapping_mul(cur_mult).wrapping_add(cur_plus);
            }
            cur_plus = cur_mult.wrapping_add(1).wrapping_mul(cur_plus);
            cur_mult = cur_mult.wrapping_mul(cur_mult);
            mdelta /= 2;
        }
        self.state = acc_mult.wrapping_mul(self.state).wrapping_add(acc_plus);
    }

    /// Construct an instance compatible with PCG seed and stream.
    ///
    /// Note that PCG specifies default values for both parameters:
    ///
    /// - `state = 0xcafef00dd15ea5e5`
    /// - `stream = 0xa02bdbf7bb3c0a7`
    // Note: stream is 1442695040888963407u64 >> 1
    pub fn new(state: u64, stream: u64) -> Self {
        // The increment must be odd, hence we discard one bit:
        let increment = (stream << 1) | 1;
        Lcg64Xsh32::from_state_incr(state, increment)
    }

    #[inline]
    fn from_state_incr(state: u64, increment: u64) -> Self {
        let mut pcg = Lcg64Xsh32 { state, increment };
        // Move away from inital value:
        pcg.state = pcg.state.wrapping_add(pcg.increment);
        pcg.step();
        pcg
    }

    #[inline]
    fn step(&mut self) {
        // prepare the LCG for the next round
        self.state = self
            .state
            .wrapping_mul(MULTIPLIER)
            .wrapping_add(self.increment);
    }
}

// Custom Debug implementation that does not expose the internal state
impl fmt::Debug for Lcg64Xsh32 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Lcg64Xsh32 {{}}")
    }
}

/// We use a single 127-bit seed to initialise the state and select a stream.
/// One `seed` bit (lowest bit of `seed[8]`) is ignored.
impl SeedableRng for Lcg64Xsh32 {
    type Seed = [u8; 16];

    fn from_seed(seed: Self::Seed) -> Self {
        let mut seed_u64 = [0u64; 2];
        le::read_u64_into(&seed, &mut seed_u64);

        // The increment must be odd, hence we discard one bit:
        Lcg64Xsh32::from_state_incr(seed_u64[0], seed_u64[1] | 1)
    }
}

impl RngCore for Lcg64Xsh32 {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        let state = self.state;
        self.step();

        // Output function XSH RR: xorshift high (bits), followed by a random rotate
        // Constants are for 64-bit state, 32-bit output
        const ROTATE: u32 = 59; // 64 - 5
        const XSHIFT: u32 = 18; // (5 + 32) / 2
        const SPARE: u32 = 27; // 64 - 32 - 5

        let rot = (state >> ROTATE) as u32;
        let xsh = (((state >> XSHIFT) ^ state) >> SPARE) as u32;
        xsh.rotate_right(rot)
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        impls::next_u64_via_u32(self)
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        impls::fill_bytes_via_next(self, dest)
    }

    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}
<commit_msg>Revert "Delta needs to be doubled when advancing Lcg64Xsh32"<commit_after>// Copyright 2018 Developers of the Rand project.
// Copyright 2017 Paul Dicker.
// Copyright 2014-2017 Melissa O'Neill and PCG Project contributors
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! PCG random number generators

use core::fmt;
use rand_core::{impls, le, Error, RngCore, SeedableRng};
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};

// This is the default multiplier used by PCG for 64-bit state.
const MULTIPLIER: u64 = 6364136223846793005;

/// A PCG random number generator (XSH RR 64/32 (LCG) variant).
///
/// Permuted Congruential Generator with 64-bit state, internal Linear
/// Congruential Generator, and 32-bit output via "xorshift high (bits),
/// random rotation" output function.
///
/// This is a 64-bit LCG with explicitly chosen stream with the PCG-XSH-RR
/// output function. This combination is the standard `pcg32`.
///
/// Despite the name, this implementation uses 16 bytes (128 bit) space
/// comprising 64 bits of state and 64 bits stream selector. These are both set
/// by `SeedableRng`, using a 128-bit seed.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct Lcg64Xsh32 {
    state: u64,
    increment: u64,
}

/// [`Lcg64Xsh32`] is also officially known as `pcg32`.
pub type Pcg32 = Lcg64Xsh32;

impl Lcg64Xsh32 {
    /// Multi-step advance functions (jump-ahead, jump-back)
    ///
    /// The method used here is based on Brown, "Random Number Generation
    /// with Arbitrary Stride,", Transactions of the American Nuclear
    /// Society (Nov. 1994).  The algorithm is very similar to fast
    /// exponentiation.
    ///
    /// Even though delta is an unsigned integer, we can pass a
    /// signed integer to go backwards, it just goes "the long way round".
    #[inline]
    pub fn advance(&mut self, delta: u64) {
        let mut acc_mult: u64 = 1;
        let mut acc_plus: u64 = 0;
        let mut cur_mult = MULTIPLIER;
        let mut cur_plus = self.increment;
        let mut mdelta = delta;

        while mdelta > 0 {
            if (mdelta & 1) != 0 {
                acc_mult = acc_mult.wrapping_mul(cur_mult);
                acc_plus = acc_plus.wrapping_mul(cur_mult).wrapping_add(cur_plus);
            }
            cur_plus = cur_mult.wrapping_add(1).wrapping_mul(cur_plus);
            cur_mult = cur_mult.wrapping_mul(cur_mult);
            mdelta /= 2;
        }
        self.state = acc_mult.wrapping_mul(self.state).wrapping_add(acc_plus);
    }

    /// Construct an instance compatible with PCG seed and stream.
    ///
    /// Note that PCG specifies default values for both parameters:
    ///
    /// - `state = 0xcafef00dd15ea5e5`
    /// - `stream = 0xa02bdbf7bb3c0a7`
    // Note: stream is 1442695040888963407u64 >> 1
    pub fn new(state: u64, stream: u64) -> Self {
        // The increment must be odd, hence we discard one bit:
        let increment = (stream << 1) | 1;
        Lcg64Xsh32::from_state_incr(state, increment)
    }

    #[inline]
    fn from_state_incr(state: u64, increment: u64) -> Self {
        let mut pcg = Lcg64Xsh32 { state, increment };
        // Move away from inital value:
        pcg.state = pcg.state.wrapping_add(pcg.increment);
        pcg.step();
        pcg
    }

    #[inline]
    fn step(&mut self) {
        // prepare the LCG for the next round
        self.state = self
            .state
            .wrapping_mul(MULTIPLIER)
            .wrapping_add(self.increment);
    }
}

// Custom Debug implementation that does not expose the internal state
impl fmt::Debug for Lcg64Xsh32 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Lcg64Xsh32 {{}}")
    }
}

/// We use a single 127-bit seed to initialise the state and select a stream.
/// One `seed` bit (lowest bit of `seed[8]`) is ignored.
impl SeedableRng for Lcg64Xsh32 {
    type Seed = [u8; 16];

    fn from_seed(seed: Self::Seed) -> Self {
        let mut seed_u64 = [0u64; 2];
        le::read_u64_into(&seed, &mut seed_u64);

        // The increment must be odd, hence we discard one bit:
        Lcg64Xsh32::from_state_incr(seed_u64[0], seed_u64[1] | 1)
    }
}

impl RngCore for Lcg64Xsh32 {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        let state = self.state;
        self.step();

        // Output function XSH RR: xorshift high (bits), followed by a random rotate
        // Constants are for 64-bit state, 32-bit output
        const ROTATE: u32 = 59; // 64 - 5
        const XSHIFT: u32 = 18; // (5 + 32) / 2
        const SPARE: u32 = 27; // 64 - 32 - 5

        let rot = (state >> ROTATE) as u32;
        let xsh = (((state >> XSHIFT) ^ state) >> SPARE) as u32;
        xsh.rotate_right(rot)
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        impls::next_u64_via_u32(self)
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        impls::fill_bytes_via_next(self, dest)
    }

    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}
<|endoftext|>


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

use rustc_hash::FxHashMap;
use rustc_hash::FxHashSet;
use salsa;

use crate::file_resolver::FileResolverImp;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(pub u32);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CrateId(pub u32);

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct CrateGraph {
    crate_roots: FxHashMap<CrateId, FileId>,
}

impl CrateGraph {
    pub fn crate_root(&self, crate_id: CrateId) -> FileId {
        self.crate_roots[&crate_id]
    }
    pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
        let crate_id = CrateId(self.crate_roots.len() as u32);
        let prev = self.crate_roots.insert(crate_id, file_id);
        assert!(prev.is_none());
        crate_id
    }
    pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
        let (&crate_id, _) = self
            .crate_roots
            .iter()
            .find(|(_crate_id, &root_id)| root_id == file_id)?;
        Some(crate_id)
    }
}

salsa::query_group! {
    pub trait FilesDatabase: salsa::Database {
        fn file_text(file_id: FileId) -> Arc<String> {
            type FileTextQuery;
            storage input;
        }
        fn file_source_root(file_id: FileId) -> SourceRootId {
            type FileSourceRootQuery;
            storage input;
        }
        fn source_root(id: SourceRootId) -> Arc<SourceRoot> {
            type SourceRootQuery;
            storage input;
        }
        fn libraries() -> Arc<Vec<SourceRootId>> {
            type LibrariesQuery;
            storage input;
        }
        fn crate_graph() -> Arc<CrateGraph> {
            type CrateGraphQuery;
            storage input;
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SourceRootId(pub u32);

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct SourceRoot {
    pub file_resolver: FileResolverImp,
    pub files: FxHashSet<FileId>,
}

pub const WORKSPACE: SourceRootId = SourceRootId(0);
<commit_msg>First step towards crate deps<commit_after>use std::sync::Arc;

use rustc_hash::FxHashMap;
use rustc_hash::FxHashSet;
use salsa;

use crate::file_resolver::FileResolverImp;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(pub u32);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CrateId(pub u32);

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct CrateGraph {
    arena: FxHashMap<CrateId, CrateData>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct CrateData {
    file_id: FileId,
    deps: Vec<Dependency>,
}

impl CrateData {
    fn new(file_id: FileId) -> CrateData {
        CrateData {
            file_id,
            deps: Vec::new(),
        }
    }

    fn add_dep(&mut self, dep: CrateId) {
        self.deps.push(Dependency { crate_: dep })
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Dependency {
    crate_: CrateId,
}

impl CrateGraph {
    pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
        let crate_id = CrateId(self.arena.len() as u32);
        let prev = self.arena.insert(crate_id, CrateData::new(file_id));
        assert!(prev.is_none());
        crate_id
    }
    pub fn add_dep(&mut self, from: CrateId, to: CrateId) {
        self.arena.get_mut(&from).unwrap().add_dep(to)
    }
    pub fn crate_root(&self, crate_id: CrateId) -> FileId {
        self.arena[&crate_id].file_id
    }
    pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
        let (&crate_id, _) = self
            .arena
            .iter()
            .find(|(_crate_id, data)| data.file_id == file_id)?;
        Some(crate_id)
    }
}

salsa::query_group! {
    pub trait FilesDatabase: salsa::Database {
        fn file_text(file_id: FileId) -> Arc<String> {
            type FileTextQuery;
            storage input;
        }
        fn file_source_root(file_id: FileId) -> SourceRootId {
            type FileSourceRootQuery;
            storage input;
        }
        fn source_root(id: SourceRootId) -> Arc<SourceRoot> {
            type SourceRootQuery;
            storage input;
        }
        fn libraries() -> Arc<Vec<SourceRootId>> {
            type LibrariesQuery;
            storage input;
        }
        fn crate_graph() -> Arc<CrateGraph> {
            type CrateGraphQuery;
            storage input;
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SourceRootId(pub u32);

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct SourceRoot {
    pub file_resolver: FileResolverImp,
    pub files: FxHashSet<FileId>,
}

pub const WORKSPACE: SourceRootId = SourceRootId(0);
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::mem;
use std::ptr;
use std::sync::Arc;

use device::Device;
use descriptor_set::PipelineLayout;
use descriptor_set::PipelineLayoutDesc;
use framebuffer::Subpass;
use shader::FragmentShaderEntryPoint;
use shader::VertexShaderEntryPoint;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

use pipeline::GenericPipeline;
use pipeline::blend::Blend;
use pipeline::input_assembly::InputAssembly;
use pipeline::multisample::Multisample;
use pipeline::raster::DepthBiasControl;
use pipeline::raster::Rasterization;
use pipeline::vertex::MultiVertex;
use pipeline::vertex::Vertex;
use pipeline::viewport::ViewportsState;

///
///
/// The template parameter contains the descriptor set to use with this pipeline, and the
/// renderpass layout.
pub struct GraphicsPipeline<MultiVertex, Layout> {
    device: Arc<Device>,
    pipeline: vk::Pipeline,
    layout: Arc<PipelineLayout<Layout>>,

    dynamic_line_width: bool,
    dynamic_viewport: bool,
    dynamic_scissor: bool,
    dynamic_depth_bias: bool,

    num_viewports: u32,

    marker: PhantomData<(MultiVertex,)>
}

impl<MV, L> GraphicsPipeline<MV, L>
    where MV: MultiVertex, L: PipelineLayoutDesc
{
    /// Builds a new graphics pipeline object.
    ///
    /// # Panic
    ///
    /// - Panicks if primitive restart is enabled and the topology doesn't support this feature.
    /// - Panicks if the `rasterization_samples` parameter of `multisample` is not >= 1.
    /// - Panicks if the `sample_shading` parameter of `multisample` is not between 0.0 and 1.0.
    /// - Panicks if the line width is different from 1.0 and the `wide_lines` feature is not enabled.
    ///
    // TODO: check all the device's limits
    pub fn new<Vi, Fo, R, Vl, Fl>
              (device: &Arc<Device>, vertex_shader: &VertexShaderEntryPoint<Vi, Vl>,
               input_assembly: &InputAssembly, viewport: &ViewportsState,
               raster: &Rasterization, multisample: &Multisample, blend: &Blend,
               fragment_shader: &FragmentShaderEntryPoint<Fo, Fl>,
               layout: &Arc<PipelineLayout<L>>, render_pass: &Subpass<R>)
               -> Result<Arc<GraphicsPipeline<MV, L>>, OomError>
    {
        let vk = device.pointers();

        // FIXME: check layout compatibility

        let pipeline = unsafe {
            // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
            let mut dynamic_states: Vec<vk::DynamicState> = Vec::new();
            // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
            let mut stages = Vec::with_capacity(5);

            stages.push(vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                stage: vk::SHADER_STAGE_VERTEX_BIT,
                module: vertex_shader.module().internal_object(),
                pName: vertex_shader.name().as_ptr(),
                pSpecializationInfo: ptr::null(),       // TODO:
            });

            stages.push(vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                stage: vk::SHADER_STAGE_FRAGMENT_BIT,
                module: fragment_shader.module().internal_object(),
                pName: fragment_shader.name().as_ptr(),
                pSpecializationInfo: ptr::null(),       // TODO:
            });

            // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
            let binding_descriptions = (0 .. MV::num_buffers()).map(|num| {
                let (stride, rate) = MV::buffer_info(num);
                vk::VertexInputBindingDescription {
                    binding: num,
                    stride: stride,
                    inputRate: rate as u32,
                }
            }).collect::<Vec<_>>();

            // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
            let attribute_descriptions = vertex_shader.attributes().iter().map(|&(loc, ref name)| {
                let (binding, info) = MV::attrib(name).expect("missing attr");       // TODO: error
                vk::VertexInputAttributeDescription {
                    location: loc as u32,
                    binding: binding,
                    format: info.format as u32,
                    offset: info.offset as u32,
                }
            }).collect::<Vec<_>>();

            let vertex_input_state = vk::PipelineVertexInputStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                vertexBindingDescriptionCount: binding_descriptions.len() as u32,
                pVertexBindingDescriptions: binding_descriptions.as_ptr(),
                vertexAttributeDescriptionCount: attribute_descriptions.len() as u32,
                pVertexAttributeDescriptions: attribute_descriptions.as_ptr(),
            };

            assert!(!input_assembly.primitive_restart_enable ||
                    input_assembly.topology.supports_primitive_restart());
            let input_assembly = vk::PipelineInputAssemblyStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                topology: input_assembly.topology as u32,
                primitiveRestartEnable: if input_assembly.primitive_restart_enable { vk::TRUE } else { vk::FALSE },
            };

            let (vp_vp, vp_sc, vp_num) = match *viewport {
                ViewportsState::Fixed { ref data } => (
                    data.iter().map(|e| e.0.clone().into()).collect::<Vec<vk::Viewport>>(),
                    data.iter().map(|e| e.1.clone().into()).collect::<Vec<vk::Rect2D>>(),
                    data.len() as u32
                ),
                ViewportsState::DynamicViewports { ref scissors } => {
                    let num = scissors.len() as u32;
                    let scissors = scissors.iter().map(|e| e.clone().into())
                                           .collect::<Vec<vk::Rect2D>>();
                    dynamic_states.push(vk::DYNAMIC_STATE_VIEWPORT);
                    (vec![], scissors, num)
                },
                ViewportsState::DynamicScissors { ref viewports } => {
                    let num = viewports.len() as u32;
                    let viewports = viewports.iter().map(|e| e.clone().into())
                                             .collect::<Vec<vk::Viewport>>();
                    dynamic_states.push(vk::DYNAMIC_STATE_SCISSOR);
                    (viewports, vec![], num)
                },
                ViewportsState::Dynamic { num } => (vec![], vec![], num),
            };

            let viewport_info = vk::PipelineViewportStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                viewportCount: vp_num,
                pViewports: vp_vp.as_ptr(),
                scissorCount: vp_num,
                pScissors: vp_sc.as_ptr(),
            };

            if let Some(line_width) = raster.line_width {
                if line_width != 1.0 {
                    assert!(device.enabled_features().wide_lines);
                }
            } else {
                dynamic_states.push(vk::DYNAMIC_STATE_LINE_WIDTH);
            }

            let (db_enable, db_const, db_clamp, db_slope) = match raster.depth_bias {
                DepthBiasControl::Dynamic => {
                    dynamic_states.push(vk::DYNAMIC_STATE_DEPTH_BIAS);
                    (vk::TRUE, 0.0, 0.0, 0.0)
                },
                DepthBiasControl::Disabled => {
                    (vk::FALSE, 0.0, 0.0, 0.0)
                },
                DepthBiasControl::Static(bias) => {
                    // TODO: check the depthBiasClamp feature if clamp != 0.0
                    (vk::TRUE, bias.constant_factor, bias.clamp, bias.slope_factor)
                },
            };

            let rasterization = vk::PipelineRasterizationStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                depthClampEnable: if raster.depth_clamp { vk::TRUE } else { vk::FALSE },
                rasterizerDiscardEnable: if raster.rasterizer_discard { vk::TRUE } else { vk::FALSE },
                polygonMode: raster.polygon_mode as u32,
                cullMode: raster.cull_mode as u32,
                frontFace: raster.front_face as u32,
                depthBiasEnable: db_enable,
                depthBiasConstantFactor: db_const,
                depthBiasClamp: db_clamp,
                depthBiasSlopeFactor: db_slope,
                lineWidth: raster.line_width.unwrap_or(1.0),
            };

            assert!(multisample.rasterization_samples >= 1);
            // FIXME: check that rasterization_samples is equal to what's in the renderpass
            if let Some(s) = multisample.sample_shading { assert!(s >= 0.0 && s <= 1.0); }
            let multisample = vk::PipelineMultisampleStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                rasterizationSamples: multisample.rasterization_samples,
                sampleShadingEnable: if multisample.sample_shading.is_some() { vk::TRUE } else { vk::FALSE },
                minSampleShading: multisample.sample_shading.unwrap_or(1.0),
                pSampleMask: ptr::null(),   //multisample.sample_mask.as_ptr(),     // FIXME:
                alphaToCoverageEnable: if multisample.alpha_to_coverage { vk::TRUE } else { vk::FALSE },
                alphaToOneEnable: if multisample.alpha_to_one { vk::TRUE } else { vk::FALSE },
            };

            let depth_stencil = vk::PipelineDepthStencilStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                depthTestEnable: vk::TRUE,          // FIXME:
                depthWriteEnable: vk::TRUE,         // FIXME:
                depthCompareOp: vk::COMPARE_OP_LESS,           // FIXME:
                depthBoundsTestEnable: vk::FALSE,            // FIXME:
                stencilTestEnable: vk::FALSE,            // FIXME:
                front: vk::StencilOpState {
                    failOp: vk::STENCIL_OP_KEEP,           // FIXME:
                    passOp: vk::STENCIL_OP_KEEP,           // FIXME:
                    depthFailOp: vk::STENCIL_OP_KEEP,          // FIXME:
                    compareOp: 0,            // FIXME:
                    compareMask: 0,          // FIXME:
                    writeMask: 0,            // FIXME:
                    reference: 0,            // FIXME:
                },
                back: vk::StencilOpState {
                    failOp: vk::STENCIL_OP_KEEP,           // FIXME:
                    passOp: vk::STENCIL_OP_KEEP,           // FIXME:
                    depthFailOp: vk::STENCIL_OP_KEEP,          // FIXME:
                    compareOp: 0,            // FIXME:
                    compareMask: 0,          // FIXME:
                    writeMask: 0,            // FIXME:
                    reference: 0,            // FIXME:
                },
                minDepthBounds: 0.0,           // FIXME:
                maxDepthBounds: 1.0,           // FIXME:
            };

            let atch = vk::PipelineColorBlendAttachmentState {
                blendEnable: 0,
                srcColorBlendFactor: 0,
                dstColorBlendFactor: 0,
                colorBlendOp: 0,
                srcAlphaBlendFactor: 0,
                dstAlphaBlendFactor: 0,
                alphaBlendOp: 0,
                colorWriteMask: 0xf,
            };
            let blend = vk::PipelineColorBlendStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                logicOpEnable: if blend.logic_op.is_some() { vk::TRUE } else { vk::FALSE },
                logicOp: blend.logic_op.unwrap_or(Default::default()) as u32,
                attachmentCount: 1,         // FIXME:
                pAttachments: &atch,      // FIXME:
                blendConstants: blend.blend_constants.unwrap_or([0.0, 0.0, 0.0, 0.0]),
            };

            let dynamic_states = vk::PipelineDynamicStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                dynamicStateCount:  dynamic_states.len() as u32,
                pDynamicStates: dynamic_states.as_ptr(),
            };

            let infos = vk::GraphicsPipelineCreateInfo {
                sType: vk::STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,       // TODO: some flags are available but none are critical
                stageCount: stages.len() as u32,
                pStages: stages.as_ptr(),
                pVertexInputState: &vertex_input_state,
                pInputAssemblyState: &input_assembly,
                pTessellationState: ptr::null(),        // FIXME:
                pViewportState: &viewport_info,
                pRasterizationState: &rasterization,
                pMultisampleState: &multisample,
                pDepthStencilState: &depth_stencil,
                pColorBlendState: &blend,
                pDynamicState: &dynamic_states,
                layout: layout.internal_object(),
                renderPass: render_pass.renderpass().internal_object(),
                subpass: render_pass.index(),
                basePipelineHandle: 0,    // TODO:
                basePipelineIndex: -1,       // TODO:
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateGraphicsPipelines(device.internal_object(), 0,
                                                         1, &infos, ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(GraphicsPipeline {
            device: device.clone(),
            pipeline: pipeline,
            layout: layout.clone(),

            dynamic_line_width: raster.line_width.is_none(),
            dynamic_viewport: viewport.dynamic_viewports(),
            dynamic_scissor: viewport.dynamic_scissors(),
            dynamic_depth_bias: raster.depth_bias.is_dynamic(),

            num_viewports: viewport.num_viewports(),

            marker: PhantomData,
        }))
    }
}

impl<MV, L> GraphicsPipeline<MV, L>
    where MV: MultiVertex, L: PipelineLayoutDesc
{
    /// Returns the pipeline layout used in the constructor.
    #[inline]
    pub fn layout(&self) -> &Arc<PipelineLayout<L>> {
        &self.layout
    }
}

impl<MultiVertex, Layout> GraphicsPipeline<MultiVertex, Layout> {
    /// Returns true if the line width used by this pipeline is dynamic.
    #[inline]
    pub fn has_dynamic_line_width(&self) -> bool {
        self.dynamic_line_width
    }
}

impl<MultiVertex, Layout> GenericPipeline for GraphicsPipeline<MultiVertex, Layout> {
}

unsafe impl<MultiVertex, Layout> VulkanObject for GraphicsPipeline<MultiVertex, Layout> {
    type Object = vk::Pipeline;

    #[inline]
    fn internal_object(&self) -> vk::Pipeline {
        self.pipeline
    }
}

impl<MultiVertex, Layout> Drop for GraphicsPipeline<MultiVertex, Layout> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipeline(self.device.internal_object(), self.pipeline, ptr::null());
        }
    }
}
<commit_msg>Fix missing viewport/scissor dynamic state with Dynamic<commit_after>use std::marker::PhantomData;
use std::mem;
use std::ptr;
use std::sync::Arc;

use device::Device;
use descriptor_set::PipelineLayout;
use descriptor_set::PipelineLayoutDesc;
use framebuffer::Subpass;
use shader::FragmentShaderEntryPoint;
use shader::VertexShaderEntryPoint;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

use pipeline::GenericPipeline;
use pipeline::blend::Blend;
use pipeline::input_assembly::InputAssembly;
use pipeline::multisample::Multisample;
use pipeline::raster::DepthBiasControl;
use pipeline::raster::Rasterization;
use pipeline::vertex::MultiVertex;
use pipeline::vertex::Vertex;
use pipeline::viewport::ViewportsState;

///
///
/// The template parameter contains the descriptor set to use with this pipeline, and the
/// renderpass layout.
pub struct GraphicsPipeline<MultiVertex, Layout> {
    device: Arc<Device>,
    pipeline: vk::Pipeline,
    layout: Arc<PipelineLayout<Layout>>,

    dynamic_line_width: bool,
    dynamic_viewport: bool,
    dynamic_scissor: bool,
    dynamic_depth_bias: bool,

    num_viewports: u32,

    marker: PhantomData<(MultiVertex,)>
}

impl<MV, L> GraphicsPipeline<MV, L>
    where MV: MultiVertex, L: PipelineLayoutDesc
{
    /// Builds a new graphics pipeline object.
    ///
    /// # Panic
    ///
    /// - Panicks if primitive restart is enabled and the topology doesn't support this feature.
    /// - Panicks if the `rasterization_samples` parameter of `multisample` is not >= 1.
    /// - Panicks if the `sample_shading` parameter of `multisample` is not between 0.0 and 1.0.
    /// - Panicks if the line width is different from 1.0 and the `wide_lines` feature is not enabled.
    ///
    // TODO: check all the device's limits
    pub fn new<Vi, Fo, R, Vl, Fl>
              (device: &Arc<Device>, vertex_shader: &VertexShaderEntryPoint<Vi, Vl>,
               input_assembly: &InputAssembly, viewport: &ViewportsState,
               raster: &Rasterization, multisample: &Multisample, blend: &Blend,
               fragment_shader: &FragmentShaderEntryPoint<Fo, Fl>,
               layout: &Arc<PipelineLayout<L>>, render_pass: &Subpass<R>)
               -> Result<Arc<GraphicsPipeline<MV, L>>, OomError>
    {
        let vk = device.pointers();

        // FIXME: check layout compatibility

        let pipeline = unsafe {
            // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
            let mut dynamic_states: Vec<vk::DynamicState> = Vec::new();
            // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
            let mut stages = Vec::with_capacity(5);

            stages.push(vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                stage: vk::SHADER_STAGE_VERTEX_BIT,
                module: vertex_shader.module().internal_object(),
                pName: vertex_shader.name().as_ptr(),
                pSpecializationInfo: ptr::null(),       // TODO:
            });

            stages.push(vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                stage: vk::SHADER_STAGE_FRAGMENT_BIT,
                module: fragment_shader.module().internal_object(),
                pName: fragment_shader.name().as_ptr(),
                pSpecializationInfo: ptr::null(),       // TODO:
            });

            // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
            let binding_descriptions = (0 .. MV::num_buffers()).map(|num| {
                let (stride, rate) = MV::buffer_info(num);
                vk::VertexInputBindingDescription {
                    binding: num,
                    stride: stride,
                    inputRate: rate as u32,
                }
            }).collect::<Vec<_>>();

            // TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
            let attribute_descriptions = vertex_shader.attributes().iter().map(|&(loc, ref name)| {
                let (binding, info) = MV::attrib(name).expect("missing attr");       // TODO: error
                vk::VertexInputAttributeDescription {
                    location: loc as u32,
                    binding: binding,
                    format: info.format as u32,
                    offset: info.offset as u32,
                }
            }).collect::<Vec<_>>();

            let vertex_input_state = vk::PipelineVertexInputStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                vertexBindingDescriptionCount: binding_descriptions.len() as u32,
                pVertexBindingDescriptions: binding_descriptions.as_ptr(),
                vertexAttributeDescriptionCount: attribute_descriptions.len() as u32,
                pVertexAttributeDescriptions: attribute_descriptions.as_ptr(),
            };

            assert!(!input_assembly.primitive_restart_enable ||
                    input_assembly.topology.supports_primitive_restart());
            let input_assembly = vk::PipelineInputAssemblyStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                topology: input_assembly.topology as u32,
                primitiveRestartEnable: if input_assembly.primitive_restart_enable { vk::TRUE } else { vk::FALSE },
            };

            let (vp_vp, vp_sc, vp_num) = match *viewport {
                ViewportsState::Fixed { ref data } => (
                    data.iter().map(|e| e.0.clone().into()).collect::<Vec<vk::Viewport>>(),
                    data.iter().map(|e| e.1.clone().into()).collect::<Vec<vk::Rect2D>>(),
                    data.len() as u32
                ),
                ViewportsState::DynamicViewports { ref scissors } => {
                    let num = scissors.len() as u32;
                    let scissors = scissors.iter().map(|e| e.clone().into())
                                           .collect::<Vec<vk::Rect2D>>();
                    dynamic_states.push(vk::DYNAMIC_STATE_VIEWPORT);
                    (vec![], scissors, num)
                },
                ViewportsState::DynamicScissors { ref viewports } => {
                    let num = viewports.len() as u32;
                    let viewports = viewports.iter().map(|e| e.clone().into())
                                             .collect::<Vec<vk::Viewport>>();
                    dynamic_states.push(vk::DYNAMIC_STATE_SCISSOR);
                    (viewports, vec![], num)
                },
                ViewportsState::Dynamic { num } => {
                    dynamic_states.push(vk::DYNAMIC_STATE_VIEWPORT);
                    dynamic_states.push(vk::DYNAMIC_STATE_SCISSOR);
                    (vec![], vec![], num)
                },
            };

            let viewport_info = vk::PipelineViewportStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                viewportCount: vp_num,
                pViewports: vp_vp.as_ptr(),
                scissorCount: vp_num,
                pScissors: vp_sc.as_ptr(),
            };

            if let Some(line_width) = raster.line_width {
                if line_width != 1.0 {
                    assert!(device.enabled_features().wide_lines);
                }
            } else {
                dynamic_states.push(vk::DYNAMIC_STATE_LINE_WIDTH);
            }

            let (db_enable, db_const, db_clamp, db_slope) = match raster.depth_bias {
                DepthBiasControl::Dynamic => {
                    dynamic_states.push(vk::DYNAMIC_STATE_DEPTH_BIAS);
                    (vk::TRUE, 0.0, 0.0, 0.0)
                },
                DepthBiasControl::Disabled => {
                    (vk::FALSE, 0.0, 0.0, 0.0)
                },
                DepthBiasControl::Static(bias) => {
                    // TODO: check the depthBiasClamp feature if clamp != 0.0
                    (vk::TRUE, bias.constant_factor, bias.clamp, bias.slope_factor)
                },
            };

            let rasterization = vk::PipelineRasterizationStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                depthClampEnable: if raster.depth_clamp { vk::TRUE } else { vk::FALSE },
                rasterizerDiscardEnable: if raster.rasterizer_discard { vk::TRUE } else { vk::FALSE },
                polygonMode: raster.polygon_mode as u32,
                cullMode: raster.cull_mode as u32,
                frontFace: raster.front_face as u32,
                depthBiasEnable: db_enable,
                depthBiasConstantFactor: db_const,
                depthBiasClamp: db_clamp,
                depthBiasSlopeFactor: db_slope,
                lineWidth: raster.line_width.unwrap_or(1.0),
            };

            assert!(multisample.rasterization_samples >= 1);
            // FIXME: check that rasterization_samples is equal to what's in the renderpass
            if let Some(s) = multisample.sample_shading { assert!(s >= 0.0 && s <= 1.0); }
            let multisample = vk::PipelineMultisampleStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                rasterizationSamples: multisample.rasterization_samples,
                sampleShadingEnable: if multisample.sample_shading.is_some() { vk::TRUE } else { vk::FALSE },
                minSampleShading: multisample.sample_shading.unwrap_or(1.0),
                pSampleMask: ptr::null(),   //multisample.sample_mask.as_ptr(),     // FIXME:
                alphaToCoverageEnable: if multisample.alpha_to_coverage { vk::TRUE } else { vk::FALSE },
                alphaToOneEnable: if multisample.alpha_to_one { vk::TRUE } else { vk::FALSE },
            };

            let depth_stencil = vk::PipelineDepthStencilStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                depthTestEnable: vk::TRUE,          // FIXME:
                depthWriteEnable: vk::TRUE,         // FIXME:
                depthCompareOp: vk::COMPARE_OP_LESS,           // FIXME:
                depthBoundsTestEnable: vk::FALSE,            // FIXME:
                stencilTestEnable: vk::FALSE,            // FIXME:
                front: vk::StencilOpState {
                    failOp: vk::STENCIL_OP_KEEP,           // FIXME:
                    passOp: vk::STENCIL_OP_KEEP,           // FIXME:
                    depthFailOp: vk::STENCIL_OP_KEEP,          // FIXME:
                    compareOp: 0,            // FIXME:
                    compareMask: 0,          // FIXME:
                    writeMask: 0,            // FIXME:
                    reference: 0,            // FIXME:
                },
                back: vk::StencilOpState {
                    failOp: vk::STENCIL_OP_KEEP,           // FIXME:
                    passOp: vk::STENCIL_OP_KEEP,           // FIXME:
                    depthFailOp: vk::STENCIL_OP_KEEP,          // FIXME:
                    compareOp: 0,            // FIXME:
                    compareMask: 0,          // FIXME:
                    writeMask: 0,            // FIXME:
                    reference: 0,            // FIXME:
                },
                minDepthBounds: 0.0,           // FIXME:
                maxDepthBounds: 1.0,           // FIXME:
            };

            let atch = vk::PipelineColorBlendAttachmentState {
                blendEnable: 0,
                srcColorBlendFactor: 0,
                dstColorBlendFactor: 0,
                colorBlendOp: 0,
                srcAlphaBlendFactor: 0,
                dstAlphaBlendFactor: 0,
                alphaBlendOp: 0,
                colorWriteMask: 0xf,
            };
            let blend = vk::PipelineColorBlendStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                logicOpEnable: if blend.logic_op.is_some() { vk::TRUE } else { vk::FALSE },
                logicOp: blend.logic_op.unwrap_or(Default::default()) as u32,
                attachmentCount: 1,         // FIXME:
                pAttachments: &atch,      // FIXME:
                blendConstants: blend.blend_constants.unwrap_or([0.0, 0.0, 0.0, 0.0]),
            };

            let dynamic_states = vk::PipelineDynamicStateCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,   // reserved
                dynamicStateCount:  dynamic_states.len() as u32,
                pDynamicStates: dynamic_states.as_ptr(),
            };

            let infos = vk::GraphicsPipelineCreateInfo {
                sType: vk::STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,       // TODO: some flags are available but none are critical
                stageCount: stages.len() as u32,
                pStages: stages.as_ptr(),
                pVertexInputState: &vertex_input_state,
                pInputAssemblyState: &input_assembly,
                pTessellationState: ptr::null(),        // FIXME:
                pViewportState: &viewport_info,
                pRasterizationState: &rasterization,
                pMultisampleState: &multisample,
                pDepthStencilState: &depth_stencil,
                pColorBlendState: &blend,
                pDynamicState: &dynamic_states,
                layout: layout.internal_object(),
                renderPass: render_pass.renderpass().internal_object(),
                subpass: render_pass.index(),
                basePipelineHandle: 0,    // TODO:
                basePipelineIndex: -1,       // TODO:
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateGraphicsPipelines(device.internal_object(), 0,
                                                         1, &infos, ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(GraphicsPipeline {
            device: device.clone(),
            pipeline: pipeline,
            layout: layout.clone(),

            dynamic_line_width: raster.line_width.is_none(),
            dynamic_viewport: viewport.dynamic_viewports(),
            dynamic_scissor: viewport.dynamic_scissors(),
            dynamic_depth_bias: raster.depth_bias.is_dynamic(),

            num_viewports: viewport.num_viewports(),

            marker: PhantomData,
        }))
    }
}

impl<MV, L> GraphicsPipeline<MV, L>
    where MV: MultiVertex, L: PipelineLayoutDesc
{
    /// Returns the pipeline layout used in the constructor.
    #[inline]
    pub fn layout(&self) -> &Arc<PipelineLayout<L>> {
        &self.layout
    }
}

impl<MultiVertex, Layout> GraphicsPipeline<MultiVertex, Layout> {
    /// Returns true if the line width used by this pipeline is dynamic.
    #[inline]
    pub fn has_dynamic_line_width(&self) -> bool {
        self.dynamic_line_width
    }
}

impl<MultiVertex, Layout> GenericPipeline for GraphicsPipeline<MultiVertex, Layout> {
}

unsafe impl<MultiVertex, Layout> VulkanObject for GraphicsPipeline<MultiVertex, Layout> {
    type Object = vk::Pipeline;

    #[inline]
    fn internal_object(&self) -> vk::Pipeline {
        self.pipeline
    }
}

impl<MultiVertex, Layout> Drop for GraphicsPipeline<MultiVertex, Layout> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipeline(self.device.internal_object(), self.pipeline, ptr::null());
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate num;

use libc::{c_char, c_double, c_float, c_int};
use num::complex::Complex;

#[link(name = "arpack")]
extern {

    // single precision symmetric

    fn ssaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               info: *mut c_int);

    fn sseupd_(rvec: *const c_int,
               All: *const c_char,
               select: *mut c_int,
               d: *mut c_float,
               z: *mut c_float,
               ldz: *const c_int,
               sigma: *const c_float,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               ierr: *mut c_int);

    // double precision symmetric

    fn dsaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               info: *mut c_int);

    fn dseupd_(rvec: *const c_int,
               All: *const c_char,
               select: *mut c_int,
               d: *mut c_double,
               z: *mut c_double,
               ldz: *const c_int,
               sigma: *const c_double,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               ierr: *mut c_int);

    // single precision non-symmetric

    // fixme: fn snaupd_();
    // fixme: fn sneupd_();

    // double precision non-symmetric

    // fixme: fn dnaupd_();
    // fixme: fn dneupd_();

    // single precision complex

    fn cnaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut Complex<c_float>,
               ncv: *const c_int,
               v: *mut Complex<c_float>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_float>,
               workl: *mut Complex<c_float>,
               lworkl: *const c_int,
               rwork: *mut c_float,
               info: *mut c_int);

    fn cneupd_(rvec: *const c_int,
               All: *const c_char,
               select: *mut c_int,
               d: *mut Complex<c_float>,
               v: *mut Complex<c_float>,
               ldv: *const c_int,
               sigma: *const c_float,
               workev: *mut Complex<c_float>,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut Complex<c_float>,
               ncv: *const c_int,
               v: *mut Complex<c_float>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_float>,
               workl: *mut Complex<c_float>,
               lworkl: *const c_int,
               rwork: *mut c_float,
               ierr: *mut c_int);

    // double precision complex

    fn znaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut Complex<c_double>,
               ncv: *const c_int,
               v: *mut Complex<c_double>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_double>,
               workl: *mut Complex<c_double>,
               lworkl: *const c_int,
               rwork: *mut c_double,
               info: *mut c_int);

    fn zneupd_(rvec: *const c_int,
               All: *const c_char,
               select: *mut c_int,
               d: *mut Complex<c_double>,
               v: *mut Complex<c_double>,
               ldv: *const c_int,
               sigma: *const c_double,
               workev: *mut Complex<c_double>,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut Complex<c_double>,
               ncv: *const c_int,
               v: *mut Complex<c_double>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_double>,
               workl: *mut Complex<c_double>,
               lworkl: *const c_int,
               rwork: *mut c_double,
               ierr: *mut c_int);

}
<commit_msg>dsaupd works<commit_after>extern crate libc;
extern crate num;
extern crate test;

use libc::{c_char, c_double, c_float, c_int};
use num::complex::Complex;

#[link(name = "arpack")]
extern {

    // single precision symmetric

    fn ssaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               info: *mut c_int);

    fn sseupd_(rvec: *const c_int,
               howmny: *const c_char,
               select: *mut c_int,
               d: *mut c_float,
               z: *mut c_float,
               ldz: *const c_int,
               sigma: *const c_float,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               ierr: *mut c_int);

    // double precision symmetric

    fn dsaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               info: *mut c_int);

    fn dseupd_(rvec: *const c_int,
               howmny: *const c_char,
               select: *mut c_int,
               d: *mut c_double,
               z: *mut c_double,
               ldz: *const c_int,
               sigma: *const c_double,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               ierr: *mut c_int);

    // single precision non-symmetric

    // fixme: fn snaupd_();
    // fixme: fn sneupd_();

    // double precision non-symmetric

    // fixme: fn dnaupd_();
    // fixme: fn dneupd_();

    // single precision complex

    fn cnaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut Complex<c_float>,
               ncv: *const c_int,
               v: *mut Complex<c_float>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_float>,
               workl: *mut Complex<c_float>,
               lworkl: *const c_int,
               rwork: *mut c_float,
               info: *mut c_int);

    fn cneupd_(rvec: *const c_int,
               howmny: *const c_char,
               select: *mut c_int,
               d: *mut Complex<c_float>,
               v: *mut Complex<c_float>,
               ldv: *const c_int,
               sigma: *const c_float,
               workev: *mut Complex<c_float>,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut Complex<c_float>,
               ncv: *const c_int,
               v: *mut Complex<c_float>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_float>,
               workl: *mut Complex<c_float>,
               lworkl: *const c_int,
               rwork: *mut c_float,
               ierr: *mut c_int);

    // double precision complex

    fn znaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut Complex<c_double>,
               ncv: *const c_int,
               v: *mut Complex<c_double>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_double>,
               workl: *mut Complex<c_double>,
               lworkl: *const c_int,
               rwork: *mut c_double,
               info: *mut c_int);

    fn zneupd_(rvec: *const c_int,
               howmny: *const c_char,
               select: *mut c_int,
               d: *mut Complex<c_double>,
               v: *mut Complex<c_double>,
               ldv: *const c_int,
               sigma: *const c_double,
               workev: *mut Complex<c_double>,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut Complex<c_double>,
               ncv: *const c_int,
               v: *mut Complex<c_double>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_double>,
               workl: *mut Complex<c_double>,
               lworkl: *const c_int,
               rwork: *mut c_double,
               ierr: *mut c_int);

}

enum Which {
    LM,
    SM,
    LA,
    SA,
    BE,
}

enum BMat {
    I,
    G,
}

fn which_func(which: Which) -> &'static str {
    match which {
        LM => "LM",
        SM => "SM",
        LA => "LA",
        SA => "SA",
        BE => "BE",
    }
}

fn bmat_func(bmat: BMat) -> &'static str {
    match bmat {
        I => "I",
        G => "G",
    }
}

// note: evals may potentially be modified even if there is an error.
fn dsaupd(n: c_int,
          nev: c_int,
          mv_multiply: |slice: &[c_double]| -> Vec<c_double>,
          evals: &mut Vec<c_double>,
          evecs: Option<&mut Vec<c_double>>) {
    assert!(nev > 0);
    assert!(nev < n);

    let mut ido: c_int = 0;
    let bmat = bmat_func(I).to_c_str();
    let which = which_func(SA).to_c_str();
    let tol: c_double = 0.0;
    let mut resid = Vec::from_elem(n as uint, 0.0 as c_double);
    let ncv = {
        let possible_ncv: c_int = 4 * nev;
        if possible_ncv > n {
            n
        } else {
            possible_ncv
        }
    };
    let ldv: c_int = n;
    let mut v = Vec::from_elem((ldv * ncv) as uint, 0.0 as c_double);
    let mut iparam = vec![1 as c_int, 0, 3 * n, 0, 0, 0, 1, 0, 0, 0, 0];
    // fixme: may wish to tune iparam[2] differently.
    let mut ipntr = Vec::from_elem(11, 0 as c_int);
    let mut workd = Vec::from_elem(3 * n as uint, 0.0 as c_double);
    let lworkl: c_int = ncv * (ncv + 8);
    let mut workl = Vec::from_elem(lworkl as uint, 0.0 as c_double);
    let mut info: c_int = 0;

    loop {
        unsafe {
            dsaupd_(&mut ido, bmat.as_ptr(), &n, which.as_ptr(), &nev, &tol,
                    resid.as_mut_ptr(), &ncv, v.as_mut_ptr(), &ldv,
                    iparam.as_mut_ptr(), ipntr.as_mut_ptr(), workd.as_mut_ptr(),
                    workl.as_mut_ptr(), &lworkl, &mut info);
        }

        if ido != 1 && ido != -1 {
            break;
        }

        // fixme: seems overkill
        let output = {
            let in_slice = workd.slice((ipntr[0] - 1) as uint,
                                       (ipntr[0] - 1 + n) as uint);
            mv_multiply(in_slice)
        };
        let out_slice = workd.mut_slice((ipntr[1] - 1) as uint,
                                        (ipntr[1] - 1 + n) as uint);
        out_slice.copy_from(output.as_slice());
    }

    if info < 0 {
        // fixme: return error using enum
        return;
    }

    let rvec: c_int = match evecs {
        Some(ref evecs) => 1,
        None => 0
    };
    let mut select = Vec::from_elem(ncv as uint, 0 as c_int);
    evals.clear(); // called ``d`` in arpack
    evals.grow(nev as uint, &0.0);
    let sigma: c_double = 0.0;
    let mut ierr: c_int = 0;

    let howmny = "A".to_c_str();
    unsafe {
        dseupd_(&rvec, howmny.as_ptr(), select.as_mut_ptr(), evals.as_mut_ptr(),
                v.as_mut_ptr(), &ldv, &sigma, bmat.as_ptr(),
	        &n, which.as_ptr(), &nev, &tol, resid.as_mut_ptr(), &ncv, v.as_mut_ptr(), &ldv,
	        iparam.as_mut_ptr(), ipntr.as_mut_ptr(), workd.as_mut_ptr(), workl.as_mut_ptr(), &lworkl, &mut ierr);
    }

    if ierr != 0 {
        // fixme: return error code
        return;
    }

    match evecs {
        Some(evecs) => {
            // copy the vector.  fixme: seems overkill.
            evecs.clear();
            evecs.grow((nev * n) as uint, &0.0);
            evecs.as_mut_slice().copy_from(v.as_slice());
        },
        None => ()
    };
}

#[cfg(test)]
mod tests {

    use super::dsaupd;
    use test::Bencher;
    use libc::c_double;

    #[test]
    fn test_dsaupd() {
        let mut evals: Vec<c_double> = Vec::new();
        let mut evecs: Vec<c_double> = Vec::new();
        dsaupd(8, 2, |slice: &[c_double]| {
            // FIXME: this is probably more involved than necessary
            slice.to_vec().move_iter().map(|i| 2.0 * i).collect()
        }, &mut evals, Some(&mut evecs));
    }

    #[bench]
    fn benchmark_dsaupd(b: &mut Bencher) {
        b.iter(|| test_dsaupd());
    }

}
<|endoftext|>