<commit_before>use rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use std::fmt;

#[derive(Clone, Debug)]
pub struct UserID {
    pub nickname: String,
    pub homeserver: String
}

impl UserID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        UserID {
            nickname: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RoomID {
    pub id: String,
    pub homeserver: String
}

impl fmt::Display for RoomID {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "!{}:{}", self.id, self.homeserver)
    }
}

impl RoomID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        RoomID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Debug)]
pub enum MembershipAction {
    Join
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases,
    Message(UserID, String),
    PowerLevels
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<UserID>,
    pub room: RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent)
}

impl EventData {
    pub fn type_str(&self) -> &'static str {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) => {
                "m.room.message"
            },
            _ => unreachable!()
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref id, ref evt) => {
                match evt {
                    &RoomEvent::Message(ref sender, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => unreachable!()
                }
            },
            _ => unreachable!()
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<String>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").trim().split(".").collect();
        assert!(tokens[0] == "m");
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(i.as_string().unwrap().to_string()),
            None => None
        };
        Event {
            id: id,
            data: match tokens[1] {
                "room" =>
                    Self::from_room_json(tokens[2], json),
                "typing" =>
                    EventData::Typing(TypingEvent {
                        users: vec![],
                        room: RoomID::from_str(mjson::string(json, "room_id"))
                    }),
                "presence" =>
                    EventData::Presence(PresenceEvent{
                        presence: mjson::string(json, "content.presence").to_string(),
                        user: UserID::from_str(mjson::string(json, "content.user_id"))
                    }),
                e => panic!("Unknown event {:?}!\nRaw JSON: {:?}", e, json)
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {
        EventData::Room(
            RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" =>
                    RoomEvent::JoinRules(mjson::string(json, "content.join_rule").to_string()),
                "member" =>
                    RoomEvent::Membership(UserID::from_str(mjson::string(json, "user_id")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" =>
                    RoomEvent::Aliases,
                "power_levels" =>
                    RoomEvent::PowerLevels,
                e => panic!("Unknown room event {:?}: {:?}", e, json)
            }
        )
    }
}
<commit_msg>matrix: events: parse message events<commit_after>use rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use std::fmt;

#[derive(Clone, Debug)]
pub struct UserID {
    pub nickname: String,
    pub homeserver: String
}

impl UserID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        UserID {
            nickname: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RoomID {
    pub id: String,
    pub homeserver: String
}

impl fmt::Display for RoomID {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "!{}:{}", self.id, self.homeserver)
    }
}

impl RoomID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        RoomID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Debug)]
pub enum MembershipAction {
    Join
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases,
    Message(UserID, String),
    PowerLevels
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<UserID>,
    pub room: RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent)
}

impl EventData {
    pub fn type_str(&self) -> &'static str {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) => {
                "m.room.message"
            },
            _ => unreachable!()
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref id, ref evt) => {
                match evt {
                    &RoomEvent::Message(ref sender, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => unreachable!()
                }
            },
            _ => unreachable!()
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<String>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").trim().split(".").collect();
        assert!(tokens[0] == "m");
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(i.as_string().unwrap().to_string()),
            None => None
        };
        Event {
            id: id,
            data: match tokens[1] {
                "room" =>
                    Self::from_room_json(tokens[2], json),
                "typing" =>
                    EventData::Typing(TypingEvent {
                        users: vec![],
                        room: RoomID::from_str(mjson::string(json, "room_id"))
                    }),
                "presence" =>
                    EventData::Presence(PresenceEvent{
                        presence: mjson::string(json, "content.presence").to_string(),
                        user: UserID::from_str(mjson::string(json, "content.user_id"))
                    }),
                e => panic!("Unknown event {:?}!\nRaw JSON: {:?}", e, json)
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {
        EventData::Room(
            RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" =>
                    RoomEvent::JoinRules(mjson::string(json, "content.join_rule").to_string()),
                "member" =>
                    RoomEvent::Membership(UserID::from_str(mjson::string(json, "user_id")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" =>
                    RoomEvent::Aliases,
                "power_levels" =>
                    RoomEvent::PowerLevels,
                "message" =>
                    RoomEvent::Message(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.body").to_string()),
                e => panic!("Unknown room event {:?}: {:?}", e, json)
            }
        )
    }
}
<|endoftext|>


<commit_before>//
// GLSL Mathematics for Rust.
//
// Copyright (c) 2015 The glm-rs authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use basenum::{ BaseNum, BaseInt, BaseFloat, SignedNum, ApproxEq };
use std::ops::{ Add, Mul, Sub, Div, Rem, Not, BitAnd, BitOr, BitXor, Shl, Shr };
use rand::Rand;
use num::{ Float, One, Zero };

// TODO: use associated types to reduce redundant type parameters.

/// Generic numeric type.
pub trait GenNum<E: BaseNum>
: Copy
+ Sized
+ Clone
+ One
+ Zero
+ Div<Self, Output = Self>
+ Rem<Self, Output = Self>
+ Add<E, Output = Self>
+ Mul<E, Output = Self>
+ Rand
{
    /// Constructs from a scalar number.
    fn from_s(x: E) -> Self;

    fn map<F>(self, f: F) -> Self where F: Fn(E) -> E;

    fn zip<F>(self, y: Self, f: F) -> Self where F: Fn(E, E) -> E;

    fn split<F>(self, f: F) -> (Self, Self) where F: Fn(E) -> (E, E);

    fn map2<F>(self, y: Self, f: F) -> (Self, Self) where F: Fn(E, E) -> (E, E);
}

macro_rules! impl_GenNum_for_scalar(
    ($t: ty) => {
        impl GenNum<$t> for $t {
            #[inline(always)]
            fn from_s(x: $t) -> Self {
                x
            }
            #[inline(always)]
            fn map<F: Fn($t) -> $t>(self, f: F) -> $t {
                f(self)
            }
            #[inline(always)]
            fn zip<F: Fn($t, $t) -> $t>(self, y: $t, f: F) -> $t {
                f(self, y)
            }
            #[inline(always)]
            fn split<F: Fn($t) -> ($t, $t)>(self, f: F) -> ($t, $t) {
                f(self)
            }
            #[inline(always)]
            fn map2<F: Fn($t, $t) -> ($t, $t)>(self, y: $t, f: F) -> ($t, $t) {
                f(self, y)
            }
        }
    }
);

/// Generic interger type.
pub trait GenInt<I: BaseInt>
: GenNum<I>
+ Eq
+ Not<Output = Self>
+ BitAnd<Output = Self>
+ BitOr<Output = Self>
+ BitXor<Output = Self>
+ Shl<usize, Output = Self>
+ Shr<usize, Output = Self>
{}

/// Generic signed integer type.
///
/// # Note
///
/// Only 32-bit integer is used in GLSL.
pub trait GenIType: GenInt<i32> + SignedNum + Sub<i32, Output = Self> {}

impl_GenNum_for_scalar! { i32 }
impl GenInt<i32> for i32 {}
impl GenIType for i32 {}

/// Generic unsigned integer type.
///
/// # Note
///
/// Only 32-bit unsigned integer is used in GLSL.
pub trait GenUType: GenInt<u32> {}

impl_GenNum_for_scalar! { u32 }
impl GenInt<u32> for u32 {}
impl GenUType for u32 {}

/// Generic float number type.
pub trait GenFloat<F: BaseFloat>
: GenNum<F>
+ ApproxEq<BaseType = F>
+ SignedNum
+ Sub<F, Output = Self>
{
    /// Computes and returns `a * b + c`.
    fn fma(&self, b: &Self, c: &Self) -> Self;
}

pub trait GenType: GenFloat<f32> {}
pub trait GenDType: GenFloat<f64> {}

macro_rules! impl_GenFloat_for_scalar(
    ($t: ty, $gt: ty) => {
        impl_GenNum_for_scalar! { $t }
        impl GenFloat<$t> for $t {
            fn fma(&self, b: &$t, c: &$t) -> $t {
                Float::mul_add(*self, *b, *c)
            }
        }
        impl $gt for $t {}
    }
);

impl_GenFloat_for_scalar! { f32, GenType }
impl_GenFloat_for_scalar! { f64, GenDType }

/// Generic boolean type.
pub trait GenBType: Eq {}

impl GenBType for bool {}
<commit_msg>Don't use types as traits in macros<commit_after>//
// GLSL Mathematics for Rust.
//
// Copyright (c) 2015 The glm-rs authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use basenum::{ BaseNum, BaseInt, BaseFloat, SignedNum, ApproxEq };
use std::ops::{ Add, Mul, Sub, Div, Rem, Not, BitAnd, BitOr, BitXor, Shl, Shr };
use rand::Rand;
use num::{ Float, One, Zero };

// TODO: use associated types to reduce redundant type parameters.

/// Generic numeric type.
pub trait GenNum<E: BaseNum>
: Copy
+ Sized
+ Clone
+ One
+ Zero
+ Div<Self, Output = Self>
+ Rem<Self, Output = Self>
+ Add<E, Output = Self>
+ Mul<E, Output = Self>
+ Rand
{
    /// Constructs from a scalar number.
    fn from_s(x: E) -> Self;

    fn map<F>(self, f: F) -> Self where F: Fn(E) -> E;

    fn zip<F>(self, y: Self, f: F) -> Self where F: Fn(E, E) -> E;

    fn split<F>(self, f: F) -> (Self, Self) where F: Fn(E) -> (E, E);

    fn map2<F>(self, y: Self, f: F) -> (Self, Self) where F: Fn(E, E) -> (E, E);
}

macro_rules! impl_GenNum_for_scalar(
    ($t: ty) => {
        impl GenNum<$t> for $t {
            #[inline(always)]
            fn from_s(x: $t) -> Self {
                x
            }
            #[inline(always)]
            fn map<F: Fn($t) -> $t>(self, f: F) -> $t {
                f(self)
            }
            #[inline(always)]
            fn zip<F: Fn($t, $t) -> $t>(self, y: $t, f: F) -> $t {
                f(self, y)
            }
            #[inline(always)]
            fn split<F: Fn($t) -> ($t, $t)>(self, f: F) -> ($t, $t) {
                f(self)
            }
            #[inline(always)]
            fn map2<F: Fn($t, $t) -> ($t, $t)>(self, y: $t, f: F) -> ($t, $t) {
                f(self, y)
            }
        }
    }
);

/// Generic interger type.
pub trait GenInt<I: BaseInt>
: GenNum<I>
+ Eq
+ Not<Output = Self>
+ BitAnd<Output = Self>
+ BitOr<Output = Self>
+ BitXor<Output = Self>
+ Shl<usize, Output = Self>
+ Shr<usize, Output = Self>
{}

/// Generic signed integer type.
///
/// # Note
///
/// Only 32-bit integer is used in GLSL.
pub trait GenIType: GenInt<i32> + SignedNum + Sub<i32, Output = Self> {}

impl_GenNum_for_scalar! { i32 }
impl GenInt<i32> for i32 {}
impl GenIType for i32 {}

/// Generic unsigned integer type.
///
/// # Note
///
/// Only 32-bit unsigned integer is used in GLSL.
pub trait GenUType: GenInt<u32> {}

impl_GenNum_for_scalar! { u32 }
impl GenInt<u32> for u32 {}
impl GenUType for u32 {}

/// Generic float number type.
pub trait GenFloat<F: BaseFloat>
: GenNum<F>
+ ApproxEq<BaseType = F>
+ SignedNum
+ Sub<F, Output = Self>
{
    /// Computes and returns `a * b + c`.
    fn fma(&self, b: &Self, c: &Self) -> Self;
}

pub trait GenType: GenFloat<f32> {}
pub trait GenDType: GenFloat<f64> {}

macro_rules! impl_GenFloat_for_scalar(
    ($t: ty, $gt: path) => {
        impl_GenNum_for_scalar! { $t }
        impl GenFloat<$t> for $t {
            fn fma(&self, b: &$t, c: &$t) -> $t {
                Float::mul_add(*self, *b, *c)
            }
        }
        impl $gt for $t {}
    }
);

impl_GenFloat_for_scalar! { f32, GenType }
impl_GenFloat_for_scalar! { f64, GenDType }

/// Generic boolean type.
pub trait GenBType: Eq {}

impl GenBType for bool {}
<|endoftext|>


<commit_before>use js_types::js_type::{JsT, JsType, Marking};
use std::vec::Vec;
use std::collections::hash_set::HashSet;
use std::collections::hash_map::HashMap;
use std::collections::vec_deque::VecDeque;
use uuid::Uuid;

/// A map from uuids to references to objects. The interface to the garbage
/// collector, this map gets updated whenever a GC cycle is performed. References
/// that are no longer live may be dropped from the map.
pub struct UuidMap<'t> {
    inner: HashMap<Uuid, RefCell<JsT>>,
}

impl<'t> UuidMap<'t> {
    pub fn new() -> UuidMap<'t> {
        UuidMap {
            inner: HashMap::new(),
        }
    }

    pub fn from_jsts(jsts: Vec<&'t JsT>) -> UuidMap<'t> {
        let mut tmp_map = HashMap::new();
        jsts.iter().map(|j| tmp_map.insert(j.uuid, *j));
        UuidMap {
            inner: tmp_map,
        }
    }

    pub fn insert_ref(&mut self, jst: &'t JsT) {
        self.inner.insert(jst.uuid, jst);
    }

    pub fn drop_uuid(&mut self, uuid: Uuid) {
        self.inner.remove(&uuid);
    }

    pub fn drop_ref(&mut self, jst: &'t JsT) {
        self.inner.remove(&jst.uuid);
    }

    pub fn mark_uuid(&mut self, uuid: Uuid, marking: Marking) {
        if let Some(jst) = self.inner.get_mut(&uuid) {
            (*jst).gc_flag = marking;
        }
        //let jst_opt = self.inner.get_mut(&uuid);
        //if let Some(jst) = jst_opt {
        //    let ref mut jst = jst.clone();
        //    jst.gc_flag = marking;
        //    self.inner.insert(uuid, jst);
        //}
    }
}

/// A graph node that stores sets of object uuids, as well as a list of
/// pointers to nodes it can flow to.
/// A variable v is live on edge e if there is:
///     - a node n in the CFG s.t. use[n] contains v
///     - a directed path from e -> n s.t. for every statement s on the path,
///       def[s] does not contain v
#[derive(Clone)]
struct LivenessNode {
    defs: HashSet<Uuid>,
    uses: HashSet<Uuid>,
    ins: HashSet<Uuid>,
    outs: HashSet<Uuid>,
    succ: Vec<Box<LivenessNode>>,
    pred: Vec<Box<LivenessNode>>,
}

struct LivenessGraph {
    nodes: Vec<LivenessNode>,
}

type Statement = i32; // TODO, placeholder

impl LivenessNode {
    fn new() -> LivenessNode {
        LivenessNode {
            defs: HashSet::new(),
            uses: HashSet::new(),
            ins: HashSet::new(),
            outs: HashSet::new(),
            succ: Vec::new(),
            pred: Vec::new(),
        }
    }

    fn node_flow(&mut self) {
        self.ins = self.uses.union(&self.outs.difference(&self.defs).cloned().collect())
                            .cloned().collect();

        self.outs = self.succ.clone().into_iter().flat_map(|s| s.ins).collect();
    }

    // TODO Given a list of AST instructions, parse out what UUIDs are used
    fn compute_uses(&mut self, statements: Vec<Statement>) {

    }

    fn compute_defs(&mut self, statements: Vec<Statement>) {

    }

}

impl LivenessGraph {
    fn new() -> LivenessGraph {
        LivenessGraph {
            nodes: Vec::new(),
        }
    }

    fn graph_flow(&mut self) {
        let mut node_queue: VecDeque<&mut LivenessNode> = self.nodes.iter_mut().collect();
        while let Some(n) = node_queue.pop_front() {
            let old_ins = n.ins.clone();
            let old_outs = n.outs.clone();
            n.node_flow();
            if old_outs != n.outs {
                n.succ.iter_mut().map(|s| node_queue.push_back(s));
            }
        }
    }
}

pub struct StackFrame<'m> {
    members: Vec<&'m JsT>,
}

impl<'m> StackFrame<'m> {
    pub fn new() -> StackFrame<'m> {
        StackFrame { members: Vec::new(), }
    }

    pub fn alloc_ref(&mut self, refce: &'m mut JsT)  {
        self.members.push(refce);
    }
}
<commit_msg>Make UuidMap map uuids -> &RefCell<JsT>s<commit_after>use std::cell::RefCell;
use std::collections::hash_map::HashMap;
use std::collections::hash_set::HashSet;
use std::collections::vec_deque::VecDeque;
use std::vec::Vec;
use js_types::js_type::{JsT, JsType, Marking};
use uuid::Uuid;

