<commit_before>//! Contains the different types of values understood by XML-RPC.

use utils::{escape_xml, format_datetime};

use base64::encode;
use iso8601::DateTime;

use std::collections::BTreeMap;
use std::io::{self, Write};

/// The possible XML-RPC values.
///
/// Nested values can be accessed by using [`get`](#method.get) method and Rust's square-bracket
/// indexing operator.
///
/// A string index can be used to access a value in a `Struct`, and a `usize` index can be used to
/// access an element of an `Array`.
///
/// # Examples
///
/// ```
/// # use std::collections::BTreeMap;
/// # use xmlrpc::{Value, Index};
/// let nothing = Value::Nil;
///
/// let person = Value::Struct(vec![
///     ("name".to_string(), Value::from("John Doe")),
///     ("age".to_string(), Value::from(37)),
///     ("children".to_string(), Value::Array(vec![
///         Value::from("Mark"),
///         Value::from("Jennyfer")
///     ])),
/// ].into_iter().collect());
///
/// // get
/// assert_eq!(nothing.get("name"), None);
/// assert_eq!(person.get("name"), Some(&Value::from("John Doe")));
/// assert_eq!(person.get("SSN"), None);
///
/// // index
/// assert_eq!(nothing["name"], Value::Nil);
/// assert_eq!(person["name"], Value::from("John Doe"));
/// assert_eq!(person["age"], Value::Int(37));
/// assert_eq!(person["SSN"], Value::Nil);
/// assert_eq!(person["children"][0], Value::from("Mark"));
/// assert_eq!(person["children"][0]["age"], Value::Nil);
/// assert_eq!(person["children"][2], Value::Nil);
///
/// // extract values
/// assert_eq!(person["name"].as_str(), Some("John Doe"));
/// assert_eq!(person["age"].as_i32(), Some(37));
/// assert_eq!(person["age"].as_bool(), None);
/// assert_eq!(person["children"].as_array().unwrap().len(), 2);
/// ```
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// `<i4>` or `<int>`, 32-bit signed integer.
    Int(i32),
    /// `<i8>`, 64-bit signed integer.
    ///
    /// This is an XMLRPC extension and may not be supported by all clients / servers.
    Int64(i64),
    /// `<boolean>`, 0 == `false`, 1 == `true`.
    Bool(bool),
    /// `<string>`
    // FIXME zero-copy? `Cow<'static, ..>`?
    String(String),
    /// `<double>`
    Double(f64),
    /// `<dateTime.iso8601>`, an ISO 8601 formatted date/time value.
    DateTime(DateTime),
    /// `<base64>`, base64-encoded binary data.
    Base64(Vec<u8>),

    /// `<struct>`, a mapping of named values.
    Struct(BTreeMap<String, Value>),
    /// `<array>`, a list of arbitrary (heterogeneous) values.
    Array(Vec<Value>),

    /// `<nil/>`, the empty (Unit) value.
    ///
    /// This is an XMLRPC [extension][ext] and may not be supported by all clients / servers.
    ///
    /// [ext]: https://web.archive.org/web/20050911054235/http://ontosys.com/xml-rpc/extensions.php
    Nil,
}

impl Value {
    /// Formats this `Value` as an XML `<value>` element.
    pub fn write_as_xml<W: Write>(&self, fmt: &mut W) -> io::Result<()> {
        writeln!(fmt, "<value>")?;

        match *self {
            Value::Int(i) => {
                writeln!(fmt, "<i4>{}</i4>", i)?;
            }
            Value::Int64(i) => {
                writeln!(fmt, "<i8>{}</i8>", i)?;
            }
            Value::Bool(b) => {
                writeln!(fmt, "<boolean>{}</boolean>", if b { "1" } else { "0" })?;
            }
            Value::String(ref s) => {
                writeln!(fmt, "<string>{}</string>", escape_xml(s))?;
            }
            Value::Double(d) => {
                writeln!(fmt, "<double>{}</double>", d)?;
            }
            Value::DateTime(date_time) => {
                writeln!(fmt, "<dateTime.iso8601>{}</dateTime.iso8601>", format_datetime(&date_time))?;
            }
            Value::Base64(ref data) => {
                writeln!(fmt, "<base64>{}</base64>", encode(data))?;
            }
            Value::Struct(ref map) => {
                writeln!(fmt, "<struct>")?;
                for (ref name, ref value) in map {
                    writeln!(fmt, "<member>")?;
                    writeln!(fmt, "<name>{}</name>", escape_xml(name))?;
                    value.write_as_xml(fmt)?;
                    writeln!(fmt, "</member>")?;
                }
                writeln!(fmt, "</struct>")?;
            }
            Value::Array(ref array) => {
                writeln!(fmt, "<array>")?;
                writeln!(fmt, "<data>")?;
                for value in array {
                    value.write_as_xml(fmt)?;
                }
                writeln!(fmt, "</data>")?;
                writeln!(fmt, "</array>")?;
            }
            Value::Nil => {
                writeln!(fmt, "<nil/>")?;
            }
        }

        writeln!(fmt, "</value>")?;
        Ok(())
    }

    /// Returns an inner struct or array value indexed by `index`.
    ///
    /// Returns `None` if the member doesn't exist or `self` is neither a struct nor an array.
    ///
    /// You can also use Rust's square-bracket indexing syntax to perform this operation if you want
    /// a default value instead of an `Option`. Refer to the top-level [examples](#examples) for
    /// details.
    pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
        index.get(self)
    }

    /// If the `Value` is a normal integer (`Value::Int`), returns associated value. Returns `None`
    /// otherwise.
    ///
    /// In particular, `None` is also returned if `self` is a `Value::Int64`. Use [`as_i64`] to
    /// handle this case.
    ///
    /// [`as_i64`]: #method.as_i64
    pub fn as_i32(&self) -> Option<i32> {
        match *self {
            Value::Int(i) => Some(i),
            _ => None
        }
    }

    /// If the `Value` is an integer, returns associated value. Returns `None` otherwise.
    ///
    /// This works with both `Value::Int` and `Value::Int64`.
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Int(i) => Some(i64::from(i)),
            Value::Int64(i) => Some(i),
            _ => None
        }
    }

    /// If the `Value` is a boolean, returns associated value. Returns `None` otherwise.
    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            Value::Bool(b) => Some(b),
            _ => None
        }
    }

    /// If the `Value` is a string, returns associated value. Returns `None` otherwise.
    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Value::String(ref s) => Some(s),
            _ => None
        }
    }

    /// If the `Value` is a floating point number, returns associated value. Returns `None`
    /// otherwise.
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::Double(d) => Some(d),
            _ => None
        }
    }

    /// If the `Value` is a date/time, returns associated value. Returns `None` otherwise.
    pub fn as_datetime(&self) -> Option<DateTime> {
        match *self {
            Value::DateTime(dt) => Some(dt),
            _ => None
        }
    }

    /// If the `Value` is base64 binary data, returns associated value. Returns `None` otherwise.
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match *self {
            Value::Base64(ref data) => Some(data),
            _ => None
        }
    }

    /// If the `Value` is a struct, returns associated map. Returns `None` otherwise.
    pub fn as_struct(&self) -> Option<&BTreeMap<String, Value>> {
        match *self {
            Value::Struct(ref map) => Some(map),
            _ => None
        }
    }

    /// If the `Value` is an array, returns associated slice. Returns `None` otherwise.
    pub fn as_array(&self) -> Option<&[Value]> {
        match *self {
            Value::Array(ref array) => Some(array),
            _ => None
        }
    }
}

impl From<i32> for Value {
    fn from(other: i32) -> Self {
        Value::Int(other)
    }
}

impl From<i64> for Value {
    fn from(other: i64) -> Self {
        Value::Int64(other)
    }
}

impl From<bool> for Value {
    fn from(other: bool) -> Self {
        Value::Bool(other)
    }
}

impl From<String> for Value {
    fn from(other: String) -> Self {
        Value::String(other)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(other: &'a str) -> Self {
        Value::String(other.to_string())
    }
}

impl From<f64> for Value {
    fn from(other: f64) -> Self {
        Value::Double(other)
    }
}

impl From<DateTime> for Value {
    fn from(other: DateTime) -> Self {
        Value::DateTime(other)
    }
}

/// A type that can be used to index into a `Value`.
pub trait Index {
    /// Gets an inner value of a given value represented by self.
    #[doc(hidden)]
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value>;
}

impl Index for str {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for String {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for usize {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Array(ref array) = *value {
            array.get(*self)
        } else {
            None
        }
    }
}

impl<'a, I> Index for &'a I where I: Index + ?Sized {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        (*self).get(value)
    }
}

impl<I> ::std::ops::Index<I> for Value where I: Index {
    type Output = Value;
    fn index(&self, index: I) -> &Self::Output {
        index.get(self).unwrap_or(&Value::Nil)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::str;
    use std::collections::BTreeMap;

    #[test]
    fn escapes_strings() {
        let mut output: Vec<u8> = Vec::new();

        Value::from("<xml> string").write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<string><xml>&nbsp;string</string>\n</value>\n");
    }

    #[test]
    fn escapes_struct_member_names() {
        let mut output: Vec<u8> = Vec::new();
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("x&<x".to_string(), Value::from(true));

        Value::Struct(map).write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<struct>\n<member>\n<name>x&<x</name>\n<value>\n<boolean>1</boolean>\n</value>\n</member>\n</struct>\n</value>\n");
    }

    #[test]
    fn access_nested_values() {
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("name".to_string(), Value::from("John Doe"));
        map.insert("age".to_string(), Value::from(37));
        map.insert("children".to_string(), Value::Array(vec![Value::from("Mark"), Value::from("Jennyfer")]));
        let value = Value::Struct(map);

        assert_eq!(value.get("name"), Some(&Value::from("John Doe")));
        assert_eq!(value.get("age"), Some(&Value::from(37)));
        assert_eq!(value.get("birthdate"), None);
        assert_eq!(Value::Nil.get("age"), None);
        assert_eq!(value["name"], Value::from("John Doe"));
        assert_eq!(value["age"], Value::from(37));
        assert_eq!(value["birthdate"], Value::Nil);
        assert_eq!(Value::Nil["age"], Value::Nil);
        assert_eq!(value["children"][0], Value::from("Mark"));
        assert_eq!(value["children"][1], Value::from("Jennyfer"));
        assert_eq!(value["children"][2], Value::Nil);

        assert_eq!(value["age"].as_i32(), Some(37));
        assert_eq!(value["children"][0].as_str(), Some("Mark"));
    }
}
<commit_msg>Revert "Remove `From<Vec<u8>>` impl of `Value`"<commit_after>//! Contains the different types of values understood by XML-RPC.

use utils::{escape_xml, format_datetime};

use base64::encode;
use iso8601::DateTime;

use std::collections::BTreeMap;
use std::io::{self, Write};

/// The possible XML-RPC values.
///
/// Nested values can be accessed by using [`get`](#method.get) method and Rust's square-bracket
/// indexing operator.
///
/// A string index can be used to access a value in a `Struct`, and a `usize` index can be used to
/// access an element of an `Array`.
///
/// # Examples
///
/// ```
/// # use std::collections::BTreeMap;
/// # use xmlrpc::{Value, Index};
/// let nothing = Value::Nil;
///
/// let person = Value::Struct(vec![
///     ("name".to_string(), Value::from("John Doe")),
///     ("age".to_string(), Value::from(37)),
///     ("children".to_string(), Value::Array(vec![
///         Value::from("Mark"),
///         Value::from("Jennyfer")
///     ])),
/// ].into_iter().collect());
///
/// // get
/// assert_eq!(nothing.get("name"), None);
/// assert_eq!(person.get("name"), Some(&Value::from("John Doe")));
/// assert_eq!(person.get("SSN"), None);
///
/// // index
/// assert_eq!(nothing["name"], Value::Nil);
/// assert_eq!(person["name"], Value::from("John Doe"));
/// assert_eq!(person["age"], Value::Int(37));
/// assert_eq!(person["SSN"], Value::Nil);
/// assert_eq!(person["children"][0], Value::from("Mark"));
/// assert_eq!(person["children"][0]["age"], Value::Nil);
/// assert_eq!(person["children"][2], Value::Nil);
///
/// // extract values
/// assert_eq!(person["name"].as_str(), Some("John Doe"));
/// assert_eq!(person["age"].as_i32(), Some(37));
/// assert_eq!(person["age"].as_bool(), None);
/// assert_eq!(person["children"].as_array().unwrap().len(), 2);
/// ```
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// `<i4>` or `<int>`, 32-bit signed integer.
    Int(i32),
    /// `<i8>`, 64-bit signed integer.
    ///
    /// This is an XMLRPC extension and may not be supported by all clients / servers.
    Int64(i64),
    /// `<boolean>`, 0 == `false`, 1 == `true`.
    Bool(bool),
    /// `<string>`
    // FIXME zero-copy? `Cow<'static, ..>`?
    String(String),
    /// `<double>`
    Double(f64),
    /// `<dateTime.iso8601>`, an ISO 8601 formatted date/time value.
    DateTime(DateTime),
    /// `<base64>`, base64-encoded binary data.
    Base64(Vec<u8>),