/// A map from uuids to references to objects. The interface to the garbage
/// collector, this map gets updated whenever a GC cycle is performed. References
/// that are no longer live may be dropped from the map.
pub struct UuidMap<'r> {
    inner: HashMap<Uuid, &'r RefCell<JsT>>,
}

impl<'r> UuidMap<'r> {
    pub fn new() -> UuidMap<'r> {
        UuidMap {
            inner: HashMap::new(),
        }
    }

    /*pub fn from_jsts(jsts: Vec<RefCell<JsT>>) -> UuidMap<'r> {
        let mut tmp_map = HashMap::new();
        jsts.iter().map(|j| tmp_map.insert(j.borrow.uuid, j));
        UuidMap {
            inner: tmp_map,
        }
    }*/

    pub fn insert_ref(&mut self, jst: &'r RefCell<JsT>) {
        self.inner.insert(jst.borrow().uuid, jst);
    }

    pub fn drop_uuid(&mut self, uuid: Uuid) {
        self.inner.remove(&uuid);
    }

    pub fn drop_ref(&mut self, jst: RefCell<JsT>) {
        self.inner.remove(&jst.borrow().uuid);
    }

    pub fn mark_uuid(&mut self, uuid: Uuid, marking: Marking) {
        if let Some(jst) = self.inner.get_mut(&uuid) {
            jst.borrow_mut().gc_flag = marking;
        }
    }
}

/// A graph node that stores sets of object uuids, as well as a list of
/// pointers to nodes it can flow to.
/// A variable v is live on edge e if there is:
///     - a node n in the CFG s.t. use[n] contains v
///     - a directed path from e -> n s.t. for every statement s on the path,
///       def[s] does not contain v
#[derive(Clone)]
struct LivenessNode {
    defs: HashSet<Uuid>,
    uses: HashSet<Uuid>,
    ins: HashSet<Uuid>,
    outs: HashSet<Uuid>,
    succ: Vec<Box<LivenessNode>>,
    pred: Vec<Box<LivenessNode>>,
}

struct LivenessGraph {
    nodes: Vec<LivenessNode>,
}

type Statement = i32; // TODO, placeholder

impl LivenessNode {
    fn new() -> LivenessNode {
        LivenessNode {
            defs: HashSet::new(),
            uses: HashSet::new(),
            ins: HashSet::new(),
            outs: HashSet::new(),
            succ: Vec::new(),
            pred: Vec::new(),
        }
    }

    fn node_flow(&mut self) {
        self.ins = self.uses.union(&self.outs.difference(&self.defs).cloned().collect())
                            .cloned().collect();

        self.outs = self.succ.clone().into_iter().flat_map(|s| s.ins).collect();
    }

    // TODO Given a list of AST instructions, parse out what UUIDs are used
    fn compute_uses(&mut self, statements: Vec<Statement>) {

    }

    fn compute_defs(&mut self, statements: Vec<Statement>) {

    }

}

impl LivenessGraph {
    fn new() -> LivenessGraph {
        LivenessGraph {
            nodes: Vec::new(),
        }
    }

    fn graph_flow(&mut self) {
        let mut node_queue: VecDeque<&mut LivenessNode> = self.nodes.iter_mut().collect();
        while let Some(n) = node_queue.pop_front() {
            let old_ins = n.ins.clone();
            let old_outs = n.outs.clone();
            n.node_flow();
            if old_outs != n.outs {
                n.succ.iter_mut().map(|s| node_queue.push_back(s));
            }
        }
    }
}

pub struct StackFrame<'m> {
    members: Vec<&'m JsT>,
}

impl<'m> StackFrame<'m> {
    pub fn new() -> StackFrame<'m> {
        StackFrame { members: Vec::new(), }
    }

    pub fn alloc_ref(&mut self, refce: &'m mut JsT)  {
        self.members.push(refce);
    }
}
<|endoftext|>


<commit_before>#![cfg(target_os = "linux")]
#![allow(unused_variables, dead_code)]

use self::wayland::egl::{EGLSurface, is_egl_available};
use self::wayland::core::{ShellSurface, Surface, Output, ShellFullscreenMethod};

use libc;
use api::dlopen;
use api::egl::Context as EglContext;

use BuilderAttribs;
use CreationError;
use Event;
use PixelFormat;
use CursorState;
use MouseCursor;
use GlContext;

use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use std::ffi::CString;

use self::context::WaylandContext;

extern crate wayland_client as wayland;

mod context;

lazy_static! {
    static ref WAYLAND_CONTEXT: Option<WaylandContext> = {
        WaylandContext::new()
    };
}

pub fn is_available() -> bool {
    WAYLAND_CONTEXT.is_some()
}

pub struct Window {
    shell_surface: ShellSurface<EGLSurface>,
    pending_events: Arc<Mutex<VecDeque<Event>>>,
    pub context: EglContext,
}

#[derive(Clone)]
pub struct WindowProxy;

impl WindowProxy {
    pub fn wakeup_event_loop(&self) {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.sync();
        }
    }
}

#[derive(Clone)]
pub struct MonitorID {
    output: Arc<Output>
}

pub fn get_available_monitors() -> VecDeque<MonitorID> {
    WAYLAND_CONTEXT.as_ref().unwrap().outputs.iter().map(|o| MonitorID::new(o.clone())).collect()
}
pub fn get_primary_monitor() -> MonitorID {
    match WAYLAND_CONTEXT.as_ref().unwrap().outputs.iter().next() {
        Some(o) => MonitorID::new(o.clone()),
        None => panic!("No monitor is available.")
    }
}

impl MonitorID {
    fn new(output: Arc<Output>) -> MonitorID {
        MonitorID {
            output: output
        }
    }

    pub fn get_name(&self) -> Option<String> {
        Some(format!("{} - {}", self.output.manufacturer(), self.output.model()))
    }

    pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
        ::native_monitor::NativeMonitorId::Unavailable
    }

    pub fn get_dimensions(&self) -> (u32, u32) {
        let (w, h) = self.output.modes()
                                .into_iter()
                                .find(|m| m.is_current())
                                .map(|m| (m.width, m.height))
                                .unwrap();
        (w as u32, h as u32)
    }
}

pub struct PollEventsIterator<'a> {
    window: &'a Window,
}

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.dispatch_pending();
        }
        self.window.pending_events.lock().unwrap().pop_front()
    }
}

pub struct WaitEventsIterator<'a> {
    window: &'a Window,
}

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.dispatch();
        }
        self.window.pending_events.lock().unwrap().pop_front()
    }
}

impl Window {
    pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
        use self::wayland::internals::FFI;

        let wayland_context = match *WAYLAND_CONTEXT {
            Some(ref c) => c,
            None => return Err(CreationError::NotSupported),
        };

        if !is_egl_available() { return Err(CreationError::NotSupported) }

        let (w, h) = builder.dimensions.unwrap_or((800, 600));

        let surface = EGLSurface::new(
            wayland_context.compositor.create_surface(),
            w as i32,
            h as i32
        );

        let shell_surface = wayland_context.shell.get_shell_surface(surface);
        if let Some(ref monitor) = builder.monitor {
            shell_surface.set_fullscreen(ShellFullscreenMethod::Default, Some(&monitor.output));
        } else {
            shell_surface.set_toplevel();
        }

        let context = {
            let libegl = unsafe { dlopen::dlopen(b"libEGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) };
            if libegl.is_null() {
                return Err(CreationError::NotSupported);
            }
            let egl = ::api::egl::ffi::egl::Egl::load_with(|sym| {
                let sym = CString::new(sym).unwrap();
                unsafe { dlopen::dlsym(libegl, sym.as_ptr()) }
            });
            try!(EglContext::new(
                egl,
                builder,
                Some(wayland_context.display.ptr() as *const _),
                (*shell_surface).ptr() as *const _
            ))
        };

        let events = Arc::new(Mutex::new(VecDeque::new()));

        wayland_context.register_surface(shell_surface.get_wsurface().get_id(), events.clone());

        wayland_context.display.flush().unwrap();

        Ok(Window {
            shell_surface: shell_surface,
            pending_events: events,
            context: context
        })
    }

    pub fn is_closed(&self) -> bool {
        // TODO
        false
    }

    pub fn set_title(&self, title: &str) {
        let ctitle = CString::new(title).unwrap();
        self.shell_surface.set_title(&ctitle);
    }

    pub fn show(&self) {
        // TODO
    }

    pub fn hide(&self) {
        // TODO
    }

    pub fn get_position(&self) -> Option<(i32, i32)> {
        // not available with wayland
        None
    }

    pub fn set_position(&self, _x: i32, _y: i32) {
        // not available with wayland
    }

    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        let (w, h) = self.shell_surface.get_attached_size();
        Some((w as u32, h as u32))
    }

    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        // maybe available if we draw the border ourselves ?
        // but for now, no.
        None
    }

    pub fn set_inner_size(&self, x: u32, y: u32) {
        self.shell_surface.resize(x as i32, y as i32, 0, 0)
    }

    pub fn create_window_proxy(&self) -> WindowProxy {
        WindowProxy
    }

    pub fn poll_events(&self) -> PollEventsIterator {
        PollEventsIterator {
            window: self
        }
    }

    pub fn wait_events(&self) -> WaitEventsIterator {
        WaitEventsIterator {
            window: self
        }
    }

    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        if let Some(callback) = callback {
            self.shell_surface.set_configure_callback(
                move |_,w,h| { callback(w as u32, h as u32) }
            );
        } else {
            self.shell_surface.set_configure_callback(
                move |_,_,_| {}
            );
        }
    }

    pub fn set_cursor(&self, cursor: MouseCursor) {
        // TODO
    }

    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        // TODO
        Ok(())
    }

    pub fn hidpi_factor(&self) -> f32 {
        1.0
    }

    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        // TODO
        Ok(())
    }

    pub fn platform_display(&self) -> *mut libc::c_void {
        unimplemented!()
    }

    pub fn platform_window(&self) -> *mut libc::c_void {
        unimplemented!()
    }
}

impl GlContext for Window {

    unsafe fn make_current(&self) {
        self.context.make_current()
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
        self.context.get_proc_address(addr)
    }

    fn swap_buffers(&self) {
        self.context.swap_buffers()
    }

    fn get_api(&self) -> ::Api {
        self.context.get_api()
    }

    fn get_pixel_format(&self) -> PixelFormat {
        self.context.get_pixel_format().clone()
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.deregister_surface(self.shell_surface.get_wsurface().get_id())
        }
    }
}
<commit_msg>Update to new Platform structure.<commit_after>#![cfg(target_os = "linux")]
#![allow(unused_variables, dead_code)]

use self::wayland::egl::{EGLSurface, is_egl_available};
use self::wayland::core::{ShellSurface, Surface, Output, ShellFullscreenMethod};

use libc;
use api::dlopen;
use api::egl::Context as EglContext;

use BuilderAttribs;
use CreationError;
use Event;
use PixelFormat;
use CursorState;
use MouseCursor;
use GlContext;

use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use std::ffi::CString;

use platform::MonitorID as PlatformMonitorID;

use self::context::WaylandContext;

extern crate wayland_client as wayland;

mod context;

lazy_static! {
    static ref WAYLAND_CONTEXT: Option<WaylandContext> = {
        WaylandContext::new()
    };
}

pub fn is_available() -> bool {
    WAYLAND_CONTEXT.is_some()
}

pub struct Window {
    shell_surface: ShellSurface<EGLSurface>,
    pending_events: Arc<Mutex<VecDeque<Event>>>,
    pub context: EglContext,
}

#[derive(Clone)]
pub struct WindowProxy;

impl WindowProxy {
    pub fn wakeup_event_loop(&self) {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.sync();
        }
    }
}

#[derive(Clone)]
pub struct MonitorID {
    output: Arc<Output>
}

pub fn get_available_monitors() -> VecDeque<MonitorID> {
    WAYLAND_CONTEXT.as_ref().unwrap().outputs.iter().map(|o| MonitorID::new(o.clone())).collect()
}
pub fn get_primary_monitor() -> MonitorID {
    match WAYLAND_CONTEXT.as_ref().unwrap().outputs.iter().next() {
        Some(o) => MonitorID::new(o.clone()),
        None => panic!("No monitor is available.")
    }
}

impl MonitorID {
    fn new(output: Arc<Output>) -> MonitorID {
        MonitorID {
            output: output
        }
    }

    pub fn get_name(&self) -> Option<String> {
        Some(format!("{} - {}", self.output.manufacturer(), self.output.model()))
    }

    pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {
        ::native_monitor::NativeMonitorId::Unavailable
    }

    pub fn get_dimensions(&self) -> (u32, u32) {
        let (w, h) = self.output.modes()
                                .into_iter()
                                .find(|m| m.is_current())
                                .map(|m| (m.width, m.height))
                                .unwrap();
        (w as u32, h as u32)
    }
}

pub struct PollEventsIterator<'a> {
    window: &'a Window,
}

impl<'a> Iterator for PollEventsIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.dispatch_pending();
        }
        self.window.pending_events.lock().unwrap().pop_front()
    }
}

pub struct WaitEventsIterator<'a> {
    window: &'a Window,
}

impl<'a> Iterator for WaitEventsIterator<'a> {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.display.dispatch();
        }
        self.window.pending_events.lock().unwrap().pop_front()
    }
}

impl Window {
    pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
        use self::wayland::internals::FFI;

        let wayland_context = match *WAYLAND_CONTEXT {
            Some(ref c) => c,
            None => return Err(CreationError::NotSupported),
        };

        if !is_egl_available() { return Err(CreationError::NotSupported) }

        let (w, h) = builder.dimensions.unwrap_or((800, 600));

        let surface = EGLSurface::new(
            wayland_context.compositor.create_surface(),
            w as i32,
            h as i32
        );

        let shell_surface = wayland_context.shell.get_shell_surface(surface);
        if let Some(PlatformMonitorID::Wayland(ref monitor)) = builder.monitor {
            shell_surface.set_fullscreen(ShellFullscreenMethod::Default, Some(&monitor.output));
        } else {
            shell_surface.set_toplevel();
        }

        let context = {
            let libegl = unsafe { dlopen::dlopen(b"libEGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) };
            if libegl.is_null() {
                return Err(CreationError::NotSupported);
            }
            let egl = ::api::egl::ffi::egl::Egl::load_with(|sym| {
                let sym = CString::new(sym).unwrap();
                unsafe { dlopen::dlsym(libegl, sym.as_ptr()) }
            });
            try!(EglContext::new(
                egl,
                builder,
                Some(wayland_context.display.ptr() as *const _),
                (*shell_surface).ptr() as *const _
            ))
        };

        let events = Arc::new(Mutex::new(VecDeque::new()));

        wayland_context.register_surface(shell_surface.get_wsurface().get_id(), events.clone());

        wayland_context.display.flush().unwrap();

        Ok(Window {
            shell_surface: shell_surface,
            pending_events: events,
            context: context
        })
    }

    pub fn is_closed(&self) -> bool {
        // TODO
        false
    }

    pub fn set_title(&self, title: &str) {
        let ctitle = CString::new(title).unwrap();
        self.shell_surface.set_title(&ctitle);
    }

    pub fn show(&self) {
        // TODO
    }

    pub fn hide(&self) {
        // TODO
    }

    pub fn get_position(&self) -> Option<(i32, i32)> {
        // not available with wayland
        None
    }

    pub fn set_position(&self, _x: i32, _y: i32) {
        // not available with wayland
    }

    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        let (w, h) = self.shell_surface.get_attached_size();
        Some((w as u32, h as u32))
    }

    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        // maybe available if we draw the border ourselves ?
        // but for now, no.
        None
    }

    pub fn set_inner_size(&self, x: u32, y: u32) {
        self.shell_surface.resize(x as i32, y as i32, 0, 0)
    }

    pub fn create_window_proxy(&self) -> WindowProxy {
        WindowProxy
    }

    pub fn poll_events(&self) -> PollEventsIterator {
        PollEventsIterator {
            window: self
        }
    }

    pub fn wait_events(&self) -> WaitEventsIterator {
        WaitEventsIterator {
            window: self
        }
    }

    pub fn set_window_resize_callback(&mut self, callback: Option<fn(u32, u32)>) {
        if let Some(callback) = callback {
            self.shell_surface.set_configure_callback(
                move |_,w,h| { callback(w as u32, h as u32) }
            );
        } else {
            self.shell_surface.set_configure_callback(
                move |_,_,_| {}
            );
        }
    }

    pub fn set_cursor(&self, cursor: MouseCursor) {
        // TODO
    }

    pub fn set_cursor_state(&self, state: CursorState) -> Result<(), String> {
        // TODO
        Ok(())
    }

    pub fn hidpi_factor(&self) -> f32 {
        1.0
    }

    pub fn set_cursor_position(&self, x: i32, y: i32) -> Result<(), ()> {
        // TODO
        Ok(())
    }

    pub fn platform_display(&self) -> *mut libc::c_void {
        unimplemented!()
    }

    pub fn platform_window(&self) -> *mut libc::c_void {
        unimplemented!()
    }
}