    /// `<struct>`, a mapping of named values.
    Struct(BTreeMap<String, Value>),
    /// `<array>`, a list of arbitrary (heterogeneous) values.
    Array(Vec<Value>),

    /// `<nil/>`, the empty (Unit) value.
    ///
    /// This is an XMLRPC [extension][ext] and may not be supported by all clients / servers.
    ///
    /// [ext]: https://web.archive.org/web/20050911054235/http://ontosys.com/xml-rpc/extensions.php
    Nil,
}

impl Value {
    /// Formats this `Value` as an XML `<value>` element.
    pub fn write_as_xml<W: Write>(&self, fmt: &mut W) -> io::Result<()> {
        writeln!(fmt, "<value>")?;

        match *self {
            Value::Int(i) => {
                writeln!(fmt, "<i4>{}</i4>", i)?;
            }
            Value::Int64(i) => {
                writeln!(fmt, "<i8>{}</i8>", i)?;
            }
            Value::Bool(b) => {
                writeln!(fmt, "<boolean>{}</boolean>", if b { "1" } else { "0" })?;
            }
            Value::String(ref s) => {
                writeln!(fmt, "<string>{}</string>", escape_xml(s))?;
            }
            Value::Double(d) => {
                writeln!(fmt, "<double>{}</double>", d)?;
            }
            Value::DateTime(date_time) => {
                writeln!(fmt, "<dateTime.iso8601>{}</dateTime.iso8601>", format_datetime(&date_time))?;
            }
            Value::Base64(ref data) => {
                writeln!(fmt, "<base64>{}</base64>", encode(data))?;
            }
            Value::Struct(ref map) => {
                writeln!(fmt, "<struct>")?;
                for (ref name, ref value) in map {
                    writeln!(fmt, "<member>")?;
                    writeln!(fmt, "<name>{}</name>", escape_xml(name))?;
                    value.write_as_xml(fmt)?;
                    writeln!(fmt, "</member>")?;
                }
                writeln!(fmt, "</struct>")?;
            }
            Value::Array(ref array) => {
                writeln!(fmt, "<array>")?;
                writeln!(fmt, "<data>")?;
                for value in array {
                    value.write_as_xml(fmt)?;
                }
                writeln!(fmt, "</data>")?;
                writeln!(fmt, "</array>")?;
            }
            Value::Nil => {
                writeln!(fmt, "<nil/>")?;
            }
        }

        writeln!(fmt, "</value>")?;
        Ok(())
    }

    /// Returns an inner struct or array value indexed by `index`.
    ///
    /// Returns `None` if the member doesn't exist or `self` is neither a struct nor an array.
    ///
    /// You can also use Rust's square-bracket indexing syntax to perform this operation if you want
    /// a default value instead of an `Option`. Refer to the top-level [examples](#examples) for
    /// details.
    pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
        index.get(self)
    }

    /// If the `Value` is a normal integer (`Value::Int`), returns associated value. Returns `None`
    /// otherwise.
    ///
    /// In particular, `None` is also returned if `self` is a `Value::Int64`. Use [`as_i64`] to
    /// handle this case.
    ///
    /// [`as_i64`]: #method.as_i64
    pub fn as_i32(&self) -> Option<i32> {
        match *self {
            Value::Int(i) => Some(i),
            _ => None
        }
    }

    /// If the `Value` is an integer, returns associated value. Returns `None` otherwise.
    ///
    /// This works with both `Value::Int` and `Value::Int64`.
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Int(i) => Some(i64::from(i)),
            Value::Int64(i) => Some(i),
            _ => None
        }
    }

    /// If the `Value` is a boolean, returns associated value. Returns `None` otherwise.
    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            Value::Bool(b) => Some(b),
            _ => None
        }
    }

    /// If the `Value` is a string, returns associated value. Returns `None` otherwise.
    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Value::String(ref s) => Some(s),
            _ => None
        }
    }

    /// If the `Value` is a floating point number, returns associated value. Returns `None`
    /// otherwise.
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::Double(d) => Some(d),
            _ => None
        }
    }

    /// If the `Value` is a date/time, returns associated value. Returns `None` otherwise.
    pub fn as_datetime(&self) -> Option<DateTime> {
        match *self {
            Value::DateTime(dt) => Some(dt),
            _ => None
        }
    }

    /// If the `Value` is base64 binary data, returns associated value. Returns `None` otherwise.
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match *self {
            Value::Base64(ref data) => Some(data),
            _ => None
        }
    }

    /// If the `Value` is a struct, returns associated map. Returns `None` otherwise.
    pub fn as_struct(&self) -> Option<&BTreeMap<String, Value>> {
        match *self {
            Value::Struct(ref map) => Some(map),
            _ => None
        }
    }

    /// If the `Value` is an array, returns associated slice. Returns `None` otherwise.
    pub fn as_array(&self) -> Option<&[Value]> {
        match *self {
            Value::Array(ref array) => Some(array),
            _ => None
        }
    }
}

impl From<i32> for Value {
    fn from(other: i32) -> Self {
        Value::Int(other)
    }
}

impl From<i64> for Value {
    fn from(other: i64) -> Self {
        Value::Int64(other)
    }
}

impl From<bool> for Value {
    fn from(other: bool) -> Self {
        Value::Bool(other)
    }
}

impl From<String> for Value {
    fn from(other: String) -> Self {
        Value::String(other)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(other: &'a str) -> Self {
        Value::String(other.to_string())
    }
}

impl From<f64> for Value {
    fn from(other: f64) -> Self {
        Value::Double(other)
    }
}

impl From<DateTime> for Value {
    fn from(other: DateTime) -> Self {
        Value::DateTime(other)
    }
}

impl From<Vec<u8>> for Value {
    fn from(other: Vec<u8>) -> Self {
        Value::Base64(other)
    }
}

/// A type that can be used to index into a `Value`.
pub trait Index {
    /// Gets an inner value of a given value represented by self.
    #[doc(hidden)]
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value>;
}

impl Index for str {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for String {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for usize {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Array(ref array) = *value {
            array.get(*self)
        } else {
            None
        }
    }
}

impl<'a, I> Index for &'a I where I: Index + ?Sized {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        (*self).get(value)
    }
}

impl<I> ::std::ops::Index<I> for Value where I: Index {
    type Output = Value;
    fn index(&self, index: I) -> &Self::Output {
        index.get(self).unwrap_or(&Value::Nil)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::str;
    use std::collections::BTreeMap;

    #[test]
    fn escapes_strings() {
        let mut output: Vec<u8> = Vec::new();

        Value::from("<xml> string").write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<string><xml>&nbsp;string</string>\n</value>\n");
    }

    #[test]
    fn escapes_struct_member_names() {
        let mut output: Vec<u8> = Vec::new();
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("x&<x".to_string(), Value::from(true));

        Value::Struct(map).write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<struct>\n<member>\n<name>x&<x</name>\n<value>\n<boolean>1</boolean>\n</value>\n</member>\n</struct>\n</value>\n");
    }

    #[test]
    fn access_nested_values() {
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("name".to_string(), Value::from("John Doe"));
        map.insert("age".to_string(), Value::from(37));
        map.insert("children".to_string(), Value::Array(vec![Value::from("Mark"), Value::from("Jennyfer")]));
        let value = Value::Struct(map);

        assert_eq!(value.get("name"), Some(&Value::from("John Doe")));
        assert_eq!(value.get("age"), Some(&Value::from(37)));
        assert_eq!(value.get("birthdate"), None);
        assert_eq!(Value::Nil.get("age"), None);
        assert_eq!(value["name"], Value::from("John Doe"));
        assert_eq!(value["age"], Value::from(37));
        assert_eq!(value["birthdate"], Value::Nil);
        assert_eq!(Value::Nil["age"], Value::Nil);
        assert_eq!(value["children"][0], Value::from("Mark"));
        assert_eq!(value["children"][1], Value::from("Jennyfer"));
        assert_eq!(value["children"][2], Value::Nil);

        assert_eq!(value["age"].as_i32(), Some(37));
        assert_eq!(value["children"][0].as_str(), Some("Mark"));
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};
use util::CastF32;
use vec3f::Vec3f;

/// Vector with two f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec2f {
    pub x: f32,
    pub y: f32
}

impl Vec2f {
    /// Create a Vec2f from two components
    pub fn new(x: f32, y: f32) -> Vec2f {
        Vec2f { x: x,
                y: y }
    }