impl GlContext for Window {

    unsafe fn make_current(&self) {
        self.context.make_current()
    }

    fn is_current(&self) -> bool {
        self.context.is_current()
    }

    fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
        self.context.get_proc_address(addr)
    }

    fn swap_buffers(&self) {
        self.context.swap_buffers()
    }

    fn get_api(&self) -> ::Api {
        self.context.get_api()
    }

    fn get_pixel_format(&self) -> PixelFormat {
        self.context.get_pixel_format().clone()
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        if let Some(ref ctxt) = *WAYLAND_CONTEXT {
            ctxt.deregister_surface(self.shell_surface.get_wsurface().get_id())
        }
    }
}
<|endoftext|>


<commit_before>/// Asserts that the type does **not** implement all of the given traits.
///
/// This can be used to ensure types implement auto traits such as [`Send`] and
/// [`Sync`], as well as traits with [blanket `impl`s][blanket].
///
/// Note that the combination of all provided traits is required to not be
/// implemented. If you want to check that none of multiple traits are
/// implemented you should invoke [`assert_not_impl_any`] instead.
///
/// # Examples
///
/// On stable Rust, using the macro requires a unique “label” when used in a
/// module scope:
///
#[cfg_attr(feature = "nightly", doc = "```ignore")]
#[cfg_attr(not(feature = "nightly"), doc = "```")]
/// # #[macro_use] extern crate static_assertions;
/// # use static_assertions::_core::cell::Cell;
/// # fn main() {}
/// assert_not_impl_all!(ptr0; *const u16, Send, Sync);
/// assert_not_impl_all!(ptr1; *const u8, Send, Sync);
/// ```
///
/// The [labeling limitation](index.html#limitations) is not necessary if
/// compiling on nightly Rust with the `nightly` feature enabled:
///
#[cfg_attr(feature = "nightly", doc = "```")]
#[cfg_attr(not(feature = "nightly"), doc = "```ignore")]
/// #![feature(underscore_const_names)]
/// # #[macro_use] extern crate static_assertions;
///
/// assert_not_impl_all!(&'static mut u8, Copy);
///
/// fn main() {
///     assert_not_impl_all!(u32, Into<usize>);
/// }
/// ```
///
/// The following example fails to compile since `u32` can be converted into
/// `u64`.
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {}
/// assert_not_impl_all!(u32, Into<u64>);
/// ```
///
/// `Cell<u32>` is not both `Sync` and `Send`.
///
#[cfg_attr(feature = "nightly", doc = "```ignore")]
#[cfg_attr(not(feature = "nightly"), doc = "```")]
/// # #[macro_use] extern crate static_assertions;
/// # use static_assertions::_core::cell::Cell;
/// # fn main() {}
/// assert_not_impl_all!(cell; Cell<u32>, Sync, Send);
/// ```
/// But it is `Send`, so this fails to compile.
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # use static_assertions::_core::cell::Cell;
/// # fn main() {}
/// assert_not_impl_all!(cell; Cell<u32>, Send);
/// ```
///
/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
/// [`assert_not_impl_any`]: macro.assert_not_impl_any.html
/// [blanket]: https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
#[macro_export(local_inner_macros)]
macro_rules! assert_not_impl_all {
    ($($xs:tt)+) => { _assert_not_impl_all!($($xs)+); };
}

#[doc(hidden)]
#[cfg(feature = "nightly")]
#[macro_export(local_inner_macros)]
macro_rules! _assert_not_impl_all {
    ($x:ty, $($t:path),+ $(,)*) => {
        const _: fn() -> () = || {
            #[allow(dead_code)]
            struct Invalid;
            trait AmbiguousIfImpl<A> { fn some_item() {} }

            impl<T: ?Sized> AmbiguousIfImpl<()> for T {}
            impl<T: ?Sized $(+ $t)*> AmbiguousIfImpl<Invalid> for T {}

            let _ = <$x as AmbiguousIfImpl<_>>::some_item;
        };
    };
}

#[doc(hidden)]
#[cfg(not(feature = "nightly"))]
#[macro_export(local_inner_macros)]
macro_rules! _assert_not_impl_all {
    ($x:ty, $($t:path),+ $(,)*) => {
        {
            #[allow(dead_code)]
            struct Invalid;
            trait AmbiguousIfImpl<A> { fn some_item() {} }

            impl<T: ?Sized> AmbiguousIfImpl<()> for T {}
            impl<T: ?Sized $(+ $t)*> AmbiguousIfImpl<Invalid> for T {}

            let _ = <$x as AmbiguousIfImpl<_>>::some_item;
        }
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_not_impl_all!($($xs)+); }
    };
}
<commit_msg>Add assert_not_impl_any<commit_after>/// Asserts that the type does **not** implement all of the given traits.
///
/// This can be used to ensure types implement auto traits such as [`Send`] and
/// [`Sync`], as well as traits with [blanket `impl`s][blanket].
///
/// Note that the combination of all provided traits is required to not be
/// implemented. If you want to check that none of multiple traits are
/// implemented you should invoke [`assert_not_impl_any`] instead.
///
/// # Examples
///
/// On stable Rust, using the macro requires a unique “label” when used in a
/// module scope:
///
#[cfg_attr(feature = "nightly", doc = "```ignore")]
#[cfg_attr(not(feature = "nightly"), doc = "```")]
/// # #[macro_use] extern crate static_assertions;
/// # use static_assertions::_core::cell::Cell;
/// # fn main() {}
/// assert_not_impl_all!(ptr0; *const u16, Send, Sync);
/// assert_not_impl_all!(ptr1; *const u8, Send, Sync);
/// ```
///
/// The [labeling limitation](index.html#limitations) is not necessary if
/// compiling on nightly Rust with the `nightly` feature enabled:
///
#[cfg_attr(feature = "nightly", doc = "```")]
#[cfg_attr(not(feature = "nightly"), doc = "```ignore")]
/// #![feature(underscore_const_names)]
/// # #[macro_use] extern crate static_assertions;
///
/// assert_not_impl_all!(&'static mut u8, Copy);
///
/// fn main() {
///     assert_not_impl_all!(u32, Into<usize>);
/// }
/// ```
///
/// The following example fails to compile since `u32` can be converted into
/// `u64`.
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {}
/// assert_not_impl_all!(u32, Into<u64>);
/// ```
///
/// `Cell<u32>` is not both `Sync` and `Send`.
///
#[cfg_attr(feature = "nightly", doc = "```ignore")]
#[cfg_attr(not(feature = "nightly"), doc = "```")]
/// # #[macro_use] extern crate static_assertions;
/// # use static_assertions::_core::cell::Cell;
/// # fn main() {}
/// assert_not_impl_all!(cell; Cell<u32>, Sync, Send);
/// ```
/// But it is `Send`, so this fails to compile.
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # use static_assertions::_core::cell::Cell;
/// # fn main() {}
/// assert_not_impl_all!(cell; Cell<u32>, Send);
/// ```
///
/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
/// [`assert_not_impl_any`]: macro.assert_not_impl_any.html
/// [blanket]: https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
#[macro_export(local_inner_macros)]
macro_rules! assert_not_impl_all {
    ($($xs:tt)+) => { _assert_not_impl_all!($($xs)+); };
}

/// Asserts that the type does **not** implement any of the given traits.
///
/// This can be used to ensure types implement auto traits such as [`Send`] and
/// [`Sync`], as well as traits with [blanket `impl`s][blanket].
///
/// The result of the macro fails to compile if any of the provided individual
/// traits are implemented for the type. If you want to check that a combination
/// of traits is not implemented you should invoke [`assert_not_impl_all`]
/// instead. For single traits both macros behave the same.
///
/// # Examples
///
/// On stable Rust, using the macro requires a unique “label” when used in a
/// module scope:
///
#[cfg_attr(feature = "nightly", doc = "```ignore")]
#[cfg_attr(not(feature = "nightly"), doc = "```")]
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {}
/// assert_not_impl_any!(ptr0; *const u16, Send);
/// assert_not_impl_any!(ptr1; *const u8, Send, Sync);
/// ```
///
/// The [labeling limitation](index.html#limitations) is not necessary if
/// compiling on nightly Rust with the `nightly` feature enabled:
///
#[cfg_attr(feature = "nightly", doc = "```")]
#[cfg_attr(not(feature = "nightly"), doc = "```ignore")]
/// #![feature(underscore_const_names)]
/// # #[macro_use] extern crate static_assertions;
///
/// assert_not_impl_any!(&'static mut u8, Copy);
///
/// fn main() {
///     assert_not_impl_any!(u32, Into<usize>);
/// }
/// ```
///
/// The following example fails to compile since `u32` can be converted into
/// `u64` even though it can not be converted into a `u16`.
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {}
/// assert_not_impl_any!(u32, Into<u64>, Into<u16>);
/// ```
///
/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
/// [`assert_not_impl_all`]: macro.assert_not_impl_all.html
/// [blanket]: https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
#[macro_export(local_inner_macros)]
macro_rules! assert_not_impl_any {
    ($($xs:tt)+) => { _assert_not_impl_any!($($xs)+); };
}

#[doc(hidden)]
#[cfg(feature = "nightly")]
#[macro_export(local_inner_macros)]
macro_rules! _assert_not_impl_all {
    ($x:ty, $($t:path),+ $(,)*) => {
        const _: fn() -> () = || {
            #[allow(dead_code)]
            struct Invalid;
            trait AmbiguousIfImpl<A> { fn some_item() {} }

            impl<T: ?Sized> AmbiguousIfImpl<()> for T {}
            impl<T: ?Sized $(+ $t)*> AmbiguousIfImpl<Invalid> for T {}

            let _ = <$x as AmbiguousIfImpl<_>>::some_item;
        };
    };
}

#[doc(hidden)]
#[cfg(not(feature = "nightly"))]
#[macro_export(local_inner_macros)]
macro_rules! _assert_not_impl_all {
    ($x:ty, $($t:path),+ $(,)*) => {
        {
            #[allow(dead_code)]
            struct Invalid;
            trait AmbiguousIfImpl<A> { fn some_item() {} }

            impl<T: ?Sized> AmbiguousIfImpl<()> for T {}
            impl<T: ?Sized $(+ $t)*> AmbiguousIfImpl<Invalid> for T {}

            let _ = <$x as AmbiguousIfImpl<_>>::some_item;
        }
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_not_impl_all!($($xs)+); }
    };
}