    pub fn cross(self, other: Vec2f) -> f32 {
        self.x * other.y - self.y * other.x
    }

    pub fn lerp(self, other: Vec2f, t: f32) -> Vec2f {
        self * (1.0 - t) + other * t
    }

    pub fn dot(self, other: Vec2f) -> f32 {
        self.x * other.x + self.y * other.y
    }

    pub fn vec3f(self) -> Vec3f {
        Vec3f::new(self.x, self.y, 0.0)
    }

    pub fn distance_squared(self, other: Vec2f) -> f32 {
        (self - other).magnitude_squared()
    }

    pub fn distance(self, other: Vec2f) -> f32 {
        self.distance_squared(other).sqrt()
    }

    pub fn magnitude_squared(self) -> f32 {
        self.dot(self)
    }

    pub fn magnitude(self) -> f32 {
        self.magnitude_squared().sqrt()
    }

    pub fn normalized(self) -> Option<Vec2f> {
        let m = self.magnitude();
        if m == 0.0 {
            None
        }
        else {
            Some(Vec2f::new(self.x / m, self.y / m))
        }
    }
}

impl Add for Vec2f {
    type Output = Vec2f;
    fn add(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x + v.x, self.y + v.y)
    }
}

impl Sub for Vec2f {
    type Output = Vec2f;
    fn sub(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x - v.x, self.y - v.y)
    }
}

impl Mul<f32> for Vec2f {
    type Output = Vec2f;
    fn mul(self, s: f32) -> Vec2f {
        Vec2f::new(self.x * s, self.y * s)
    }
}

impl Div<f32> for Vec2f {
    type Output = Vec2f;
    fn div(self, s: f32) -> Vec2f {
        Vec2f::new(self.x / s, self.y / s)
    }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Line2f {
    pub points: (Vec2f, Vec2f)
}

impl Line2f {
    pub fn new(a: Vec2f, b: Vec2f) -> Line2f {
        Line2f { points: (a, b) }
    }

    pub fn closest_parametric_point(self, point: Vec2f) -> f32 {
        let p0p = point - self.points.0;
        let p0p1 = self.points.1 - self.points.0;

        p0p.dot(p0p1) / p0p1.dot(p0p1)
    }

    pub fn cart_from_para(self, t: f32) -> Vec2f {
        self.points.0.lerp(self.points.1, t)
    }
}

/// Create a Vec2f from x and y inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec2f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec2f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec2f<X: CastF32, Y: CastF32>(x: X, y: Y) -> Vec2f {
    Vec2f { x: x.as_f32(), y: y.as_f32() }
}
<commit_msg>Add Line2f::orient<commit_after>// Copyright 2015 Nicholas Bishop
//
// Orientation code adapted from "Real-Time Collision Detection" by
// Christer Ericson, published by Morgan Kaufmann Publishers,
// Copyright 2005 Elsevier Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};
use util::CastF32;
use vec3f::Vec3f;

/// Vector with two f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec2f {
    pub x: f32,
    pub y: f32
}

impl Vec2f {
    /// Create a Vec2f from two components
    pub fn new(x: f32, y: f32) -> Vec2f {
        Vec2f { x: x,
                y: y }
    }

    pub fn cross(self, other: Vec2f) -> f32 {
        self.x * other.y - self.y * other.x
    }

    pub fn lerp(self, other: Vec2f, t: f32) -> Vec2f {
        self * (1.0 - t) + other * t
    }

    pub fn dot(self, other: Vec2f) -> f32 {
        self.x * other.x + self.y * other.y
    }

    pub fn vec3f(self) -> Vec3f {
        Vec3f::new(self.x, self.y, 0.0)
    }

    pub fn distance_squared(self, other: Vec2f) -> f32 {
        (self - other).magnitude_squared()
    }

    pub fn distance(self, other: Vec2f) -> f32 {
        self.distance_squared(other).sqrt()
    }

    pub fn magnitude_squared(self) -> f32 {
        self.dot(self)
    }

    pub fn magnitude(self) -> f32 {
        self.magnitude_squared().sqrt()
    }

    pub fn normalized(self) -> Option<Vec2f> {
        let m = self.magnitude();
        if m == 0.0 {
            None
        }
        else {
            Some(Vec2f::new(self.x / m, self.y / m))
        }
    }
}

impl Add for Vec2f {
    type Output = Vec2f;
    fn add(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x + v.x, self.y + v.y)
    }
}

impl Sub for Vec2f {
    type Output = Vec2f;
    fn sub(self, v: Vec2f) -> Vec2f {
        Vec2f::new(self.x - v.x, self.y - v.y)
    }
}

impl Mul<f32> for Vec2f {
    type Output = Vec2f;
    fn mul(self, s: f32) -> Vec2f {
        Vec2f::new(self.x * s, self.y * s)
    }
}

impl Div<f32> for Vec2f {
    type Output = Vec2f;
    fn div(self, s: f32) -> Vec2f {
        Vec2f::new(self.x / s, self.y / s)
    }
}

pub fn detf_2x2(top_left: f32, top_right: f32,
                bot_left: f32, bot_right: f32) -> f32 {
    top_left * bot_right - top_right * bot_left
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Line2f {
    pub points: (Vec2f, Vec2f)
}

impl Line2f {
    pub fn new(a: Vec2f, b: Vec2f) -> Line2f {
        Line2f { points: (a, b) }
    }

    pub fn closest_parametric_point(self, point: Vec2f) -> f32 {
        let p0p = point - self.points.0;
        let p0p1 = self.points.1 - self.points.0;

        p0p.dot(p0p1) / p0p1.dot(p0p1)
    }

    pub fn cart_from_para(self, t: f32) -> Vec2f {
        self.points.0.lerp(self.points.1, t)
    }

    /// If result is greater than zero `point` lies to the left of the
    /// line. If result is less than zero `point` lies to the
    /// right. If result is zero, the point is on the line.
    ///
    /// The value is also twice the signed area of the triangle
    /// `(points.0, points.1, point)` (positive if counterclockwise,
    /// otherwise negative).
    ///
    /// Adapted from "Real-Time Collision Detection" by Christer
    /// Ericson, published by Morgan Kaufmann Publishers, Copyright
    /// 2005 Elsevier Inc
    pub fn orient(self, point: Vec2f) -> f32 {
        detf_2x2(self.points.0.x - point.x, self.points.0.y - point.y,
                 self.points.1.x - point.x, self.points.1.y - point.y)
    }
}

/// Create a Vec2f from x and y inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec2f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec2f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec2f<X: CastF32, Y: CastF32>(x: X, y: Y) -> Vec2f {
    Vec2f { x: x.as_f32(), y: y.as_f32() }
}
<|endoftext|>


<commit_before>//! # cache
//!
//! Manages internal cargo-make persistant cache.
//!

#[cfg(test)]
#[path = "./cache_test.rs"]
mod cache_test;

use std::fs::{create_dir_all, File};
use std::io::Read;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use toml;
use environment;
use types::Cache;

fn load_from_path(directory: PathBuf) -> Cache {
    let file_path = Path::new(&directory).join("cache.toml");

    let mut cache_data = if file_path.exists() {
        match File::open(&file_path) {
            Ok(mut file) => {
                let mut cache_str = String::new();
                file.read_to_string(&mut cache_str).unwrap();

                let cache_data: Cache = match toml::from_str(&cache_str) {
                    Ok(value) => value,
                    Err(error) => {
                        info!("Unable to parse cache file, {}", error);
                        Cache::new()
                    }
                };

                cache_data
            }
            Err(error) => {
                info!(
                    "Unable to open cache file, directory: {:#?} error: {}",
                    &directory, error
                );
                Cache::new()
            }
        }
    } else {
        Cache::new()
    };

    match file_path.to_str() {
        Some(value) => cache_data.file_name = Some(value.to_string()),
        None => cache_data.file_name = None,
    };

    cache_data
}

/// Loads the persisted data
pub(crate) fn load() -> Cache {
    match environment::get_cargo_make_home() {
        Some(directory) => load_from_path(directory),
        None => Cache::new(),
    }
}

/// Stores the data
pub(crate) fn store(cache_data: &Cache) {
    match environment::get_cargo_make_home() {
        Some(directory) => {
            let mut exists = if directory.exists() {
                true
            } else {
                match create_dir_all(&directory) {
                    Ok(_) => true,
                    _ => false,
                }
            };

            if exists {
                let file_name = directory.join("cache.toml");

                let file_descriptor = match File::create(&file_name) {
                    Ok(mut file) => Some(file),
                    Err(error) => {
                        info!(
                            "Error while creating cache file: {:#?}, error: {:#?}",
                            &file_name, error
                        );
                        None
                    }
                };

                match file_descriptor {
                    Some(mut file) => match toml::to_string_pretty(cache_data) {
                        Ok(toml_str) => {
                            let data = toml_str.as_bytes();

                            match file.write_all(data) {
                                Err(error) => info!(
                                    "Error while writing to cache file: {:#?}, error: {:#?}",
                                    &file_name, error
                                ),
                                _ => (),
                            }
                        }
                        Err(error) => info!(
                            "Error during serialization of cache, file: {:#?}, error: {:#?}",
                            &file_name, error
                        ),
                    },
                    _ => (),
                };
            }
        }
        None => (),
    }
}
<commit_msg>fix build<commit_after>//! # cache
//!
//! Manages internal cargo-make persistant cache.
//!

#[cfg(test)]
#[path = "./cache_test.rs"]
mod cache_test;

use std::fs::{create_dir_all, File};
use std::io::Read;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use toml;
use environment;
use types::Cache;

fn load_from_path(directory: PathBuf) -> Cache {
    let file_path = Path::new(&directory).join("cache.toml");

    let mut cache_data = if file_path.exists() {
        match File::open(&file_path) {
            Ok(mut file) => {
                let mut cache_str = String::new();
                file.read_to_string(&mut cache_str).unwrap();

                let cache_data: Cache = match toml::from_str(&cache_str) {
                    Ok(value) => value,
                    Err(error) => {
                        info!("Unable to parse cache file, {}", error);
                        Cache::new()
                    }
                };

                cache_data
            }
            Err(error) => {
                info!(
                    "Unable to open cache file, directory: {:#?} error: {}",
                    &directory, error
                );
                Cache::new()
            }
        }
    } else {
        Cache::new()
    };

    match file_path.to_str() {
        Some(value) => cache_data.file_name = Some(value.to_string()),
        None => cache_data.file_name = None,
    };

    cache_data
}