#[doc(hidden)]
#[cfg(feature = "nightly")]
#[macro_export(local_inner_macros)]
macro_rules! _assert_not_impl_any {
    ($x:ty, $($t:path),+ $(,)*) => {
        const _: fn() -> () = || {
            trait AmbiguousIfImpl<A> { fn some_item() {} }

            impl<T: ?Sized> AmbiguousIfImpl<()> for T {}
            $({
                #[allow(dead_code)]
                struct Invalid;
                impl<T: ?Sized + $t> AmbiguousIfImpl<Invalid> for T {}
            })+

            let _ = <$x as AmbiguousIfImpl<_>>::some_item;
        };
    };
}

#[doc(hidden)]
#[cfg(not(feature = "nightly"))]
#[macro_export(local_inner_macros)]
macro_rules! _assert_not_impl_any {
    ($x:ty, $($t:path),+ $(,)*) => {
        {
            trait AmbiguousIfImpl<A> { fn some_item() {} }

            impl<T: ?Sized> AmbiguousIfImpl<()> for T {}
            $({
                #[allow(dead_code)]
                struct Invalid;
                impl<T: ?Sized + $t> AmbiguousIfImpl<Invalid> for T {}
            })+

            let _ = <$x as AmbiguousIfImpl<_>>::some_item;
        }
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_not_impl_any!($($xs)+); }
    };
}
<|endoftext|>


<commit_before>use crate::event::{parse_action, Event, EventSender};
/// Input will listens to user input, modify the query string, send special
/// keystrokes(such as Enter, Ctrl-p, Ctrl-n, etc) to the controller.
use std::collections::HashMap;
use std::sync::Arc;
use tuikit::event::Event as TuiEvent;
use tuikit::key::{from_keyname, Key};
use tuikit::term::Term;

pub struct Input {
    tx_input: EventSender,
    term: Arc<Term>,
    keymap: HashMap<Key, (Event, Option<String>)>,
}

impl Input {
    pub fn new(term: Arc<Term>, tx_input: EventSender) -> Self {
        Input {
            tx_input,
            term,
            keymap: get_default_key_map(),
        }
    }

    pub fn run(&mut self) {
        loop {
            match self.term.poll_event() {
                // search event from keymap
                Ok(TuiEvent::Key(key)) => match self.keymap.get(&key) {
                    Some(&(ev @ Event::EvActAccept, None)) | Some(&(ev @ Event::EvActAbort, None)) => {
                        let _ = self.tx_input.send((ev, Box::new(None as Option<String>)));
                        break;
                    }
                    Some(&(ev, Some(ref args))) => {
                        let _ = self.tx_input.send((ev, Box::new(Some(args.clone()))));
                    }
                    Some(&(ev, None)) => {
                        let _ = self.tx_input.send((ev, Box::new(None as Option<String>)));
                    }
                    None => {
                        if let Key::Char(ch) = key {
                            let _ = self.tx_input.send((Event::EvActAddChar, Box::new(ch)));
                        } else {
                            let _ = self.tx_input.send((Event::EvInputKey, Box::new(key)));
                        }
                    }
                },

                Ok(TuiEvent::Resize { .. }) => {
                    let _ = self.tx_input.send((Event::EvActRedraw, Box::new(true)));
                }

                _ => {
                    let _ = self.tx_input.send((Event::EvInputInvalid, Box::new(true)));
                }
            }
        }
    }

    pub fn bind(&mut self, key: &str, action: &str, args: Option<String>) {
        let key = from_keyname(key);
        let action = parse_action(action);
        if key == None || action == None {
            return;
        }

        let key = key.unwrap();
        let act = action.unwrap();

        // remove the key for existing keymap;
        let _ = self.keymap.remove(&key);
        self.keymap.entry(key).or_insert((act, args));
    }

    pub fn parse_keymaps(&mut self, maps: &[&str]) {
        for &map in maps {
            self.parse_keymap(map);
        }
    }

    // key_action is comma separated: 'ctrl-j:accept,ctrl-k:kill-line'
    pub fn parse_keymap(&mut self, key_action: &str) {
        for pair in key_action.split(',') {
            let vec: Vec<&str> = pair.split(':').collect();
            if vec.len() < 2 {
                continue;
            }
            self.bind(vec[0], vec[1], vec.get(2).map(|&string| string.to_string()));
        }
    }

    pub fn parse_expect_keys(&mut self, keys: Option<&str>) {
        if let Some(keys) = keys {
            self.bind("enter", "accept", Some("".to_string()));
            for key in keys.split(',') {
                self.bind(key, "accept", Some(key.to_string()));
            }
        }
    }
}

fn get_default_key_map() -> HashMap<Key, (Event, Option<String>)> {
    let mut ret = HashMap::new();
    ret.insert(Key::ESC, (Event::EvActAbort, None));
    ret.insert(Key::Ctrl('c'), (Event::EvActAbort, None));
    ret.insert(Key::Char('g'), (Event::EvActAbort, None));

    ret.insert(Key::Enter, (Event::EvActAccept, None));

    ret.insert(Key::Left, (Event::EvActBackwardChar, None));
    ret.insert(Key::Ctrl('b'), (Event::EvActBackwardChar, None));

    ret.insert(Key::Ctrl('h'), (Event::EvActBackwardDeleteChar, None));
    ret.insert(Key::Backspace, (Event::EvActBackwardDeleteChar, None));

    ret.insert(Key::AltBackspace, (Event::EvActBackwardKillWord, None));

    ret.insert(Key::Alt('b'), (Event::EvActBackwardWord, None));
    ret.insert(Key::ShiftLeft, (Event::EvActBackwardWord, None));

    ret.insert(Key::Ctrl('a'), (Event::EvActBeginningOfLine, None));
    //ret.insert(Key::Alt('b'),  (Event::EvActCancel, None));
    ret.insert(Key::Ctrl('l'), (Event::EvActClearScreen, None));
    ret.insert(Key::Del, (Event::EvActDeleteChar, None));
    ret.insert(Key::Ctrl('d'), (Event::EvActDeleteCharEOF, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActDeselectAll, None));

    ret.insert(Key::Ctrl('j'), (Event::EvActDown, None));
    ret.insert(Key::Ctrl('n'), (Event::EvActDown, None));
    ret.insert(Key::Down, (Event::EvActDown, None));

    ret.insert(Key::Ctrl('e'), (Event::EvActEndOfLine, None));
    ret.insert(Key::End, (Event::EvActEndOfLine, None));

    ret.insert(Key::Ctrl('f'), (Event::EvActForwardChar, None));
    ret.insert(Key::Right, (Event::EvActForwardChar, None));

    ret.insert(Key::Alt('f'), (Event::EvActForwardWord, None));
    ret.insert(Key::ShiftRight, (Event::EvActForwardWord, None));

    //ret.insert(Key::Alt('z'),  (Event::EvActIgnore, None));

    ret.insert(Key::Alt('d'), (Event::EvActKillWord, None));
    //ret.insert(Key::Ctrl('n'), (Event::EvActNextHistory, None));
    ret.insert(Key::PageDown, (Event::EvActPageDown, None));
    ret.insert(Key::PageUp, (Event::EvActPageUp, None));
    ret.insert(Key::Ctrl('r'), (Event::EvActRotateMode, None));
    ret.insert(Key::Alt('h'), (Event::EvActScrollLeft, None));
    ret.insert(Key::Alt('l'), (Event::EvActScrollRight, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActSelectAll, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggle, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggleAll, None));
    ret.insert(Key::Tab, (Event::EvActToggleDown, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggleIn, None));
    ret.insert(Key::Ctrl('q'), (Event::EvActToggleInteractive, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggleOut, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggleSort, None));
    ret.insert(Key::BackTab, (Event::EvActToggleUp, None));
    ret.insert(Key::Ctrl('u'), (Event::EvActUnixLineDiscard, None));
    ret.insert(Key::Ctrl('w'), (Event::EvActUnixWordRubout, None));
    ret.insert(Key::Ctrl('p'), (Event::EvActUp, None));
    ret.insert(Key::Ctrl('k'), (Event::EvActUp, None));
    ret.insert(Key::Up, (Event::EvActUp, None));
    ret.insert(Key::Ctrl('y'), (Event::EvActYank, None));
    ret
}
<commit_msg>[input] fix default key binding (g -> C-g)<commit_after>use crate::event::{parse_action, Event, EventSender};
/// Input will listens to user input, modify the query string, send special
/// keystrokes(such as Enter, Ctrl-p, Ctrl-n, etc) to the controller.
use std::collections::HashMap;
use std::sync::Arc;
use tuikit::event::Event as TuiEvent;
use tuikit::key::{from_keyname, Key};
use tuikit::term::Term;

pub struct Input {
    tx_input: EventSender,
    term: Arc<Term>,
    keymap: HashMap<Key, (Event, Option<String>)>,
}

impl Input {
    pub fn new(term: Arc<Term>, tx_input: EventSender) -> Self {
        Input {
            tx_input,
            term,
            keymap: get_default_key_map(),
        }
    }

    pub fn run(&mut self) {
        loop {
            match self.term.poll_event() {
                // search event from keymap
                Ok(TuiEvent::Key(key)) => match self.keymap.get(&key) {
                    Some(&(ev @ Event::EvActAccept, None)) | Some(&(ev @ Event::EvActAbort, None)) => {
                        let _ = self.tx_input.send((ev, Box::new(None as Option<String>)));
                        break;
                    }
                    Some(&(ev, Some(ref args))) => {
                        let _ = self.tx_input.send((ev, Box::new(Some(args.clone()))));
                    }
                    Some(&(ev, None)) => {
                        let _ = self.tx_input.send((ev, Box::new(None as Option<String>)));
                    }
                    None => {
                        if let Key::Char(ch) = key {
                            let _ = self.tx_input.send((Event::EvActAddChar, Box::new(ch)));
                        } else {
                            let _ = self.tx_input.send((Event::EvInputKey, Box::new(key)));
                        }
                    }
                },

                Ok(TuiEvent::Resize { .. }) => {
                    let _ = self.tx_input.send((Event::EvActRedraw, Box::new(true)));
                }

                _ => {
                    let _ = self.tx_input.send((Event::EvInputInvalid, Box::new(true)));
                }
            }
        }
    }

    pub fn bind(&mut self, key: &str, action: &str, args: Option<String>) {
        let key = from_keyname(key);
        let action = parse_action(action);
        if key == None || action == None {
            return;
        }

        let key = key.unwrap();
        let act = action.unwrap();

        // remove the key for existing keymap;
        let _ = self.keymap.remove(&key);
        self.keymap.entry(key).or_insert((act, args));
    }

    pub fn parse_keymaps(&mut self, maps: &[&str]) {
        for &map in maps {
            self.parse_keymap(map);
        }
    }

    // key_action is comma separated: 'ctrl-j:accept,ctrl-k:kill-line'
    pub fn parse_keymap(&mut self, key_action: &str) {
        for pair in key_action.split(',') {
            let vec: Vec<&str> = pair.split(':').collect();
            if vec.len() < 2 {
                continue;
            }
            self.bind(vec[0], vec[1], vec.get(2).map(|&string| string.to_string()));
        }
    }

    pub fn parse_expect_keys(&mut self, keys: Option<&str>) {
        if let Some(keys) = keys {
            self.bind("enter", "accept", Some("".to_string()));
            for key in keys.split(',') {
                self.bind(key, "accept", Some(key.to_string()));
            }
        }
    }
}

fn get_default_key_map() -> HashMap<Key, (Event, Option<String>)> {
    let mut ret = HashMap::new();
    ret.insert(Key::ESC, (Event::EvActAbort, None));
    ret.insert(Key::Ctrl('c'), (Event::EvActAbort, None));
    ret.insert(Key::Ctrl('g'), (Event::EvActAbort, None));

    ret.insert(Key::Enter, (Event::EvActAccept, None));

    ret.insert(Key::Left, (Event::EvActBackwardChar, None));
    ret.insert(Key::Ctrl('b'), (Event::EvActBackwardChar, None));

    ret.insert(Key::Ctrl('h'), (Event::EvActBackwardDeleteChar, None));
    ret.insert(Key::Backspace, (Event::EvActBackwardDeleteChar, None));

    ret.insert(Key::AltBackspace, (Event::EvActBackwardKillWord, None));

    ret.insert(Key::Alt('b'), (Event::EvActBackwardWord, None));
    ret.insert(Key::ShiftLeft, (Event::EvActBackwardWord, None));

    ret.insert(Key::Ctrl('a'), (Event::EvActBeginningOfLine, None));
    //ret.insert(Key::Alt('b'),  (Event::EvActCancel, None));
    ret.insert(Key::Ctrl('l'), (Event::EvActClearScreen, None));
    ret.insert(Key::Del, (Event::EvActDeleteChar, None));
    ret.insert(Key::Ctrl('d'), (Event::EvActDeleteCharEOF, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActDeselectAll, None));

    ret.insert(Key::Ctrl('j'), (Event::EvActDown, None));
    ret.insert(Key::Ctrl('n'), (Event::EvActDown, None));
    ret.insert(Key::Down, (Event::EvActDown, None));

    ret.insert(Key::Ctrl('e'), (Event::EvActEndOfLine, None));
    ret.insert(Key::End, (Event::EvActEndOfLine, None));

    ret.insert(Key::Ctrl('f'), (Event::EvActForwardChar, None));
    ret.insert(Key::Right, (Event::EvActForwardChar, None));

    ret.insert(Key::Alt('f'), (Event::EvActForwardWord, None));
    ret.insert(Key::ShiftRight, (Event::EvActForwardWord, None));

    //ret.insert(Key::Alt('z'),  (Event::EvActIgnore, None));

    ret.insert(Key::Alt('d'), (Event::EvActKillWord, None));
    //ret.insert(Key::Ctrl('n'), (Event::EvActNextHistory, None));
    ret.insert(Key::PageDown, (Event::EvActPageDown, None));
    ret.insert(Key::PageUp, (Event::EvActPageUp, None));
    ret.insert(Key::Ctrl('r'), (Event::EvActRotateMode, None));
    ret.insert(Key::Alt('h'), (Event::EvActScrollLeft, None));
    ret.insert(Key::Alt('l'), (Event::EvActScrollRight, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActSelectAll, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggle, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggleAll, None));
    ret.insert(Key::Tab, (Event::EvActToggleDown, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggleIn, None));
    ret.insert(Key::Ctrl('q'), (Event::EvActToggleInteractive, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggleOut, None));
    //ret.insert(Key::Alt('z'),  (Event::EvActToggleSort, None));
    ret.insert(Key::BackTab, (Event::EvActToggleUp, None));
    ret.insert(Key::Ctrl('u'), (Event::EvActUnixLineDiscard, None));
    ret.insert(Key::Ctrl('w'), (Event::EvActUnixWordRubout, None));
    ret.insert(Key::Ctrl('p'), (Event::EvActUp, None));
    ret.insert(Key::Ctrl('k'), (Event::EvActUp, None));
    ret.insert(Key::Up, (Event::EvActUp, None));
    ret.insert(Key::Ctrl('y'), (Event::EvActYank, None));
    ret
}
<|endoftext|>


<commit_before>//! TODO Fill in

use gdk_pixbuf::Pixbuf;
use glib::translate::ToGlibPtr;
use cairo::{self, ImageSurface};
use std::fmt::{self, Display, Formatter};
use std::default::Default;
use std::rc::Rc;
use rlua::{self, Table, Lua, UserData, ToLua, Value};
use super::object::{Object, Objectable};
use super::class::{self, Class, ClassBuilder};

#[derive(Clone, Debug)]
pub struct AwesomeState {
    // TODO Fill in
    dummy: i32
}

pub struct Awesome<'lua>(Table<'lua>);

impl Default for AwesomeState {
    fn default() -> Self {
        AwesomeState {
            dummy: 0
        }
    }
}

impl <'lua> Awesome<'lua> {
    fn new(lua: &Lua) -> rlua::Result<Object> {
        // TODO FIXME
        let class = class::button_class(lua)?;
        Ok(Awesome::allocate(lua, class)?.build())
    }
}

impl Display for AwesomeState {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Awesome: {:p}", self)
    }
}

impl <'lua> ToLua<'lua> for Awesome<'lua> {
    fn to_lua(self, lua: &'lua Lua) -> rlua::Result<Value<'lua>> {
        self.0.to_lua(lua)
    }
}

impl UserData for AwesomeState {}

pub fn init(lua: &Lua) -> rlua::Result<Class> {
    property_setup(lua, method_setup(lua, Class::builder(lua, Some(Rc::new(Awesome::new)), None, None)?)?)?
        .save_class("awesome")?
        .build()
}

fn method_setup<'lua>(lua: &'lua Lua, builder: ClassBuilder<'lua>) -> rlua::Result<ClassBuilder<'lua>> {
    // TODO Do properly
    use super::dummy;
    builder.method("connect_signal".into(), lua.create_function(dummy))?
           .method("register_xproperty".into(), lua.create_function(register_xproperty))?
           .method("xkb_get_group_names".into(), lua.create_function(xkb_get_group_names))?
           .method("restart".into(), lua.create_function(restart))?
           .method("load_image".into(), lua.create_function(load_image))?
           .method("quit".into(), lua.create_function(dummy))
}

/// Registers a new X property
/// This actually does nothing, since this is Wayland.
fn register_xproperty<'lua>(_: &'lua Lua, _: Value<'lua>) -> rlua::Result<()> {
    warn!("register_xproperty not supported");
    Ok(())
}

/// Get layout short names
fn xkb_get_group_names<'lua>(_: &'lua Lua, _: ()) -> rlua::Result<()> {
    warn!("xkb_get_group_names not supported");
    Ok(())
}

/// Restart Awesome by restarting the Lua thread
fn restart<'lua>(_: &'lua Lua, _: ()) -> rlua::Result<()> {
    use lua::{self, LuaQuery};
    if let Err(err) = lua::send(LuaQuery::Restart) {
        warn!("Could not restart Lua thread {:#?}", err);
    }
    Ok(())
}

/// Load an image from the given path
/// Returns either a cairo surface as light user data, nil and an error message
fn load_image<'lua>(lua: &'lua Lua, file_path: String) -> rlua::Result<Value<'lua>> {
    // TODO Move to render module
    let pixbuf = Pixbuf::new_from_file(file_path.as_str())
        .map_err(|err| rlua::Error::RuntimeError(format!("{}", err)))?;
    let width = pixbuf.get_width();
    let height = pixbuf.get_height();
    let channels = pixbuf.get_n_channels();
    let pix_stride = pixbuf.get_rowstride() as usize;
    // NOTE This is safe because we aren't modifying the bytes, but there's no immutable view
    let pixels = unsafe { pixbuf.get_pixels() };
    let format = if channels == 3 {cairo::Format::Rgb24} else { cairo::Format::ARgb32};
    let mut surface = ImageSurface::create(format, width, height)
        .expect("Could not create image of that size");
    let cairo_stride = surface.get_stride() as usize;
    {
        let mut cairo_data = surface.get_data().unwrap();
        let mut pix_pixels_index = 0;
        let mut cairo_pixels_index = 0;
        for _ in 0..height {
            let mut pix_pixels_index2 = pix_pixels_index;
            let mut cairo_pixels_index2 = cairo_pixels_index;
            for _ in 0..width {
                if channels == 3 {
                    let r = pixels[pix_pixels_index2];
                    let g = pixels[pix_pixels_index2 + 1];
                    let b = pixels[pix_pixels_index2 + 2];
                    cairo_data[cairo_pixels_index2] = b;
                    cairo_data[cairo_pixels_index2 + 1] = g;
                    cairo_data[cairo_pixels_index2 + 2] = r;
                    pix_pixels_index2 += 3;
                    // NOTE Four because of the alpha value we ignore
                    cairo_pixels_index2 += 4;
                } else {
                    // TODO TEST THIS BRANCH
                    let mut r = pixels[pix_pixels_index];
                    let mut g = pixels[pix_pixels_index + 1];
                    let mut b = pixels[pix_pixels_index + 2];
                    let a = pixels[pix_pixels_index + 3];
                    let alpha = a as f64 / 255.0;
                    r *= alpha as u8;
                    g *= alpha as u8;
                    b *= alpha as u8;
                    cairo_data[cairo_pixels_index] = b;
                    cairo_data[cairo_pixels_index + 1] = g;
                    cairo_data[cairo_pixels_index + 2] = r;
                    cairo_data[cairo_pixels_index + 3] = a;
                    pix_pixels_index += 4;
                    cairo_pixels_index += 4;
                }
            }
            pix_pixels_index += pix_stride;
            cairo_pixels_index += cairo_stride;
        }
    }
    surface.get_data().unwrap();
    // UGH, I wanted to do to_glib_full, but that isn't defined apparently
    // So now I have to ignore the lifetime completely and just forget about the surface.
    let surface_ptr = surface.to_glib_none().0;
    ::std::mem::forget(surface);
    rlua::LightUserData(surface_ptr as _).to_lua(lua)
}

fn property_setup<'lua>(lua: &'lua Lua, builder: ClassBuilder<'lua>) -> rlua::Result<ClassBuilder<'lua>> {
    // TODO Do properly
    builder.dummy_property("version".into(), "0".to_lua(lua)?)?
           .dummy_property("themes_path".into(), "/usr/share/awesome/themes".to_lua(lua)?)?
           .dummy_property("conffile".into(), "".to_lua(lua)?)
}

impl_objectable!(Awesome, AwesomeState);
<commit_msg>Removed useless flush<commit_after>//! TODO Fill in

use gdk_pixbuf::Pixbuf;
use glib::translate::ToGlibPtr;
use cairo::{self, ImageSurface};
use std::fmt::{self, Display, Formatter};
use std::default::Default;
use std::rc::Rc;
use rlua::{self, Table, Lua, UserData, ToLua, Value};
use super::object::{Object, Objectable};
use super::class::{self, Class, ClassBuilder};