/// Loads the persisted data
pub(crate) fn load() -> Cache {
    match environment::get_cargo_make_home() {
        Some(directory) => load_from_path(directory),
        None => Cache::new(),
    }
}

/// Stores the data
pub(crate) fn store(cache_data: &Cache) {
    match environment::get_cargo_make_home() {
        Some(directory) => {
            let exists = if directory.exists() {
                true
            } else {
                match create_dir_all(&directory) {
                    Ok(_) => true,
                    _ => false,
                }
            };

            if exists {
                let file_name = directory.join("cache.toml");

                let file_descriptor = match File::create(&file_name) {
                    Ok(file) => Some(file),
                    Err(error) => {
                        info!(
                            "Error while creating cache file: {:#?}, error: {:#?}",
                            &file_name, error
                        );
                        None
                    }
                };

                match file_descriptor {
                    Some(mut file) => match toml::to_string_pretty(cache_data) {
                        Ok(toml_str) => {
                            let data = toml_str.as_bytes();

                            match file.write_all(data) {
                                Err(error) => info!(
                                    "Error while writing to cache file: {:#?}, error: {:#?}",
                                    &file_name, error
                                ),
                                _ => (),
                            }
                        }
                        Err(error) => info!(
                            "Error during serialization of cache, file: {:#?}, error: {:#?}",
                            &file_name, error
                        ),
                    },
                    _ => (),
                };
            }
        }
        None => (),
    }
}
<|endoftext|>


<commit_before>//! Graph visitor algorithms.
//!

use std::collections::{
    HashSet,
    VecDeque,
};
use std::hash::Hash;
use fb::FixedBitSet;

use super::{
    graphmap,
    graph,
    EdgeType,
    EdgeDirection,
    Graph,
    GraphMap,
};

use graph::{
    IndexType,
};

/// Base trait for graphs that defines the node identifier.
pub trait Graphlike {
    type NodeId: Clone;
}

/// A graph trait for accessing the neighbors iterator
pub trait NeighborIter<'a> : Graphlike {
    type Iter: Iterator<Item=Self::NodeId>;

    /// Return an iterator that visits all neighbors of the node **n**.
    fn neighbors(&'a self, n: Self::NodeId) -> Self::Iter;
}