#[derive(Clone, Debug)]
pub struct AwesomeState {
    // TODO Fill in
    dummy: i32
}

pub struct Awesome<'lua>(Table<'lua>);

impl Default for AwesomeState {
    fn default() -> Self {
        AwesomeState {
            dummy: 0
        }
    }
}

impl <'lua> Awesome<'lua> {
    fn new(lua: &Lua) -> rlua::Result<Object> {
        // TODO FIXME
        let class = class::button_class(lua)?;
        Ok(Awesome::allocate(lua, class)?.build())
    }
}

impl Display for AwesomeState {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Awesome: {:p}", self)
    }
}

impl <'lua> ToLua<'lua> for Awesome<'lua> {
    fn to_lua(self, lua: &'lua Lua) -> rlua::Result<Value<'lua>> {
        self.0.to_lua(lua)
    }
}

impl UserData for AwesomeState {}

pub fn init(lua: &Lua) -> rlua::Result<Class> {
    property_setup(lua, method_setup(lua, Class::builder(lua, Some(Rc::new(Awesome::new)), None, None)?)?)?
        .save_class("awesome")?
        .build()
}

fn method_setup<'lua>(lua: &'lua Lua, builder: ClassBuilder<'lua>) -> rlua::Result<ClassBuilder<'lua>> {
    // TODO Do properly
    use super::dummy;
    builder.method("connect_signal".into(), lua.create_function(dummy))?
           .method("register_xproperty".into(), lua.create_function(register_xproperty))?
           .method("xkb_get_group_names".into(), lua.create_function(xkb_get_group_names))?
           .method("restart".into(), lua.create_function(restart))?
           .method("load_image".into(), lua.create_function(load_image))?
           .method("quit".into(), lua.create_function(dummy))
}

/// Registers a new X property
/// This actually does nothing, since this is Wayland.
fn register_xproperty<'lua>(_: &'lua Lua, _: Value<'lua>) -> rlua::Result<()> {
    warn!("register_xproperty not supported");
    Ok(())
}

/// Get layout short names
fn xkb_get_group_names<'lua>(_: &'lua Lua, _: ()) -> rlua::Result<()> {
    warn!("xkb_get_group_names not supported");
    Ok(())
}

/// Restart Awesome by restarting the Lua thread
fn restart<'lua>(_: &'lua Lua, _: ()) -> rlua::Result<()> {
    use lua::{self, LuaQuery};
    if let Err(err) = lua::send(LuaQuery::Restart) {
        warn!("Could not restart Lua thread {:#?}", err);
    }
    Ok(())
}

/// Load an image from the given path
/// Returns either a cairo surface as light user data, nil and an error message
fn load_image<'lua>(lua: &'lua Lua, file_path: String) -> rlua::Result<Value<'lua>> {
    // TODO Move to render module
    let pixbuf = Pixbuf::new_from_file(file_path.as_str())
        .map_err(|err| rlua::Error::RuntimeError(format!("{}", err)))?;
    let width = pixbuf.get_width();
    let height = pixbuf.get_height();
    let channels = pixbuf.get_n_channels();
    let pix_stride = pixbuf.get_rowstride() as usize;
    // NOTE This is safe because we aren't modifying the bytes, but there's no immutable view
    let pixels = unsafe { pixbuf.get_pixels() };
    let format = if channels == 3 {cairo::Format::Rgb24} else { cairo::Format::ARgb32};
    let mut surface = ImageSurface::create(format, width, height)
        .expect("Could not create image of that size");
    let cairo_stride = surface.get_stride() as usize;
    {
        let mut cairo_data = surface.get_data().unwrap();
        let mut pix_pixels_index = 0;
        let mut cairo_pixels_index = 0;
        for _ in 0..height {
            let mut pix_pixels_index2 = pix_pixels_index;
            let mut cairo_pixels_index2 = cairo_pixels_index;
            for _ in 0..width {
                if channels == 3 {
                    let r = pixels[pix_pixels_index2];
                    let g = pixels[pix_pixels_index2 + 1];
                    let b = pixels[pix_pixels_index2 + 2];
                    cairo_data[cairo_pixels_index2] = b;
                    cairo_data[cairo_pixels_index2 + 1] = g;
                    cairo_data[cairo_pixels_index2 + 2] = r;
                    pix_pixels_index2 += 3;
                    // NOTE Four because of the alpha value we ignore
                    cairo_pixels_index2 += 4;
                } else {
                    // TODO TEST THIS BRANCH
                    let mut r = pixels[pix_pixels_index];
                    let mut g = pixels[pix_pixels_index + 1];
                    let mut b = pixels[pix_pixels_index + 2];
                    let a = pixels[pix_pixels_index + 3];
                    let alpha = a as f64 / 255.0;
                    r *= alpha as u8;
                    g *= alpha as u8;
                    b *= alpha as u8;
                    cairo_data[cairo_pixels_index] = b;
                    cairo_data[cairo_pixels_index + 1] = g;
                    cairo_data[cairo_pixels_index + 2] = r;
                    cairo_data[cairo_pixels_index + 3] = a;
                    pix_pixels_index += 4;
                    cairo_pixels_index += 4;
                }
            }
            pix_pixels_index += pix_stride;
            cairo_pixels_index += cairo_stride;
        }
    }
    // UGH, I wanted to do to_glib_full, but that isn't defined apparently
    // So now I have to ignore the lifetime completely and just forget about the surface.
    let surface_ptr = surface.to_glib_none().0;
    ::std::mem::forget(surface);
    rlua::LightUserData(surface_ptr as _).to_lua(lua)
}

fn property_setup<'lua>(lua: &'lua Lua, builder: ClassBuilder<'lua>) -> rlua::Result<ClassBuilder<'lua>> {
    // TODO Do properly
    builder.dummy_property("version".into(), "0".to_lua(lua)?)?
           .dummy_property("themes_path".into(), "/usr/share/awesome/themes".to_lua(lua)?)?
           .dummy_property("conffile".into(), "".to_lua(lua)?)
}

impl_objectable!(Awesome, AwesomeState);
<|endoftext|>


<commit_before>//! This module represents abstraction on top the linux direct rendering manager api (drm).
//!
//! ## [`DrmDevice`]
//!
//! A device exposes certain properties, which are directly derived
//! from the *device* as perceived by the direct rendering manager api (drm). These resources consists
//! out of connectors, encoders, framebuffers, planes and crtcs.
//!
//! [`crtc`](drm::control::crtc)s represent scanout engines of the device pointer to one framebuffer.
//! Their responsibility is to read the data of the framebuffer and export it into an "Encoder".
//! The number of crtc's represent the number of independent output devices the hardware may handle.
//!
//! On modern graphic cards it is better to think about the `crtc` as some sort of rendering engine.
//! You can only have so many different pictures, you may display, as you have `crtc`s, but a single image
//! may be put onto multiple displays.
//!
//! An [`encoder`](drm::control::encoder) encodes the data of connected crtcs into a video signal for a fixed set of connectors.
//! E.g. you might have an analog encoder based on a DAG for VGA ports, but another one for digital ones.
//! Also not every encoder might be connected to every crtc.
//!
//! A [`connector`](drm::control::connector) represents a port on your computer, possibly with a connected monitor, TV, capture card, etc.
//!
//! A [`framebuffer`](drm::control::framebuffer) represents a buffer you may display, see `DrmSurface` below.
//!
//! A [`plane`](drm::control::plane) adds another layer on top of the crtcs, which allow us to layer multiple images on top of each other more efficiently
//! then by combining the rendered images in the rendering phase, e.g. via OpenGL. Planes have to be explicitly used by the user to be useful.
//! Every device has at least one primary plane used to display an image to the whole crtc. Additionally cursor and overlay planes may be present.
//! Cursor planes are usually very restricted in size and meant to be used for hardware cursors, while overlay planes may
//! be used for performance reasons to display any overlay on top of the image, e.g. the top-most windows.
//! Overlay planes may have a bunch of weird limitation, that you cannot query, e.g. only working on round pixel coordinates.
//! You code should never rely on a fixed set of overlay planes, but always have a fallback solution in place.
//!
//! The main functionality of a `Device` in smithay is to give access to all these properties for the user to
//! choose an appropriate rendering configuration. What that means is defined by the requirements and constraints documented
//! in the specific device implementations. The second functionality is the creation of a `Surface`.
//! Surface creation requires a `crtc` (which cannot be the same as another existing `Surface`'s crtc), a plane,
//! as well as a `Mode` and a set of `connectors`.
//!
//! smithay does not make sure that `connectors` are not already in use by another `Surface`. Overlapping `connector`-Sets may
//! be an error or result in undefined rendering behavior depending on the `Surface` implementation.
//!
//! ## [`DrmSurface`]
//!
//! A surface is a part of a `Device` that may output a picture to a number of connectors. It pumps pictures of buffers to outputs.
//!
//! On surface creation a matching encoder for your `connector` is automatically selected, if one exists(!),
//! which means you still need to check your configuration beforehand, even if you do not need to provide an encoder.
//!
//! A surface consists of one `crtc` that is rendered to by the user. This is fixed for the `Surface`s lifetime and cannot be changed.
//! A surface also always needs at least one connector to output the resulting image to as well as a `Mode` that is valid for the given connectors.
//!
//! The state of a `Surface` is double-buffered, meaning all operations that chance the set of `connector`s or their `Mode` are stored and
//! only applied on the next commit. `Surface`s do their best to validate these changes, if possible.
//!
//! A commit/page_flip may be triggered to apply the pending state.
//!
//! ## Rendering
//!
//! The drm infrastructure makes no assumptions about the used renderer and does not interface with them directly.
//! It just provides a way to create framebuffers from various buffer types (mainly `DumbBuffer`s and hardware-backed gbm `BufferObject`s).
//!
//! Buffer management and details about the various types can be found in the [`allocator`-Module](crate::backend::allocator) and
//! rendering abstractions, which can target these buffers can be found in the [`renderer`-Module](crate::backend::renderer).
//!
//! ## [`DrmNode`]
//!
//! A drm node refers to a drm device and the capabilities that may be performed using the node.
//! Generally [`DrmNode`] is primarily used by clients (such as the output backends) which need
//! to allocate buffers for use in X11 or Wayland. If you need to do mode setting, you should use
//! [`DrmDevice`] instead.

pub(crate) mod device;
pub(self) mod error;
pub mod node;
/// TODO: Docs
pub mod renderer;
#[cfg(feature = "backend_session")]
pub(self) mod session;
pub(self) mod surface;

pub use device::{DevPath, DrmDevice, DrmEvent, EventMetadata as DrmEventMetadata, Time as DrmEventTime};
pub use error::Error as DrmError;
pub use node::{CreateDrmNodeError, DrmNode, NodeType};
#[cfg(feature = "backend_gbm")]
pub use surface::gbm::{Error as GbmBufferedSurfaceError, GbmBufferedSurface};
pub use surface::DrmSurface;

use drm::control::{crtc, plane, Device as ControlDevice, PlaneType};