impl<'a, N, E, Ty, Ix> NeighborIter<'a> for Graph<N, E, Ty, Ix> where
    Ty: EdgeType,
    Ix: IndexType,
{
    type Iter = graph::Neighbors<'a, E, Ix>;
    fn neighbors(&'a self, n: graph::NodeIndex<Ix>) -> graph::Neighbors<'a, E, Ix>
    {
        Graph::neighbors(self, n)
    }
}

impl<'a, N, E> NeighborIter<'a> for GraphMap<N, E>
where N: Copy + Ord + Hash + Eq
{
    type Iter = graphmap::Neighbors<'a, N>;
    fn neighbors(&'a self, n: N) -> graphmap::Neighbors<'a, N>
    {
        GraphMap::neighbors(self, n)
    }
}

/// Wrapper type for walking the graph as if it is undirected
pub struct AsUndirected<G>(pub G);
/// Wrapper type for walking edges the other way
pub struct Reversed<G>(pub G);

impl<'a, 'b, N, E, Ty, Ix> NeighborIter<'a> for AsUndirected<&'b Graph<N, E, Ty, Ix>> where
    Ty: EdgeType,
    Ix: IndexType,
{
    type Iter = graph::Neighbors<'a, E, Ix>;

    fn neighbors(&'a self, n: graph::NodeIndex<Ix>) -> graph::Neighbors<'a, E, Ix>
    {
        Graph::neighbors_undirected(self.0, n)
    }
}

impl<'a, 'b, N, E, Ty, Ix> NeighborIter<'a> for Reversed<&'b Graph<N, E, Ty, Ix>> where
    Ty: EdgeType,
    Ix: IndexType,
{
    type Iter = graph::Neighbors<'a, E, Ix>;
    fn neighbors(&'a self, n: graph::NodeIndex<Ix>) -> graph::Neighbors<'a, E, Ix>
    {
        Graph::neighbors_directed(self.0, n, EdgeDirection::Incoming)
    }
}

pub trait VisitMap<N> {
    /// Return **true** if the value is not already present.
    fn visit(&mut self, N) -> bool;
    fn is_visited(&self, &N) -> bool;
}

impl<Ix> VisitMap<graph::NodeIndex<Ix>> for FixedBitSet where
    Ix: IndexType,
{
    fn visit(&mut self, x: graph::NodeIndex<Ix>) -> bool {
        let present = self.contains(x.index());
        self.insert(x.index());
        !present
    }
    fn is_visited(&self, x: &graph::NodeIndex<Ix>) -> bool {
        self.contains(x.index())
    }
}

impl<N: Eq + Hash> VisitMap<N> for HashSet<N> {
    fn visit(&mut self, x: N) -> bool {
        self.insert(x)
    }
    fn is_visited(&self, x: &N) -> bool {
        self.contains(x)
    }
}

/// Trait for GraphMap that knows which datastructure is the best for its visitor map
pub trait Visitable : Graphlike {
    type Map: VisitMap<Self::NodeId>;
    fn visit_map(&self) -> Self::Map;
}

impl<N, E, Ty, Ix> Graphlike for Graph<N, E, Ty, Ix> where
    Ix: IndexType,
{
    type NodeId = graph::NodeIndex<Ix>;
}

impl<N, E, Ty, Ix> Visitable for Graph<N, E, Ty, Ix> where
    Ty: EdgeType,
    Ix: IndexType,
{
    type Map = FixedBitSet;
    fn visit_map(&self) -> FixedBitSet { FixedBitSet::with_capacity(self.node_count()) }
}

impl<N: Clone, E> Graphlike for GraphMap<N, E>
{
    type NodeId = N;
}

impl<N, E> Visitable for GraphMap<N, E>
    where N: Copy + Ord + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<'a, V: Graphlike> Graphlike for AsUndirected<&'a V>
{
    type NodeId = V::NodeId;
}

impl<'a, V: Graphlike> Graphlike for Reversed<&'a V>
{
    type NodeId = V::NodeId;
}

impl<'a, V: Visitable> Visitable for AsUndirected<&'a V>
{
    type Map = V::Map;
    fn visit_map(&self) -> V::Map {
        self.0.visit_map()
    }
}

impl<'a, V: Visitable> Visitable for Reversed<&'a V>
{
    type Map = V::Map;
    fn visit_map(&self) -> V::Map {
        self.0.visit_map()
    }
}

/// Create or access the adjacency matrix of a graph
pub trait GetAdjacencyMatrix : Graphlike {
    type AdjMatrix;
    fn adjacency_matrix(&self) -> Self::AdjMatrix;
    fn is_adjacent(&self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool;
}

/// The **GraphMap** keeps an adjacency matrix internally.
impl<N, E> GetAdjacencyMatrix for GraphMap<N, E>
    where N: Copy + Ord + Eq + Hash
{
    type AdjMatrix = ();
    #[inline]
    fn adjacency_matrix(&self) { }
    #[inline]
    fn is_adjacent(&self, _: &(), a: N, b: N) -> bool {
        self.contains_edge(a, b)
    }
}

/// A depth first search (DFS) of a graph.
///
/// Using a **Dfs** you can run a traversal over a graph while still retaining
/// mutable access to it, if you use it like the following example:
///
/// ```
/// use petgraph::{Graph, Dfs};
///
/// let mut graph = Graph::<_,()>::new();
/// let a = graph.add_node(0);
///
/// let mut dfs = Dfs::new(&graph, a);
/// while let Some(nx) = dfs.next(&graph) {
///     // we can access `graph` mutably here still
///     graph[nx] += 1;
/// }
///
/// assert_eq!(graph[a], 1);
/// ```
///
/// **Note:** The algorithm may not behave correctly if nodes are removed
/// during iteration. It may not necessarily visit added nodes or edges.
#[derive(Clone, Debug)]
pub struct Dfs<N, VM> {
    pub stack: Vec<N>,
    pub discovered: VM,
}

impl<G: Visitable> Dfs<G::NodeId, G::Map>
{
    /// Create a new **Dfs**, using the graph's visitor map, and put **start**
    /// in the stack of nodes to visit.
    pub fn new(graph: &G, start: G::NodeId) -> Self
    {
        let mut dfs = Dfs::empty(graph);
        dfs.move_to(start);
        dfs
    }

    /// Create a new **Dfs** using the graph's visitor map, and no stack.
    pub fn empty(graph: &G) -> Self
    {
        Dfs {
            stack: Vec::new(),
            discovered: graph.visit_map(),
        }
    }
}

impl<N, VM> Dfs<N, VM> where
    N: Clone,
    VM: VisitMap<N>
{
    /// Keep the discovered map, but clear the visit stack and restart
    /// the dfs from a particular node.
    pub fn move_to(&mut self, start: N)
    {
        self.discovered.visit(start.clone());
        self.stack.clear();
        self.stack.push(start);
    }

    /// Return the next node in the dfs, or **None** if the traversal is done.
    pub fn next<G>(&mut self, graph: &G) -> Option<N> where
        G: Graphlike<NodeId=N>,
        G: for<'a> NeighborIter<'a>,
    {
        while let Some(node) = self.stack.pop() {
            for succ in graph.neighbors(node.clone()) {
                if self.discovered.visit(succ.clone()) {
                    self.stack.push(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

/// An iterator for a depth first traversal of a graph.
pub struct DfsIter<'a, G: 'a + Visitable>
{
    graph: &'a G,
    dfs: Dfs<G::NodeId, G::Map>,
}

impl<'a, G: Visitable> DfsIter<'a, G>
{
    pub fn new(graph: &'a G, start: G::NodeId) -> Self
    {
        // Inline the code from Dfs::new to
        // work around rust bug #22841
        let mut dfs = Dfs::empty(graph);
        dfs.move_to(start);
        DfsIter {
            graph: graph,
            dfs: dfs,
        }
    }
}

impl<'a, G: 'a + Visitable> Iterator for DfsIter<'a, G> where
    G: for<'b> NeighborIter<'b>,
{
    type Item = G::NodeId;
    fn next(&mut self) -> Option<G::NodeId>
    {
        self.dfs.next(self.graph)
    }
}

impl<'a, G: Visitable> Clone for DfsIter<'a, G> where Dfs<G::NodeId, G::Map>: Clone
{
    fn clone(&self) -> Self {
        DfsIter {
            graph: self.graph,
            dfs: self.dfs.clone(),
        }
    }
}

/// A breadth first search (BFS) of a graph.
///
/// Using a **Bfs** you can run a traversal over a graph while still retaining
/// mutable access to it, if you use it like the following example:
///
/// ```
/// use petgraph::{Graph, Bfs};
///
/// let mut graph = Graph::<_,()>::new();
/// let a = graph.add_node(0);
///
/// let mut bfs = Bfs::new(&graph, a);
/// while let Some(nx) = bfs.next(&graph) {
///     // we can access `graph` mutably here still
///     graph[nx] += 1;
/// }
///
/// assert_eq!(graph[a], 1);
/// ```
///
/// **Note:** The algorithm may not behave correctly if nodes are removed
/// during iteration. It may not necessarily visit added nodes or edges.
#[derive(Clone)]
pub struct Bfs<N, VM> {
    pub stack: VecDeque<N>,
    pub discovered: VM,
}

impl<G: Visitable> Bfs<G::NodeId, G::Map>
{
    /// Create a new **Bfs**, using the graph's visitor map, and put **start**
    /// in the stack of nodes to visit.
    pub fn new(graph: &G, start: G::NodeId) -> Self
    {
        let mut discovered = graph.visit_map();
        discovered.visit(start.clone());
        let mut stack = VecDeque::new();
        stack.push_front(start.clone());
        Bfs {
            stack: stack,
            discovered: discovered,
        }
    }
}

impl<N, VM> Bfs<N, VM> where
    N: Clone,
    VM: VisitMap<N>
{
    /// Return the next node in the dfs, or **None** if the traversal is done.
    pub fn next<G>(&mut self, graph: &G) -> Option<N> where
        G: Graphlike<NodeId=N>,
        G: for<'a> NeighborIter<'a>,
    {
        while let Some(node) = self.stack.pop_front() {
            for succ in graph.neighbors(node.clone()) {
                if self.discovered.visit(succ.clone()) {
                    self.stack.push_back(succ);
                }
            }

            return Some(node);
        }
        None
    }

}

/// An iterator for a breadth first traversal of a graph.
pub struct BfsIter<'a, G: 'a + Visitable>
{
    graph: &'a G,
    bfs: Bfs<G::NodeId, G::Map>,
}

impl<'a, G: Visitable> BfsIter<'a, G> where
    G::NodeId: Clone,
{
    pub fn new(graph: &'a G, start: G::NodeId) -> Self
    {
        // Inline the code from Bfs::new to
        // work around rust bug #22841
        let mut discovered = graph.visit_map();
        discovered.visit(start.clone());
        let mut stack = VecDeque::new();
        stack.push_front(start.clone());
        let bfs = Bfs {
            stack: stack,
            discovered: discovered,
        };
        BfsIter {
            graph: graph,
            bfs: bfs,
        }
    }
}

impl<'a, G: 'a + Visitable> Iterator for BfsIter<'a, G> where
    G::NodeId: Clone,
    G: for<'b> NeighborIter<'b>,
{
    type Item = G::NodeId;
    fn next(&mut self) -> Option<G::NodeId>
    {
        self.bfs.next(self.graph)
    }
}

impl<'a, G: Visitable> Clone for BfsIter<'a, G> where Bfs<G::NodeId, G::Map>: Clone
{
    fn clone(&self) -> Self {
        BfsIter {
            graph: self.graph,
            bfs: self.bfs.clone(),
        }
    }
}
<commit_msg>size_hint for visitor iterators<commit_after>//! Graph visitor algorithms.
//!

use std::collections::{
    HashSet,
    VecDeque,
};
use std::hash::Hash;
use fb::FixedBitSet;

use super::{
    graphmap,
    graph,
    EdgeType,
    EdgeDirection,
    Graph,
    GraphMap,
};

use graph::{
    IndexType,
};

/// Base trait for graphs that defines the node identifier.
pub trait Graphlike {
    type NodeId: Clone;
}

/// A graph trait for accessing the neighbors iterator
pub trait NeighborIter<'a> : Graphlike {
    type Iter: Iterator<Item=Self::NodeId>;

    /// Return an iterator that visits all neighbors of the node **n**.
    fn neighbors(&'a self, n: Self::NodeId) -> Self::Iter;
}

impl<'a, N, E, Ty, Ix> NeighborIter<'a> for Graph<N, E, Ty, Ix> where
    Ty: EdgeType,
    Ix: IndexType,
{
    type Iter = graph::Neighbors<'a, E, Ix>;
    fn neighbors(&'a self, n: graph::NodeIndex<Ix>) -> graph::Neighbors<'a, E, Ix>
    {
        Graph::neighbors(self, n)
    }
}

impl<'a, N, E> NeighborIter<'a> for GraphMap<N, E>
where N: Copy + Ord + Hash + Eq
{
    type Iter = graphmap::Neighbors<'a, N>;
    fn neighbors(&'a self, n: N) -> graphmap::Neighbors<'a, N>
    {
        GraphMap::neighbors(self, n)
    }
}

/// Wrapper type for walking the graph as if it is undirected
pub struct AsUndirected<G>(pub G);
/// Wrapper type for walking edges the other way
pub struct Reversed<G>(pub G);

impl<'a, 'b, N, E, Ty, Ix> NeighborIter<'a> for AsUndirected<&'b Graph<N, E, Ty, Ix>> where
    Ty: EdgeType,
    Ix: IndexType,
{
    type Iter = graph::Neighbors<'a, E, Ix>;

    fn neighbors(&'a self, n: graph::NodeIndex<Ix>) -> graph::Neighbors<'a, E, Ix>
    {
        Graph::neighbors_undirected(self.0, n)
    }
}

impl<'a, 'b, N, E, Ty, Ix> NeighborIter<'a> for Reversed<&'b Graph<N, E, Ty, Ix>> where
    Ty: EdgeType,
    Ix: IndexType,
{
    type Iter = graph::Neighbors<'a, E, Ix>;
    fn neighbors(&'a self, n: graph::NodeIndex<Ix>) -> graph::Neighbors<'a, E, Ix>
    {
        Graph::neighbors_directed(self.0, n, EdgeDirection::Incoming)
    }
}

pub trait VisitMap<N> {
    /// Return **true** if the value is not already present.
    fn visit(&mut self, N) -> bool;
    fn is_visited(&self, &N) -> bool;
}

impl<Ix> VisitMap<graph::NodeIndex<Ix>> for FixedBitSet where
    Ix: IndexType,
{
    fn visit(&mut self, x: graph::NodeIndex<Ix>) -> bool {
        let present = self.contains(x.index());
        self.insert(x.index());
        !present
    }
    fn is_visited(&self, x: &graph::NodeIndex<Ix>) -> bool {
        self.contains(x.index())
    }
}

impl<N: Eq + Hash> VisitMap<N> for HashSet<N> {
    fn visit(&mut self, x: N) -> bool {
        self.insert(x)
    }
    fn is_visited(&self, x: &N) -> bool {
        self.contains(x)
    }
}

/// Trait for GraphMap that knows which datastructure is the best for its visitor map
pub trait Visitable : Graphlike {
    type Map: VisitMap<Self::NodeId>;
    fn visit_map(&self) -> Self::Map;
}

impl<N, E, Ty, Ix> Graphlike for Graph<N, E, Ty, Ix> where
    Ix: IndexType,
{
    type NodeId = graph::NodeIndex<Ix>;
}

impl<N, E, Ty, Ix> Visitable for Graph<N, E, Ty, Ix> where
    Ty: EdgeType,
    Ix: IndexType,
{
    type Map = FixedBitSet;
    fn visit_map(&self) -> FixedBitSet { FixedBitSet::with_capacity(self.node_count()) }
}

impl<N: Clone, E> Graphlike for GraphMap<N, E>
{
    type NodeId = N;
}

impl<N, E> Visitable for GraphMap<N, E>
    where N: Copy + Ord + Eq + Hash
{
    type Map = HashSet<N>;
    fn visit_map(&self) -> HashSet<N> { HashSet::with_capacity(self.node_count()) }
}

impl<'a, V: Graphlike> Graphlike for AsUndirected<&'a V>
{
    type NodeId = V::NodeId;
}

impl<'a, V: Graphlike> Graphlike for Reversed<&'a V>
{
    type NodeId = V::NodeId;
}

impl<'a, V: Visitable> Visitable for AsUndirected<&'a V>
{
    type Map = V::Map;
    fn visit_map(&self) -> V::Map {
        self.0.visit_map()
    }
}

impl<'a, V: Visitable> Visitable for Reversed<&'a V>
{
    type Map = V::Map;
    fn visit_map(&self) -> V::Map {
        self.0.visit_map()
    }
}

/// Create or access the adjacency matrix of a graph
pub trait GetAdjacencyMatrix : Graphlike {
    type AdjMatrix;
    fn adjacency_matrix(&self) -> Self::AdjMatrix;
    fn is_adjacent(&self, matrix: &Self::AdjMatrix, a: Self::NodeId, b: Self::NodeId) -> bool;
}

/// The **GraphMap** keeps an adjacency matrix internally.
impl<N, E> GetAdjacencyMatrix for GraphMap<N, E>
    where N: Copy + Ord + Eq + Hash
{
    type AdjMatrix = ();
    #[inline]
    fn adjacency_matrix(&self) { }
    #[inline]
    fn is_adjacent(&self, _: &(), a: N, b: N) -> bool {
        self.contains_edge(a, b)
    }
}

/// A depth first search (DFS) of a graph.
///
/// Using a **Dfs** you can run a traversal over a graph while still retaining
/// mutable access to it, if you use it like the following example:
///
/// ```
/// use petgraph::{Graph, Dfs};
///
/// let mut graph = Graph::<_,()>::new();
/// let a = graph.add_node(0);
///
/// let mut dfs = Dfs::new(&graph, a);
/// while let Some(nx) = dfs.next(&graph) {
///     // we can access `graph` mutably here still
///     graph[nx] += 1;
/// }
///
/// assert_eq!(graph[a], 1);
/// ```
///
/// **Note:** The algorithm may not behave correctly if nodes are removed
/// during iteration. It may not necessarily visit added nodes or edges.
#[derive(Clone, Debug)]
pub struct Dfs<N, VM> {
    pub stack: Vec<N>,
    pub discovered: VM,
}

impl<G: Visitable> Dfs<G::NodeId, G::Map>
{
    /// Create a new **Dfs**, using the graph's visitor map, and put **start**
    /// in the stack of nodes to visit.
    pub fn new(graph: &G, start: G::NodeId) -> Self
    {
        let mut dfs = Dfs::empty(graph);
        dfs.move_to(start);
        dfs
    }

    /// Create a new **Dfs** using the graph's visitor map, and no stack.
    pub fn empty(graph: &G) -> Self
    {
        Dfs {
            stack: Vec::new(),
            discovered: graph.visit_map(),
        }
    }
}

impl<N, VM> Dfs<N, VM> where
    N: Clone,
    VM: VisitMap<N>
{
    /// Keep the discovered map, but clear the visit stack and restart
    /// the dfs from a particular node.
    pub fn move_to(&mut self, start: N)
    {
        self.discovered.visit(start.clone());
        self.stack.clear();
        self.stack.push(start);
    }

    /// Return the next node in the dfs, or **None** if the traversal is done.
    pub fn next<G>(&mut self, graph: &G) -> Option<N> where
        G: Graphlike<NodeId=N>,
        G: for<'a> NeighborIter<'a>,
    {
        while let Some(node) = self.stack.pop() {
            for succ in graph.neighbors(node.clone()) {
                if self.discovered.visit(succ.clone()) {
                    self.stack.push(succ);
                }
            }

            return Some(node);
        }
        None
    }
}

/// An iterator for a depth first traversal of a graph.
pub struct DfsIter<'a, G: 'a + Visitable>
{
    graph: &'a G,
    dfs: Dfs<G::NodeId, G::Map>,
}

impl<'a, G: Visitable> DfsIter<'a, G>
{
    pub fn new(graph: &'a G, start: G::NodeId) -> Self
    {
        // Inline the code from Dfs::new to
        // work around rust bug #22841
        let mut dfs = Dfs::empty(graph);
        dfs.move_to(start);
        DfsIter {
            graph: graph,
            dfs: dfs,
        }
    }
}

impl<'a, G: 'a + Visitable> Iterator for DfsIter<'a, G> where
    G: for<'b> NeighborIter<'b>,
{
    type Item = G::NodeId;

    #[inline]
    fn next(&mut self) -> Option<G::NodeId>
    {
        self.dfs.next(self.graph)
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        // Very vauge info about size of traversal
        (self.dfs.stack.len(), None)
    }
}

impl<'a, G: Visitable> Clone for DfsIter<'a, G> where Dfs<G::NodeId, G::Map>: Clone
{
    fn clone(&self) -> Self {
        DfsIter {
            graph: self.graph,
            dfs: self.dfs.clone(),
        }
    }
}

/// A breadth first search (BFS) of a graph.
///
/// Using a **Bfs** you can run a traversal over a graph while still retaining
/// mutable access to it, if you use it like the following example:
///
/// ```
/// use petgraph::{Graph, Bfs};
///
/// let mut graph = Graph::<_,()>::new();
/// let a = graph.add_node(0);
///
/// let mut bfs = Bfs::new(&graph, a);
/// while let Some(nx) = bfs.next(&graph) {
///     // we can access `graph` mutably here still
///     graph[nx] += 1;
/// }
///
/// assert_eq!(graph[a], 1);
/// ```
///
/// **Note:** The algorithm may not behave correctly if nodes are removed
/// during iteration. It may not necessarily visit added nodes or edges.
#[derive(Clone)]
pub struct Bfs<N, VM> {
    pub stack: VecDeque<N>,
    pub discovered: VM,
}

impl<G: Visitable> Bfs<G::NodeId, G::Map>
{
    /// Create a new **Bfs**, using the graph's visitor map, and put **start**
    /// in the stack of nodes to visit.
    pub fn new(graph: &G, start: G::NodeId) -> Self
    {
        let mut discovered = graph.visit_map();
        discovered.visit(start.clone());
        let mut stack = VecDeque::new();
        stack.push_front(start.clone());
        Bfs {
            stack: stack,
            discovered: discovered,
        }
    }
}

impl<N, VM> Bfs<N, VM> where
    N: Clone,
    VM: VisitMap<N>
{
    /// Return the next node in the dfs, or **None** if the traversal is done.
    pub fn next<G>(&mut self, graph: &G) -> Option<N> where
        G: Graphlike<NodeId=N>,
        G: for<'a> NeighborIter<'a>,
    {
        while let Some(node) = self.stack.pop_front() {
            for succ in graph.neighbors(node.clone()) {
                if self.discovered.visit(succ.clone()) {
                    self.stack.push_back(succ);
                }
            }

            return Some(node);
        }
        None
    }

}

/// An iterator for a breadth first traversal of a graph.
pub struct BfsIter<'a, G: 'a + Visitable>
{
    graph: &'a G,
    bfs: Bfs<G::NodeId, G::Map>,
}

impl<'a, G: Visitable> BfsIter<'a, G> where
    G::NodeId: Clone,
{
    pub fn new(graph: &'a G, start: G::NodeId) -> Self
    {
        // Inline the code from Bfs::new to
        // work around rust bug #22841
        let mut discovered = graph.visit_map();
        discovered.visit(start.clone());
        let mut stack = VecDeque::new();
        stack.push_front(start.clone());
        let bfs = Bfs {
            stack: stack,
            discovered: discovered,
        };
        BfsIter {
            graph: graph,
            bfs: bfs,
        }
    }
}

impl<'a, G: 'a + Visitable> Iterator for BfsIter<'a, G> where
    G::NodeId: Clone,
    G: for<'b> NeighborIter<'b>,
{
    type Item = G::NodeId;
    fn next(&mut self) -> Option<G::NodeId>
    {
        self.bfs.next(self.graph)
    }

    fn size_hint(&self) -> (usize, Option<usize>)
    {
        (self.bfs.stack.len(), None)
    }
}

impl<'a, G: Visitable> Clone for BfsIter<'a, G> where Bfs<G::NodeId, G::Map>: Clone
{
    fn clone(&self) -> Self {
        BfsIter {
            graph: self.graph,
            bfs: self.bfs.clone(),
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wlroots;

use std::{thread, process::Command};

use wlroots::{area::{Area, Origin, Size},
              compositor,
              cursor::{self, Cursor, xcursor},
              input::{self, keyboard, pointer},
              output::{self, layout::Layout},
              render::{matrix, Renderer},
              seat::{self, Seat},
              shell::xdg_shell_v6,
              surface,
              utils::{log::{init_logging, WLR_DEBUG}, current_time}};
use wlroots::wlroots_sys::wlr_key_state::WLR_KEY_PRESSED;
use wlroots::xkbcommon::xkb::keysyms::{KEY_Escape, KEY_F1};
use wlroots::wlroots_dehandle;

struct State {
    xcursor_manager: xcursor::Manager,
    keyboard: Option<keyboard::Handle>,
    layout: output::layout::Handle,
    cursor: cursor::Handle,
    shells: Vec<xdg_shell_v6::Handle>,
    seat_handle: Option<seat::Handle>
}

impl State {
    fn new(xcursor_manager: xcursor::Manager,
           layout: output::layout::Handle,
           cursor: cursor::Handle)
           -> Self {
        State { xcursor_manager,
                layout,
                cursor,
                keyboard: None,
                seat_handle: None,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

struct CursorEx;

impl cursor::Handler for CursorEx {}

impl seat::Handler for SeatHandlerEx {}

struct XdgV6ShellHandlerEx;
struct XdgV6ShellManager;
struct OutputLayoutEx;

impl output::layout::Handler for OutputLayoutEx {}

impl xdg_shell_v6::Handler for XdgV6ShellHandlerEx {
    fn destroyed(&mut self, compositor: compositor::Handle, shell: xdg_shell_v6::Handle) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let weak = shell;
            if let Some(index) = state.shells.iter().position(|s| *s == weak) {
                state.shells.remove(index);
            }
        }).unwrap();
    }
}

struct SurfaceEx;

impl surface::Handler for SurfaceEx {
    fn on_commit(&mut self, _: compositor::Handle, surface: surface::Handle) {
        wlr_log!(WLR_DEBUG, "Commiting for surface {:?}", surface);
    }
}

impl xdg_shell_v6::ManagerHandler for XdgV6ShellManager {
    #[wlroots_dehandle(compositor, shell, layout, output)]
    fn new_surface(&mut self,
                   compositor: compositor::Handle,
                   shell: xdg_shell_v6::Handle)
                   -> (Option<Box<xdg_shell_v6::Handler>>, Option<Box<surface::Handler>>) {
        {
            use compositor as compositor;
            use shell as shell;
            shell.ping();
            let state: &mut State = compositor.into();
            state.shells.push(shell.weak_reference());
            let layout_handle = &state.layout;
            use layout_handle as layout;
            for (output, _) in layout.outputs() {
                use output as output;
                output.schedule_frame()
            }
        }
        (Some(Box::new(XdgV6ShellHandlerEx)), Some(Box::new(SurfaceEx)))
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl output::ManagerHandler for OutputManager {
    #[wlroots_dehandle(compositor, output, layout, cursor)]
    fn output_added<'output>(&mut self,
                             compositor: compositor::Handle,
                             builder: output::Builder<'output>)
                             -> Option<output::BuilderResult<'output>> {
        let result = builder.build_best_mode(ExOutput);
        {
            let output_handle = &result.output;
            use compositor as compositor;
            use output_handle as output;
            let state: &mut State = compositor.data.downcast_mut().unwrap();
            let xcursor_manager = &mut state.xcursor_manager;
            // TODO use output config if present instead of auto
            let layout = &mut state.layout;
            let cursor = &mut state.cursor;
            use layout as layout;
            use cursor as cursor;
            layout.add_auto(output);
            cursor.attach_output_layout(layout);
            xcursor_manager.load(output.scale());
            xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
            let (x, y) = cursor.coords();
            // https://en.wikipedia.org/wiki/Mouse_warping
            cursor.warp(None, x, y);
        }
        Some(result)
    }
}

impl keyboard::Handler for ExKeyboardHandler {
    #[wlroots_dehandle(compositor, seat)]
    fn on_key(&mut self,
              compositor_handle: compositor::Handle,
              _: keyboard::Handle,
              key_event: &keyboard::event::Key) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor::terminate();
            } else if key_event.key_state() == WLR_KEY_PRESSED {
                if key == KEY_F1 {
                    thread::spawn(move || {
                        Command::new("weston-terminal").output().unwrap();
                    });
                    return
                }
            }
        };
        use compositor_handle as compositor;
        let state: &mut State = compositor.into();
        let seat_handle = state.seat_handle.clone().unwrap();
        use seat_handle as seat;
        seat.keyboard_notify_key(key_event.time_msec(),
                                    key_event.keycode(),
                                    key_event.key_state() as u32);
    }
}

impl pointer::Handler for ExPointer {
    #[wlroots_dehandle(compositor, cursor)]
    fn on_motion_absolute(&mut self,
                          compositor: compositor::Handle,
                          _: pointer::Handle,
                          event: &pointer::event::AbsoluteMotion) {
        use compositor as compositor;
        let state: &mut State = compositor.into();
        let (x, y) = event.pos();
        let cursor_handle = &state.cursor;
        use cursor_handle as cursor;
        cursor.warp_absolute(event.device(), x, y)
    }

    #[wlroots_dehandle(compositor, cursor)]
    fn on_motion(&mut self,
                 compositor: compositor::Handle,
                 _: pointer::Handle,
                 event: &pointer::event::Motion) {
        use compositor as compositor;
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        let cursor_handle = &state.cursor;
        use cursor_handle as cursor;
        cursor.move_to(event.device(), delta_x, delta_y)
    }

    #[wlroots_dehandle(compositor, shell, seat, keyboard, surface)]
    fn on_button(&mut self,
                 compositor: compositor::Handle, _:
                 pointer::Handle,
                 _: &pointer::event::Button) {
        use compositor as compositor;
        let state: &mut State = compositor.into();
        let seat = state.seat_handle.clone().unwrap();
        let keyboard = state.keyboard.clone().unwrap();
        let shell_handle = &state.shells[0];
        use shell_handle as shell;
        match shell.state() {
            Some(&mut xdg_shell_v6::ShellState::TopLevel(ref mut toplevel)) => {
                toplevel.set_activated(true);
            }
            _ => {}
        };
        let surface = shell.surface();
        use seat as seat;
        use keyboard as keyboard;
        use surface as surface;
        seat.set_keyboard(keyboard.input_device());
        seat.keyboard_notify_enter(surface,
                                   &mut keyboard.keycodes(),
                                   &mut keyboard.get_modifier_masks())
    }
}

impl output::Handler for ExOutput {
    #[wlroots_dehandle(compositor, output)]
    fn on_frame(&mut self, compositor: compositor::Handle, output: output::Handle) {
        use compositor as compositor;
        use output as output;
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        let renderer = compositor.renderer
            .as_mut()
            .expect("Compositor was not loaded with a renderer");
        let mut render_context = renderer.render(output, None);
        render_context.clear([0.25, 0.25, 0.25, 1.0]);
        render_shells(state, &mut render_context)
    }
}

impl input::ManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: compositor::Handle,
                     _: pointer::Handle)
                     -> Option<Box<pointer::Handler>> {
        Some(Box::new(ExPointer))
    }

    #[wlroots_dehandle(compositor, keyboard, seat)]
    fn keyboard_added(&mut self,
                      compositor: compositor::Handle,
                      keyboard: keyboard::Handle)
                      -> Option<Box<keyboard::Handler>> {
        {
            use compositor as compositor;
            use keyboard as keyboard;
            let state: &mut State = compositor.into();
            state.keyboard = Some(keyboard.weak_reference());
            let seat_handle = state.seat_handle.as_ref().unwrap();
            use seat_handle as seat;
            seat.set_keyboard(keyboard.input_device());
        }
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(WLR_DEBUG, None);
    let cursor = Cursor::create(Box::new(CursorEx));
    let mut xcursor_manager =
        xcursor::Manager::create("default".to_string(), 24).expect("Could not create xcursor \
                                                                  manager");
    xcursor_manager.load(1.0);
    cursor.run(|c| xcursor_manager.set_cursor_image("left_ptr".to_string(), c))
          .unwrap();
    let layout = Layout::create(Box::new(OutputLayoutEx));

    let mut compositor =
        compositor::Builder::new().gles2(true)
                                  .input_manager(Box::new(InputManager))
                                  .output_manager(Box::new(OutputManager))
                                  .xdg_shell_v6_manager(Box::new(XdgV6ShellManager))
                                  .build_auto(State::new(xcursor_manager, layout, cursor));

    {
        let seat_handle =
            Seat::create(&mut compositor, "seat0".into(), Box::new(SeatHandlerEx));
        seat_handle.run(|seat| {
                            seat.set_capabilities(seat::Capability::all());
                        })
                   .unwrap();
        let state: &mut State = (&mut compositor).into();
        state.seat_handle = Some(seat_handle);
    }
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
#[wlroots_dehandle(shell, surface, layout)]
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    let layout_handle = &state.layout;
    for mut shell in shells {
        use shell as shell;
        let surface_handle = shell.surface();
        use surface_handle as surface;
        use layout_handle as layout;
        let (width, height) = surface.current_state().size();
        let (render_width, render_height) =
            (width * renderer.output.scale() as i32,
             height * renderer.output.scale() as i32);
        let (lx, ly) = (0.0, 0.0);
        let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                   Size::new(render_width,
                                             render_height));
        if layout.intersects(renderer.output, render_box) {
            let transform = renderer.output.get_transform().invert();
            let matrix = matrix::project_box(render_box,
                                             transform,
                                             0.0,
                                             renderer.output
                                             .transform_matrix());
            if let Some(texture) = surface.texture().as_ref() {
                renderer.render_texture_with_matrix(texture, matrix);
            }
            surface.send_frame_done(current_time());
        }
    }
}
<commit_msg>Import handleable<commit_after>#[macro_use]
extern crate wlroots;

use std::{thread, process::Command};

use wlroots::{area::{Area, Origin, Size},
              compositor,
              cursor::{self, Cursor, xcursor},
              input::{self, keyboard, pointer},
              output::{self, layout::Layout},
              render::{matrix, Renderer},
              seat::{self, Seat},
              shell::xdg_shell_v6,
              surface,
              utils::{Handleable, log::{init_logging, WLR_DEBUG}, current_time}};
use wlroots::wlroots_sys::wlr_key_state::WLR_KEY_PRESSED;
use wlroots::xkbcommon::xkb::keysyms::{KEY_Escape, KEY_F1};
use wlroots::wlroots_dehandle;

struct State {
    xcursor_manager: xcursor::Manager,
    keyboard: Option<keyboard::Handle>,
    layout: output::layout::Handle,
    cursor: cursor::Handle,
    shells: Vec<xdg_shell_v6::Handle>,
    seat_handle: Option<seat::Handle>
}

impl State {
    fn new(xcursor_manager: xcursor::Manager,
           layout: output::layout::Handle,
           cursor: cursor::Handle)
           -> Self {
        State { xcursor_manager,
                layout,
                cursor,
                keyboard: None,
                seat_handle: None,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

struct CursorEx;

impl cursor::Handler for CursorEx {}

impl seat::Handler for SeatHandlerEx {}

struct XdgV6ShellHandlerEx;
struct XdgV6ShellManager;
struct OutputLayoutEx;

impl output::layout::Handler for OutputLayoutEx {}

impl xdg_shell_v6::Handler for XdgV6ShellHandlerEx {
    fn destroyed(&mut self, compositor: compositor::Handle, shell: xdg_shell_v6::Handle) {
        with_handles!([(compositor: {compositor})] => {
            let state: &mut State = compositor.into();
            let weak = shell;
            if let Some(index) = state.shells.iter().position(|s| *s == weak) {
                state.shells.remove(index);
            }
        }).unwrap();
    }
}

struct SurfaceEx;

impl surface::Handler for SurfaceEx {
    fn on_commit(&mut self, _: compositor::Handle, surface: surface::Handle) {
        wlr_log!(WLR_DEBUG, "Commiting for surface {:?}", surface);
    }
}

impl xdg_shell_v6::ManagerHandler for XdgV6ShellManager {
    #[wlroots_dehandle(compositor, shell, layout, output)]
    fn new_surface(&mut self,
                   compositor: compositor::Handle,
                   shell: xdg_shell_v6::Handle)
                   -> (Option<Box<xdg_shell_v6::Handler>>, Option<Box<surface::Handler>>) {
        {
            use compositor as compositor;
            use shell as shell;
            shell.ping();
            let state: &mut State = compositor.into();
            state.shells.push(shell.weak_reference());
            let layout_handle = &state.layout;
            use layout_handle as layout;
            for (output, _) in layout.outputs() {
                use output as output;
                output.schedule_frame()
            }
        }
        (Some(Box::new(XdgV6ShellHandlerEx)), Some(Box::new(SurfaceEx)))
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl output::ManagerHandler for OutputManager {
    #[wlroots_dehandle(compositor, output, layout, cursor)]
    fn output_added<'output>(&mut self,
                             compositor: compositor::Handle,
                             builder: output::Builder<'output>)
                             -> Option<output::BuilderResult<'output>> {
        let result = builder.build_best_mode(ExOutput);
        {
            let output_handle = &result.output;
            use compositor as compositor;
            use output_handle as output;
            let state: &mut State = compositor.data.downcast_mut().unwrap();
            let xcursor_manager = &mut state.xcursor_manager;
            // TODO use output config if present instead of auto
            let layout = &mut state.layout;
            let cursor = &mut state.cursor;
            use layout as layout;
            use cursor as cursor;
            layout.add_auto(output);
            cursor.attach_output_layout(layout);
            xcursor_manager.load(output.scale());
            xcursor_manager.set_cursor_image("left_ptr".to_string(), cursor);
            let (x, y) = cursor.coords();
            // https://en.wikipedia.org/wiki/Mouse_warping
            cursor.warp(None, x, y);
        }
        Some(result)
    }
}

impl keyboard::Handler for ExKeyboardHandler {
    #[wlroots_dehandle(compositor, seat)]
    fn on_key(&mut self,
              compositor_handle: compositor::Handle,
              _: keyboard::Handle,
              key_event: &keyboard::event::Key) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor::terminate();
            } else if key_event.key_state() == WLR_KEY_PRESSED {
                if key == KEY_F1 {
                    thread::spawn(move || {
                        Command::new("weston-terminal").output().unwrap();
                    });
                    return
                }
            }
        };
        use compositor_handle as compositor;
        let state: &mut State = compositor.into();
        let seat_handle = state.seat_handle.clone().unwrap();
        use seat_handle as seat;
        seat.keyboard_notify_key(key_event.time_msec(),
                                    key_event.keycode(),
                                    key_event.key_state() as u32);
    }
}

impl pointer::Handler for ExPointer {
    #[wlroots_dehandle(compositor, cursor)]
    fn on_motion_absolute(&mut self,
                          compositor: compositor::Handle,
                          _: pointer::Handle,
                          event: &pointer::event::AbsoluteMotion) {
        use compositor as compositor;
        let state: &mut State = compositor.into();
        let (x, y) = event.pos();
        let cursor_handle = &state.cursor;
        use cursor_handle as cursor;
        cursor.warp_absolute(event.device(), x, y)
    }

    #[wlroots_dehandle(compositor, cursor)]
    fn on_motion(&mut self,
                 compositor: compositor::Handle,
                 _: pointer::Handle,
                 event: &pointer::event::Motion) {
        use compositor as compositor;
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        let cursor_handle = &state.cursor;
        use cursor_handle as cursor;
        cursor.move_to(event.device(), delta_x, delta_y)
    }

    #[wlroots_dehandle(compositor, shell, seat, keyboard, surface)]
    fn on_button(&mut self,
                 compositor: compositor::Handle, _:
                 pointer::Handle,
                 _: &pointer::event::Button) {
        use compositor as compositor;
        let state: &mut State = compositor.into();
        let seat = state.seat_handle.clone().unwrap();
        let keyboard = state.keyboard.clone().unwrap();
        let shell_handle = &state.shells[0];
        use shell_handle as shell;
        match shell.state() {
            Some(&mut xdg_shell_v6::ShellState::TopLevel(ref mut toplevel)) => {
                toplevel.set_activated(true);
            }
            _ => {}
        };
        let surface = shell.surface();
        use seat as seat;
        use keyboard as keyboard;
        use surface as surface;
        seat.set_keyboard(keyboard.input_device());
        seat.keyboard_notify_enter(surface,
                                   &mut keyboard.keycodes(),
                                   &mut keyboard.get_modifier_masks())
    }
}

impl output::Handler for ExOutput {
    #[wlroots_dehandle(compositor, output)]
    fn on_frame(&mut self, compositor: compositor::Handle, output: output::Handle) {
        use compositor as compositor;
        use output as output;
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        let renderer = compositor.renderer
            .as_mut()
            .expect("Compositor was not loaded with a renderer");
        let mut render_context = renderer.render(output, None);
        render_context.clear([0.25, 0.25, 0.25, 1.0]);
        render_shells(state, &mut render_context)
    }
}

impl input::ManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: compositor::Handle,
                     _: pointer::Handle)
                     -> Option<Box<pointer::Handler>> {
        Some(Box::new(ExPointer))
    }

    #[wlroots_dehandle(compositor, keyboard, seat)]
    fn keyboard_added(&mut self,
                      compositor: compositor::Handle,
                      keyboard: keyboard::Handle)
                      -> Option<Box<keyboard::Handler>> {
        {
            use compositor as compositor;
            use keyboard as keyboard;
            let state: &mut State = compositor.into();
            state.keyboard = Some(keyboard.weak_reference());
            let seat_handle = state.seat_handle.as_ref().unwrap();
            use seat_handle as seat;
            seat.set_keyboard(keyboard.input_device());
        }
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(WLR_DEBUG, None);
    let cursor = Cursor::create(Box::new(CursorEx));
    let mut xcursor_manager =
        xcursor::Manager::create("default".to_string(), 24).expect("Could not create xcursor \
                                                                  manager");
    xcursor_manager.load(1.0);
    cursor.run(|c| xcursor_manager.set_cursor_image("left_ptr".to_string(), c))
          .unwrap();
    let layout = Layout::create(Box::new(OutputLayoutEx));

    let mut compositor =
        compositor::Builder::new().gles2(true)
                                  .input_manager(Box::new(InputManager))
                                  .output_manager(Box::new(OutputManager))
                                  .xdg_shell_v6_manager(Box::new(XdgV6ShellManager))
                                  .build_auto(State::new(xcursor_manager, layout, cursor));

    {
        let seat_handle =
            Seat::create(&mut compositor, "seat0".into(), Box::new(SeatHandlerEx));
        seat_handle.run(|seat| {
                            seat.set_capabilities(seat::Capability::all());
                        })
                   .unwrap();
        let state: &mut State = (&mut compositor).into();
        state.seat_handle = Some(seat_handle);
    }
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
#[wlroots_dehandle(shell, surface, layout)]
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    let layout_handle = &state.layout;
    for mut shell in shells {
        use shell as shell;
        let surface_handle = shell.surface();
        use surface_handle as surface;
        use layout_handle as layout;
        let (width, height) = surface.current_state().size();
        let (render_width, render_height) =
            (width * renderer.output.scale() as i32,
             height * renderer.output.scale() as i32);
        let (lx, ly) = (0.0, 0.0);
        let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                   Size::new(render_width,
                                             render_height));
        if layout.intersects(renderer.output, render_box) {
            let transform = renderer.output.get_transform().invert();
            let matrix = matrix::project_box(render_box,
                                             transform,
                                             0.0,
                                             renderer.output
                                             .transform_matrix());
            if let Some(texture) = surface.texture().as_ref() {
                renderer.render_texture_with_matrix(texture, matrix);
            }
            surface.send_frame_done(current_time());
        }
    }
}
<|endoftext|>


<commit_before>const DATA: &'static str = include_str!("../data/input_6.txt");

pub fn main() -> Vec<String> {
    let s1 = light_show(DATA);
    let s2 = bright_show(DATA);
    vec![s1.to_string(), s2.to_string()]
}

fn doit<F, L>(f: F, state: &mut [[L; 1000]; 1000], a: (usize, usize), b: (usize, usize))
    where F: Fn(&mut L)
{
    for x in a.0..(b.0 + 1) {
        for y in a.1..(b.1 + 1) {
            f(&mut state[x][y]);
        }
    }
}

fn light_show(input: &str) -> usize {
    let mut state = box [[false; 1000]; 1000];

    let on = |light: &mut bool| *light = true;
    let off = |light: &mut bool| *light = false;
    let toggle = |light: &mut bool| *light = !*light;

    for line in input.lines() {
        let mut words = line.split_whitespace();

        let f: &(Fn(&mut bool)) = match words.next() {
            Some("turn") => {
                match words.next() {
                    Some("on") => &on,
                    Some("off") => &off,
                    _ => panic!("bad input"),
                }
            }
            Some("toggle") => &toggle,
            _ => panic!("bad input"),
        };

        if let (Some(a), Some(b), Some(c), Some(d)) = scan_fmt!(&words.collect::<String>(),
                                                                "{d},{d} through {d},{d}",
                                                                usize,
                                                                usize,
                                                                usize,
                                                                usize) {
            doit(f, &mut state, (a, b), (c, d));
        } else {
            panic!("bad input");
        }
    }
    state.iter()
         .flat_map(|inner| inner.iter())
         .filter(|&&on| on == true)
         .count()
}

fn bright_show(input: &str) -> u32 {
    let mut state = box [[0u32; 1000]; 1000];

    let on = |light: &mut u32| *light += 1;
    let off = |light: &mut u32| {
        if *light > 0 {
            *light -= 1
        }
    };
    let toggle = |light: &mut u32| *light += 2;

    for line in input.lines() {
        let mut words = line.split_whitespace();

        let f: &(Fn(&mut u32)) = match words.next() {
            Some("turn") => {
                match words.next() {
                    Some("on") => &on,
                    Some("off") => &off,
                    _ => panic!("bad input"),
                }
            }
            Some("toggle") => &toggle,
            _ => panic!("bad input"),
        };

        if let (Some(a), Some(b), Some(c), Some(d)) = scan_fmt!(&words.collect::<String>(),
                                                                "{d},{d} through {d},{d}",
                                                                usize,
                                                                usize,
                                                                usize,
                                                                usize) {
            doit(f, &mut state, (a, b), (c, d));
        } else {
            panic!("bad input");
        }
    }
    state.iter()
         .flat_map(|inner| inner.iter())
         .sum()
}

#[cfg(test)]
mod test {
    use super::{light_show, bright_show};

    #[test]
    fn test_light_show() {
        assert_eq!(light_show("turn on 0,0 through 999,999"), 1000 * 1000);
        assert_eq!(light_show("toggle 0,0 through 999,0"), 1000);
        assert_eq!(light_show("turn off 499,499 through 500,500"), 0);
    }

    #[test]
    fn test_bright_show() {
        assert_eq!(bright_show("turn on 0,0 through 0,0"), 1);
        assert_eq!(bright_show("toggle 0,0 through 999,999"), 2 * 1000 * 1000);
    }
}
<commit_msg>day06: try and share as much as possible from part 1 to 2<commit_after>const DATA: &'static str = include_str!("../data/input_6.txt");

pub fn main() -> Vec<String> {
    let s1 = light_show(DATA);
    let s2 = bright_show(DATA);
    vec![s1.to_string(), s2.to_string()]
}

fn doit<F, L>(f: F, state: &mut [[L; 1000]; 1000], a: (usize, usize), b: (usize, usize))
    where F: Fn(&mut L)
{
    for x in a.0..(b.0 + 1) {
        for y in a.1..(b.1 + 1) {
            f(&mut state[x][y]);
        }
    }
}

fn parse_input_line<'a, L>(line: &str,
                           on: &'a Fn(&mut L),
                           off: &'a Fn(&mut L),
                           toggle: &'a Fn(&mut L))
                           -> Box<Fn(&mut [[L; 1000]; 1000]) + 'a> {
    let mut words = line.split_whitespace();

    let f: (&Fn(&mut L)) = match words.next() {
        Some("turn") => {
            match words.next() {
                Some("on") => on,
                Some("off") => off,
                _ => panic!("bad input"),
            }
        }
        Some("toggle") => toggle,
        _ => panic!("bad input"),
    };

    if let (Some(a), Some(b), Some(c), Some(d)) = scan_fmt!(&words.collect::<String>(),
                                                            "{d},{d} through {d},{d}",
                                                            usize,
                                                            usize,
                                                            usize,
                                                            usize) {
        box move |state| doit(f, state, (a, b), (c, d))
    } else {
        panic!("bad input");
    }
}

fn light_show(input: &str) -> usize {
    let mut state = box [[false; 1000]; 1000];

    let on = |light: &mut bool| *light = true;
    let off = |light: &mut bool| *light = false;
    let toggle = |light: &mut bool| *light = !*light;

    for line in input.lines() {
        let f = parse_input_line(line, &on, &off, &toggle);
        f(&mut state);
    }
    state.iter()
         .flat_map(|inner| inner.iter())
         .filter(|&&on| on == true)
         .count()
}

fn bright_show(input: &str) -> u32 {
    let mut state = box [[0u32; 1000]; 1000];

    let on = |light: &mut u32| *light += 1;
    let off = |light: &mut u32| {
        if *light > 0 {
            *light -= 1
        }
    };
    let toggle = |light: &mut u32| *light += 2;

    for line in input.lines() {
        let f = parse_input_line(line, &on, &off, &toggle);
        f(&mut state);
    }
    state.iter()
         .flat_map(|inner| inner.iter())
         .sum()
}

#[cfg(test)]
mod test {
    use super::{light_show, bright_show};

    #[test]
    fn test_light_show() {
        assert_eq!(light_show("turn on 0,0 through 999,999"), 1000 * 1000);
        assert_eq!(light_show("toggle 0,0 through 999,0"), 1000);
        assert_eq!(light_show("turn off 499,499 through 500,500"), 0);
    }

    #[test]
    fn test_bright_show() {
        assert_eq!(bright_show("turn on 0,0 through 0,0"), 1);
        assert_eq!(bright_show("toggle 0,0 through 999,999"), 2 * 1000 * 1000);
    }
}
<|endoftext|>