/// A set of planes as supported by a crtc
#[derive(Debug)]
pub struct Planes {
    /// The primary plane of the crtc (automatically selected for [DrmDevice::create_surface])
    pub primary: plane::Handle,
    /// The cursor plane of the crtc, if available
    pub cursor: Option<plane::Handle>,
    /// Overlay planes supported by the crtc, if available
    pub overlay: Vec<plane::Handle>,
}

fn planes(
    dev: &impl ControlDevice,
    crtc: &crtc::Handle,
    has_universal_planes: bool,
) -> Result<Planes, DrmError> {
    let mut primary = None;
    let mut cursor = None;
    let mut overlay = Vec::new();

    let planes = dev.plane_handles().map_err(|source| DrmError::Access {
        errmsg: "Error loading plane handles",
        dev: dev.dev_path(),
        source,
    })?;

    let resources = dev.resource_handles().map_err(|source| DrmError::Access {
        errmsg: "Error loading resource handles",
        dev: dev.dev_path(),
        source,
    })?;

    for plane in planes {
        let info = dev.get_plane(plane).map_err(|source| DrmError::Access {
            errmsg: "Failed to get plane information",
            dev: dev.dev_path(),
            source,
        })?;
        let filter = info.possible_crtcs();
        if resources.filter_crtcs(filter).contains(crtc) {
            match plane_type(dev, plane)? {
                PlaneType::Primary => {
                    primary = Some(plane);
                }
                PlaneType::Cursor => {
                    cursor = Some(plane);
                }
                PlaneType::Overlay => {
                    overlay.push(plane);
                }
            };
        }
    }

    Ok(Planes {
        primary: primary.expect("Crtc has no primary plane"),
        cursor: if has_universal_planes { cursor } else { None },
        overlay: if has_universal_planes { overlay } else { Vec::new() },
    })
}

fn plane_type(dev: &impl ControlDevice, plane: plane::Handle) -> Result<PlaneType, DrmError> {
    let props = dev.get_properties(plane).map_err(|source| DrmError::Access {
        errmsg: "Failed to get properties of plane",
        dev: dev.dev_path(),
        source,
    })?;
    let (ids, vals) = props.as_props_and_values();
    for (&id, &val) in ids.iter().zip(vals.iter()) {
        let info = dev.get_property(id).map_err(|source| DrmError::Access {
            errmsg: "Failed to get property info",
            dev: dev.dev_path(),
            source,
        })?;
        if info.name().to_str().map(|x| x == "type").unwrap_or(false) {
            return Ok(match val {
                x if x == (PlaneType::Primary as u64) => PlaneType::Primary,
                x if x == (PlaneType::Cursor as u64) => PlaneType::Cursor,
                _ => PlaneType::Overlay,
            });
        }
    }
    unreachable!()
}
<commit_msg>drm: fix compilation without default features<commit_after>//! This module represents abstraction on top the linux direct rendering manager api (drm).
//!
//! ## [`DrmDevice`]
//!
//! A device exposes certain properties, which are directly derived
//! from the *device* as perceived by the direct rendering manager api (drm). These resources consists
//! out of connectors, encoders, framebuffers, planes and crtcs.
//!
//! [`crtc`](drm::control::crtc)s represent scanout engines of the device pointer to one framebuffer.
//! Their responsibility is to read the data of the framebuffer and export it into an "Encoder".
//! The number of crtc's represent the number of independent output devices the hardware may handle.
//!
//! On modern graphic cards it is better to think about the `crtc` as some sort of rendering engine.
//! You can only have so many different pictures, you may display, as you have `crtc`s, but a single image
//! may be put onto multiple displays.
//!
//! An [`encoder`](drm::control::encoder) encodes the data of connected crtcs into a video signal for a fixed set of connectors.
//! E.g. you might have an analog encoder based on a DAG for VGA ports, but another one for digital ones.
//! Also not every encoder might be connected to every crtc.
//!
//! A [`connector`](drm::control::connector) represents a port on your computer, possibly with a connected monitor, TV, capture card, etc.
//!
//! A [`framebuffer`](drm::control::framebuffer) represents a buffer you may display, see `DrmSurface` below.
//!
//! A [`plane`](drm::control::plane) adds another layer on top of the crtcs, which allow us to layer multiple images on top of each other more efficiently
//! then by combining the rendered images in the rendering phase, e.g. via OpenGL. Planes have to be explicitly used by the user to be useful.
//! Every device has at least one primary plane used to display an image to the whole crtc. Additionally cursor and overlay planes may be present.
//! Cursor planes are usually very restricted in size and meant to be used for hardware cursors, while overlay planes may
//! be used for performance reasons to display any overlay on top of the image, e.g. the top-most windows.
//! Overlay planes may have a bunch of weird limitation, that you cannot query, e.g. only working on round pixel coordinates.
//! You code should never rely on a fixed set of overlay planes, but always have a fallback solution in place.
//!
//! The main functionality of a `Device` in smithay is to give access to all these properties for the user to
//! choose an appropriate rendering configuration. What that means is defined by the requirements and constraints documented
//! in the specific device implementations. The second functionality is the creation of a `Surface`.
//! Surface creation requires a `crtc` (which cannot be the same as another existing `Surface`'s crtc), a plane,
//! as well as a `Mode` and a set of `connectors`.
//!
//! smithay does not make sure that `connectors` are not already in use by another `Surface`. Overlapping `connector`-Sets may
//! be an error or result in undefined rendering behavior depending on the `Surface` implementation.
//!
//! ## [`DrmSurface`]
//!
//! A surface is a part of a `Device` that may output a picture to a number of connectors. It pumps pictures of buffers to outputs.
//!
//! On surface creation a matching encoder for your `connector` is automatically selected, if one exists(!),
//! which means you still need to check your configuration beforehand, even if you do not need to provide an encoder.
//!
//! A surface consists of one `crtc` that is rendered to by the user. This is fixed for the `Surface`s lifetime and cannot be changed.
//! A surface also always needs at least one connector to output the resulting image to as well as a `Mode` that is valid for the given connectors.
//!
//! The state of a `Surface` is double-buffered, meaning all operations that chance the set of `connector`s or their `Mode` are stored and
//! only applied on the next commit. `Surface`s do their best to validate these changes, if possible.
//!
//! A commit/page_flip may be triggered to apply the pending state.
//!
//! ## Rendering
//!
//! The drm infrastructure makes no assumptions about the used renderer and does not interface with them directly.
//! It just provides a way to create framebuffers from various buffer types (mainly `DumbBuffer`s and hardware-backed gbm `BufferObject`s).
//!
//! Buffer management and details about the various types can be found in the [`allocator`-Module](crate::backend::allocator) and
//! rendering abstractions, which can target these buffers can be found in the [`renderer`-Module](crate::backend::renderer).
//!
//! ## [`DrmNode`]
//!
//! A drm node refers to a drm device and the capabilities that may be performed using the node.
//! Generally [`DrmNode`] is primarily used by clients (such as the output backends) which need
//! to allocate buffers for use in X11 or Wayland. If you need to do mode setting, you should use
//! [`DrmDevice`] instead.

pub(crate) mod device;
pub(self) mod error;
pub mod node;

#[cfg(feature = "wayland_frontend")]
/// TODO: Docs
pub mod renderer;
#[cfg(feature = "backend_session")]
pub(self) mod session;
pub(self) mod surface;

pub use device::{DevPath, DrmDevice, DrmEvent, EventMetadata as DrmEventMetadata, Time as DrmEventTime};
pub use error::Error as DrmError;
pub use node::{CreateDrmNodeError, DrmNode, NodeType};
#[cfg(feature = "backend_gbm")]
pub use surface::gbm::{Error as GbmBufferedSurfaceError, GbmBufferedSurface};
pub use surface::DrmSurface;

use drm::control::{crtc, plane, Device as ControlDevice, PlaneType};

/// A set of planes as supported by a crtc
#[derive(Debug)]
pub struct Planes {
    /// The primary plane of the crtc (automatically selected for [DrmDevice::create_surface])
    pub primary: plane::Handle,
    /// The cursor plane of the crtc, if available
    pub cursor: Option<plane::Handle>,
    /// Overlay planes supported by the crtc, if available
    pub overlay: Vec<plane::Handle>,
}

fn planes(
    dev: &impl ControlDevice,
    crtc: &crtc::Handle,
    has_universal_planes: bool,
) -> Result<Planes, DrmError> {
    let mut primary = None;
    let mut cursor = None;
    let mut overlay = Vec::new();

    let planes = dev.plane_handles().map_err(|source| DrmError::Access {
        errmsg: "Error loading plane handles",
        dev: dev.dev_path(),
        source,
    })?;

    let resources = dev.resource_handles().map_err(|source| DrmError::Access {
        errmsg: "Error loading resource handles",
        dev: dev.dev_path(),
        source,
    })?;

    for plane in planes {
        let info = dev.get_plane(plane).map_err(|source| DrmError::Access {
            errmsg: "Failed to get plane information",
            dev: dev.dev_path(),
            source,
        })?;
        let filter = info.possible_crtcs();
        if resources.filter_crtcs(filter).contains(crtc) {
            match plane_type(dev, plane)? {
                PlaneType::Primary => {
                    primary = Some(plane);
                }
                PlaneType::Cursor => {
                    cursor = Some(plane);
                }
                PlaneType::Overlay => {
                    overlay.push(plane);
                }
            };
        }
    }

    Ok(Planes {
        primary: primary.expect("Crtc has no primary plane"),
        cursor: if has_universal_planes { cursor } else { None },
        overlay: if has_universal_planes { overlay } else { Vec::new() },
    })
}

fn plane_type(dev: &impl ControlDevice, plane: plane::Handle) -> Result<PlaneType, DrmError> {
    let props = dev.get_properties(plane).map_err(|source| DrmError::Access {
        errmsg: "Failed to get properties of plane",
        dev: dev.dev_path(),
        source,
    })?;
    let (ids, vals) = props.as_props_and_values();
    for (&id, &val) in ids.iter().zip(vals.iter()) {
        let info = dev.get_property(id).map_err(|source| DrmError::Access {
            errmsg: "Failed to get property info",
            dev: dev.dev_path(),
            source,
        })?;
        if info.name().to_str().map(|x| x == "type").unwrap_or(false) {
            return Ok(match val {
                x if x == (PlaneType::Primary as u64) => PlaneType::Primary,
                x if x == (PlaneType::Cursor as u64) => PlaneType::Cursor,
                _ => PlaneType::Overlay,
            });
        }
    }
    unreachable!()
}
<|endoftext|>


<commit_before>use std::ops::{Add, AddAssign, Sub};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}
<commit_msg>Add trait implementation for SubAssign<commit_after>use std::ops::{Add, AddAssign, Sub, SubAssign};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Traits intended for blanket imports.

pub use auto::traits::*;
pub use cairo_interaction::ContextExt;
pub use window::WindowExtManual;
<commit_msg>Cairo interactions: auto load Pixbuf & Surface Exts<commit_after>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Traits intended for blanket imports.

pub use auto::traits::*;
pub use cairo_interaction::{ContextExt, PixbufExt, SurfaceExt};
pub use window::WindowExtManual;
<|endoftext|>