<commit_before>//
// yaml.rs
// Nothing to see here yet
//

#![crate_id="yaml"]

use std::iter::Iterator;
use std::option::Option;
use std::io::{IoResult, MemReader};
use std::borrow::Cow;
use self::Token::*;

/// A Yaml Tokenizer
///
/// A tokenizer takes a byte stream and produces a stream of Tokens
/// This shelters the parser from the complexity of dealing with raw bytes.
///
pub struct Tokenizer<'a> {
    reader: Box<Reader + 'a>,
    stack: Vec<u8>,
}

impl <'a>Tokenizer<'a> {

    /// Creates a new Tokenizer from a Reader
    pub fn new<T: Reader + 'a>(reader: Box<T>) -> Tokenizer<'a> {
        Tokenizer {
            reader: reader,
            stack: Vec::new(),
        }
    }

    fn read_char(&mut self) -> Option<char> {
        match self.reader.read_byte() {
            Ok(byte) => Some(byte as char),
            Err(_) => None,
        }
    }

    pub fn pop(&mut self) -> Option<char> {
        if(self.stack.len() == 0) {
            self.read_char()
        } else {
            match self.stack.pop() {
                Some(byte) => Some(byte as char),
                None => None,
            }
        }
    }

    pub fn next_token(&mut self) -> Option<Token> {
        match self.pop() {
            Some(character) => match character {
                '-' => {
                    if self.consume("--") {
                        Some(DocumentStart)
                    } else {
                        Some(SequenceEntry)
                    }
                },
                _ => {
                    self.stack.push(character as u8);
                    self.consume_scalar()
                },
            },
            None => None,
        }
    }

    fn consume_scalar(&mut self) -> Option<Token> {
        let mut eaten = Vec::new();
        loop {
            match self.pop() {
                Some(character) => match character {
                    'A'...'Z'|'a'...'z'|'0'...'9' => {
                        eaten.push(character as u8);
                    },
                    _ => {
                        self.stack.push(character as u8);
                        break;
                    },
                },
                None => {
                    break;
                }
            }
        }

        match String::from_utf8(eaten) {
            Ok(string) => Some(Scalar(string)),
            Err(_) => None,
        }
    }

    fn consume(&mut self, edible: &'static str) -> bool {
        let mut eaten = Vec::new();
        for expected in edible.chars() {
            let character = self.pop();
            if character.is_some() {
                let c = character.unwrap();
                eaten.push(c as u8);
                if c == expected {
                    continue;
                }
            }
            for ate in eaten.drain().rev() {
                self.stack.push(ate);
            }
            return false;
        }
        true
    }
}

/// All the types of tokens
///
/// Describes all of the token types described by the [Yaml 1.0 Spec](http://yaml.org/spec/1.0/)
///
#[derive(PartialEq, Debug)]
pub enum Token {

    /// `[`: the start of a _flow_ sequence
    /// `c-sequence-start` in the spec
    SequenceStart,

    /// `]`: the end of a _flow_ sequence
    /// `c-sequence-end` in the spec
    SequenceEnd,

    /// `{`: the end of a _flow_ mapping
    /// `c-mapping-start` in the spec
    MappingStart,

    /// `}`: the end of a _flow_ mapping
    /// `c-mapping-end` in the spec
    MappingEnd,

    /// `-`: indicates an entry in a sequence
    /// `c-sequence-entry` in the spec
    SequenceEntry,

    /// `:`: separates key from value in a mapping
    /// `c-mapping-entry` in the spec
    MappingSeparator,

    /// `,`: separates entries in _flow_ collections (mapping or sequence)
    /// `c-collect-entry` in the spec
    CollectionSeparator,

    /// `?`: indicates a complex key (e.g a non-scalar key)
    /// `c-complex-key` in the spec
    ComplexKey,

    /// `!`: indicates a tag property
    /// `c-tag` in the spec
    Tag,

    /// `&`: indicates an anchor property (e.g setting a variable)
    /// `c-anchor` in the spec
    Anchor(String),

    /// `*`: indicates an anchor property (e.g using a variable)
    /// `c-alias` in the spec
    Alias,

    /// `|`: indicates a literal value (not to be escaped)
    /// `c-literal` in the spec
    Literal,

    /// `>`: indicates a folded value (ignore line breaks)
    /// `c-folded` in the spec
    Folded,

    /// `'`: a single quoted scalar
    /// `c-single-quote` in the spec
    SingleQuote,

    /// `"`: a double quoted scalar
    /// `c-double-quote` in the spec
    DoubleQuote,

    /// `#`: a comment
    /// `c-throwaway`
    Comment,

    /// `%`: a directive (tags for the YAML parser)
    /// `c-directive` in the spec
    Directive,

    /// `@ | \``: reserved for future use?
    /// `c-reserved` in the spec
    Reserved,

    ///TODO Documentation
    ///
    DocumentStart,

    ///TODO: Documentation
    ///
    DocumentEnd,

    /// ``: a line break with no specific purpose
    LineBreakGeneric,

    /// ``
    LineBreak(LineBreakType),

    Other, // A temporary addition for unimplemented tokens
    Scalar(String),
    Eof,
}

#[derive(PartialEq, Copy, Debug)]
pub enum LineBreakType {
    Generic,
    LineSeparator,
    ParagraphSeparator
}

impl <'a>Iterator for Tokenizer<'a> {

    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        self.next_token()
    }
}

mod test {

    use std::io::MemReader;
    use super::{Tokenizer, Token};
    use super::Token::*;

    #[test]
    fn test_tokens() {
        let stream = "--hallo";
        let mut reader = MemReader::new(stream.bytes().collect());
        let mut tokenizer = Tokenizer::new(Box::new(reader));
        let tokens: Vec<Token> = tokenizer.collect();
        assert!(tokens == vec![SequenceEntry, SequenceEntry, Scalar("hallo".to_string())]);
    }
}
<commit_msg>Implement more tokens<commit_after>//
// yaml.rs
// Nothing to see here yet
//

#![crate_id="yaml"]

use std::iter::Iterator;
use std::option::Option;
use std::io::{IoResult, MemReader};
use std::borrow::Cow;
use self::Token::*;

/// A Yaml Tokenizer
///
/// A tokenizer takes a byte stream and produces a stream of Tokens
/// This shelters the parser from the complexity of dealing with raw bytes.
///
pub struct Tokenizer<'a> {
    reader: Box<Reader + 'a>,
    stack: Vec<u8>,
}

impl <'a>Tokenizer<'a> {

    /// Creates a new Tokenizer from a Reader
    pub fn new<T: Reader + 'a>(reader: Box<T>) -> Tokenizer<'a> {
        Tokenizer {
            reader: reader,
            stack: Vec::new(),
        }
    }

    fn read_char(&mut self) -> Option<char> {
        match self.reader.read_byte() {
            Ok(byte) => Some(byte as char),
            Err(_) => None,
        }
    }

    pub fn pop(&mut self) -> Option<char> {
        if(self.stack.len() == 0) {
            self.read_char()
        } else {
            match self.stack.pop() {
                Some(byte) => Some(byte as char),
                None => None,
            }
        }
    }

    pub fn next_token(&mut self) -> Option<Token> {
        match self.pop() {
            Some(character) => match character {
                // TODO: factor out Some(Token)
                '[' => Some(SequenceStart),
                ']' => Some(SequenceEnd),
                '{' => Some(MappingStart),
                '}' => Some(MappingEnd),
                '-' => {
                    if self.consume("--") {
                        Some(DocumentStart)
                    } else {
                        Some(SequenceEntry)
                    }
                },
                ':' => Some(MappingSeparator),
                ',' => Some(CollectionSeparator),
                '?' => Some(ComplexKey),
                '!' => Some(Tag),
                '&' => {
                    match self.consume_anchor() {
                        Some(string) => Some(Anchor(string)),
                        None => None,
                    }
                },
                '*' => {
                    match self.consume_anchor() {
                        Some(string) => Some(Alias(string)),
                        None => None,
                    }
                },
                '#' => {
                    self.throw_away_comment();
                    self.next_token()
                },
                '\'' => Some(SingleQuote),
                '"' => Some(DoubleQuote),
                '|' => Some(Literal),
                '>' => Some(Folded),
                '.' => {
                    if self.consume("..") {
                        Some(DocumentEnd)
                    } else {
                        self.stack.push(character as u8);
                        self.consume_scalar()
                    }
                }
                _ => {
                    self.stack.push(character as u8);
                    self.consume_scalar()
                },
            },
            None => None,
        }
    }

    fn throw_away_comment(&mut self) {
        loop {
            match self.pop() {
                Some(character) => match character {
                    '\n' => { break },
                    _ => { continue },
                },
                None => {
                    break;
                }
            }
        }
    }

    fn consume_anchor(&mut self) -> Option<String> {
        let mut eaten = Vec::new();
        loop {
            match self.pop() {
                Some(character) => match character {
                    'A'...'Z'|'a'...'z'|'0'...'9'|'-'|'_' => {
                        eaten.push(character as u8);
                    },
                    _ => {
                        self.stack.push(character as u8);
                        break;
                    },
                },
                None => {
                    break;
                }
            }
        }

        match String::from_utf8(eaten) {
            Ok(string) => Some(string),
            Err(_) => None,
        }

    }

    fn consume_scalar(&mut self) -> Option<Token> {
        let mut eaten = Vec::new();
        loop {
            match self.pop() {
                Some(character) => match character {
                    'A'...'Z'|'a'...'z'|'0'...'9' => {
                        eaten.push(character as u8);
                    },
                    _ => {
                        self.stack.push(character as u8);
                        break;
                    },
                },
                None => {
                    break;
                }
            }
        }

        match String::from_utf8(eaten) {
            Ok(string) => Some(Scalar(string)),
            Err(_) => None,
        }
    }

    fn consume(&mut self, edible: &'static str) -> bool {
        let mut eaten = Vec::new();
        for expected in edible.chars() {
            let character = self.pop();
            if character.is_some() {
                let c = character.unwrap();
                eaten.push(c as u8);
                if c == expected {
                    continue;
                }
            }
            for ate in eaten.drain().rev() {
                self.stack.push(ate);
            }
            return false;
        }
        true
    }
}

/// All the types of tokens
///
/// Describes all of the token types described by the [Yaml 1.0 Spec](http://yaml.org/spec/1.0/)
///
#[derive(PartialEq, Debug)]
pub enum Token {

    /// `[`: the start of a _flow_ sequence
    /// `c-sequence-start` in the spec
    SequenceStart,

    /// `]`: the end of a _flow_ sequence
    /// `c-sequence-end` in the spec
    SequenceEnd,

    /// `{`: the end of a _flow_ mapping
    /// `c-mapping-start` in the spec
    MappingStart,

    /// `}`: the end of a _flow_ mapping
    /// `c-mapping-end` in the spec
    MappingEnd,

    /// `-`: indicates an entry in a sequence
    /// `c-sequence-entry` in the spec
    SequenceEntry,

    /// `:`: separates key from value in a mapping
    /// `c-mapping-entry` in the spec
    MappingSeparator,

    /// `,`: separates entries in _flow_ collections (mapping or sequence)
    /// `c-collect-entry` in the spec
    CollectionSeparator,

    /// `?`: indicates a complex key (e.g a non-scalar key)
    /// `c-complex-key` in the spec
    ComplexKey,

    /// `!`: indicates a tag property
    /// `c-tag` in the spec
    Tag,

    /// `&`: indicates an anchor property (e.g setting a variable)
    /// `c-anchor` in the spec
    Anchor(String),

    /// `*`: indicates an anchor property (e.g using a variable)
    /// `c-alias` in the spec
    Alias(String),

    /// `|`: indicates a literal value (not to be escaped)
    /// `c-literal` in the spec
    Literal,

    /// `>`: indicates a folded value (ignore line breaks)
    /// `c-folded` in the spec
    Folded,

    /// `'`: a single quoted scalar
    /// `c-single-quote` in the spec
    SingleQuote,

    /// `"`: a double quoted scalar
    /// `c-double-quote` in the spec
    DoubleQuote,

    /// `#`: a comment
    /// `c-throwaway`
    Comment,

    /// `%`: a directive (tags for the YAML parser)
    /// `c-directive` in the spec
    Directive,

    /// `@ | \``: reserved for future use?
    /// `c-reserved` in the spec
    Reserved,

    ///TODO Documentation
    ///
    DocumentStart,

    ///TODO: Documentation
    ///
    DocumentEnd,

    /// ``: a line break with no specific purpose
    LineBreakGeneric,

    /// ``
    LineBreak(LineBreakType),

    Other, // A temporary addition for unimplemented tokens
    Scalar(String),
    Eof,
}

#[derive(PartialEq, Copy, Debug)]
pub enum LineBreakType {
    Generic,
    LineSeparator,
    ParagraphSeparator
}

impl <'a>Iterator for Tokenizer<'a> {

    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        self.next_token()
    }
}

mod test {

    use std::io::MemReader;
    use super::{Tokenizer, Token};
    use super::Token::*;

    #[test]
    fn test_tokens() {
        let stream = "--hallo";
        let mut reader = MemReader::new(stream.bytes().collect());
        let mut tokenizer = Tokenizer::new(Box::new(reader));
        let tokens: Vec<Token> = tokenizer.collect();
        assert!(tokens == vec![SequenceEntry, SequenceEntry, Scalar("hallo".to_string())]);
    }
}
<|endoftext|>


<commit_before>//! Debug Logging

use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};

#[allow(dead_code)]
#[derive(Debug)]
pub enum Event {
    StartWorking { index: usize },
    InjectJobs { count: usize },
    WaitForWork { worker: usize, was_active: bool },
    StoleWork { worker: usize },
    Join { worker: usize },
    PoppedJob { worker: usize },
    LostJob { worker: usize },
}

pub const DUMP_LOGS: bool = false;

macro_rules! log {
    ($event:expr) => {
        if ::log::DUMP_LOGS { println!("{:?}", $event); }
    }
}

pub static STOLEN_JOB: AtomicUsize = ATOMIC_USIZE_INIT;

macro_rules! stat_stolen {
    () => {
        ::log::STOLEN_JOB.fetch_add(1, ::std::sync::atomic::Ordering::SeqCst);
    }
}

pub static POPPED_JOB: AtomicUsize = ATOMIC_USIZE_INIT;

macro_rules! stat_popped {
    () => {
        ::log::POPPED_JOB.fetch_add(1, ::std::sync::atomic::Ordering::SeqCst);
    }
}

macro_rules! dump_stats {
    () => {
        {
            let stolen = ::log::STOLEN_JOB.load(::std::sync::atomic::Ordering::SeqCst);
            println!("Jobs stolen: {:?}", stolen);
            let popped = ::log::POPPED_JOB.load(::std::sync::atomic::Ordering::SeqCst);
            println!("Jobs popped: {:?}", popped);
        }
    }
}
<commit_msg>remove unnecessary attribute: #[allow(dead_code)]<commit_after>//! Debug Logging

use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};

#[derive(Debug)]
pub enum Event {
    StartWorking { index: usize },
    InjectJobs { count: usize },
    WaitForWork { worker: usize, was_active: bool },
    StoleWork { worker: usize },
    Join { worker: usize },
    PoppedJob { worker: usize },
    LostJob { worker: usize },
}

pub const DUMP_LOGS: bool = false;

macro_rules! log {
    ($event:expr) => {
        if ::log::DUMP_LOGS { println!("{:?}", $event); }
    }
}

pub static STOLEN_JOB: AtomicUsize = ATOMIC_USIZE_INIT;

macro_rules! stat_stolen {
    () => {
        ::log::STOLEN_JOB.fetch_add(1, ::std::sync::atomic::Ordering::SeqCst);
    }
}

pub static POPPED_JOB: AtomicUsize = ATOMIC_USIZE_INIT;

macro_rules! stat_popped {
    () => {
        ::log::POPPED_JOB.fetch_add(1, ::std::sync::atomic::Ordering::SeqCst);
    }
}

macro_rules! dump_stats {
    () => {
        {
            let stolen = ::log::STOLEN_JOB.load(::std::sync::atomic::Ordering::SeqCst);
            println!("Jobs stolen: {:?}", stolen);
            let popped = ::log::POPPED_JOB.load(::std::sync::atomic::Ordering::SeqCst);
            println!("Jobs popped: {:?}", popped);
        }
    }
}
<|endoftext|>


<commit_before>//
// nfa.rs
// Nondeterministic Finite Automata
//

type StateID = usize;

struct State {
    id: StateID,
    trans: Vec<Transition>
}

impl State {
    // finds the outgoing transitions for a given label
    pub fn find_transition(&self, label: Label) -> Vec<&Transition> {
        let mut res : Vec<&Transition> = Vec::new();
        for t in self.trans.iter() {
            if t.label == label {
                res.push(&t);
            }
        }

        res
    }
}

#[derive(PartialEq, Eq)]
enum Label {
    Epsilon,
    Symbol(char)
}

struct Transition {
    label: Label,
    target: StateID
}

struct NFASet {
    states: Vec<State>
}

impl NFASet {
    pub fn new() -> NFASet {
        let st : Vec<State> = Vec::with_capacity(10);
        NFASet { states: st }
    }

    pub fn create_state(&mut self) -> StateID {
        let id = self.states.len();
        let trs : Vec<Transition> = Vec::with_capacity(2);
        let st = State { id: id, trans: trs };
        self.states.push(st);
        id
    }

    pub fn check_id(&self, id: StateID) -> bool {
        id < self.states.len()
    }

    fn get_state_mut(&mut self, id: StateID) -> &mut State {
        // TODO: change to safe, checked access
        unsafe {
            let res : &mut State = self.states.get_unchecked_mut(id);
            res
        }
    }

    pub fn get_state(&self, id: StateID) -> Option<&State> {
        self.states.get(id)
    }

    pub fn add_transition(&mut self, src_id: StateID, dst_id: StateID, label: Label) -> bool {
        if self.check_id(src_id) && self.check_id(dst_id) {
            let src_st = self.get_state_mut(src_id);
            let trans = Transition { label: label, target: dst_id };
            src_st.trans.push(trans);
            true
        }
        else {
            false
        }
    }

    pub fn create_nfa(&self, start: StateID, acc: StateID) -> Option<NFA> {
        if self.check_id(start) && self.check_id(acc) {
            Some(NFA { ns: self, start: start, accept: acc })
        }
        else {
            None
        }
    }

    pub fn nfa_epsilon(&mut self) -> NFA {
        let start = self.create_state();
        let acc = self.create_state();

        self.add_transition(start, acc, Label::Epsilon);

        NFA { ns: self, start: start, accept: acc }
    }

    pub fn nfa_symbol(&mut self, symbol: char) -> NFA {
        let start = self.create_state();
        let acc = self.create_state();

        self.add_transition(start, acc, Label::Symbol(symbol));

        NFA { ns: self, start: start, accept: acc }
    }

    pub fn nfa_union(&mut self, n1: NFA, n2: NFA) -> NFA {
        let start = self.create_state();
        self.add_transition(start, n1.start, Label::Epsilon);
        self.add_transition(start, n2.start, Label::Epsilon);

        let acc = self.create_state();
        self.add_transition(n1.accept, acc, Label::Epsilon);
        self.add_transition(n2.accept, acc, Label::Epsilon);

        NFA { ns: self, start: start, accept: acc }
    }

    pub fn nfa_concat(&mut self, n1: NFA, n2: NFA) -> NFA {
        self.add_transition(n1.accept, n2.start, Label::Epsilon);
        NFA { ns: self, start: n1.start, accept: n2.accept }
    }

    pub fn nfa_star(&mut self, n: NFA) -> NFA {
        let start = self.create_state();
        let acc = self.create_state();

        // transitions connecting old and new start/accept states
        self.add_transition(start, n.start, Label::Epsilon);
        self.add_transition(n.accept, acc, Label::Epsilon);

        // transition connecting start and accept for 0 occurrences
        self.add_transition(start, acc, Label::Epsilon);

        // loop transition for any number of occurrences
        self.add_transition(n.accept, n.start, Label::Epsilon);

        NFA { ns: self, start: start, accept: acc }
    }
}

// NFAs with a single accepting state, which is sufficient
// for automata generated from regular expressions
struct NFA<'a> {
    ns: &'a NFASet,    // FIX: forces mut borrowing when building NFAs
    start: StateID,
    accept: StateID
}

impl<'a> NFA<'a> {
    fn epsilon_closure(&self, states: Vec<StateID>) -> Vec<StateID> {
        let mut stack : Vec<StateID> = Vec::with_capacity(states.len());

        stack.extend(states.clone());

        while !stack.is_empty() {
            let s = stack.pop().unwrap();
            let st = self.ns.get_state(s).unwrap();
            let ets = st.find_transition(Label::Epsilon);
        }

        states
    }

    pub fn simulate(&self, word: &str) -> bool {
        false
    }
}

#[test]
fn states() {
    let mut ns = NFASet::new();
    let id1 = ns.create_state();
    let id2 = ns.create_state();
    assert_eq!(id1, 0);
    assert_eq!(id2, 1);

    assert!(ns.check_id(id1));
    assert!(ns.check_id(id2));
    assert!(!ns.check_id(100));
}

#[test]
fn add_transition() {
    let mut ns = NFASet::new();
    let id1 = ns.create_state();
    let id2 = ns.create_state();
    let id3 = ns.create_state();
    assert!(ns.add_transition(id1, id2, Label::Epsilon));
    assert!(ns.add_transition(id2, id3, Label::Symbol('a')));

    assert!(!ns.add_transition(id1, 1200, Label::Epsilon));
    assert!(!ns.add_transition(1020, id2, Label::Epsilon));
    assert!(!ns.add_transition(1320, 1200, Label::Epsilon));
}

#[test]
fn transitions() {
    let mut ns = NFASet::new();
    let id1 = ns.create_state();
    let id2 = ns.create_state();
    let id3 = ns.create_state();
    assert!(ns.add_transition(id1, id2, Label::Epsilon));
    assert!(ns.add_transition(id1, id3, Label::Epsilon));
    assert!(ns.add_transition(id2, id3, Label::Symbol('a')));

    let st1 = ns.get_state(id1).unwrap();
    let t0 = st1.find_transition(Label::Symbol('b'));
    assert_eq!(t0.len(), 0);
    let t1 = st1.find_transition(Label::Epsilon);
    assert_eq!(t1.len(), 2);

    let st2 = ns.get_state(t1[0].target).unwrap();
    let t2 = st2.find_transition(Label::Symbol('a'));
    assert_eq!(t2.len(), 1);

    assert_eq!(t2[0].target, id3);
    assert_eq!(t1[1].target, id3);
}

#[test]
fn epsilon() {
    let mut ns = NFASet::new();
    let n1 = ns.nfa_epsilon();

    let st1 = n1.ns.get_state(n1.start).unwrap();  // FIX
    let t1 = st1.find_transition(Label::Epsilon);
    assert_eq!(t1.len(), 1);

    let st2 = n1.ns.get_state(t1[0].target).unwrap(); // FIX
    let t2 = st2.find_transition(Label::Epsilon);
    assert_eq!(t2.len(), 0);
}
<commit_msg>Implemented NFABuilder with new approach for NFAs<commit_after>//
// nfa.rs
// Nondeterministic Finite Automata
//

type StateID = usize;

struct State {
    id: StateID,
    trans: Vec<Transition>
}

impl State {
    // finds the outgoing transitions for a given label
    pub fn find_transition(&self, label: Label) -> Vec<&Transition> {
        let mut res : Vec<&Transition> = Vec::new();
        for t in self.trans.iter() {
            if t.label == label {
                res.push(&t);
            }
        }

        res
    }
}

#[derive(PartialEq, Eq, Debug)]
enum Label {
    Epsilon,
    Any,
    Symbol(char)
}

struct Transition {
    label: Label,
    target: StateID
}

struct NFASet {
    states: Vec<State>
}

impl NFASet {
    pub fn new() -> NFASet {
        let st : Vec<State> = Vec::with_capacity(10);
        NFASet { states: st }
    }

    pub fn create_state(&mut self) -> StateID {
        let id = self.states.len();
        let trs : Vec<Transition> = Vec::with_capacity(2);
        let st = State { id: id, trans: trs };
        self.states.push(st);
        id
    }

    pub fn check_id(&self, id: StateID) -> bool {
        id < self.states.len()
    }

    fn get_state_mut(&mut self, id: StateID) -> &mut State {
        // TODO: change to safe, checked access
        unsafe {
            let res : &mut State = self.states.get_unchecked_mut(id);
            res
        }
    }

    pub fn get_state(&self, id: StateID) -> Option<&State> {
        self.states.get(id)
    }

    pub fn add_transition(&mut self, src_id: StateID, dst_id: StateID, label: Label) -> bool {
        if self.check_id(src_id) && self.check_id(dst_id) {
            let src_st = self.get_state_mut(src_id);
            let trans = Transition { label: label, target: dst_id };
            src_st.trans.push(trans);
            true
        }
        else {
            false
        }
    }

    pub fn create_nfa(&self, start: StateID, acc: StateID) -> Option<NFA> {
        if self.check_id(start) && self.check_id(acc) {
            Some(NFA { ns: self, start: start, accept: acc })
        }
        else {
            None
        }
    }

    pub fn nfa_epsilon(&mut self) -> NFA {
        let start = self.create_state();
        let acc = self.create_state();

        self.add_transition(start, acc, Label::Epsilon);

        NFA { ns: self, start: start, accept: acc }
    }

    pub fn nfa_symbol(&mut self, symbol: char) -> NFA {
        let start = self.create_state();
        let acc = self.create_state();

        self.add_transition(start, acc, Label::Symbol(symbol));

        NFA { ns: self, start: start, accept: acc }
    }

    pub fn nfa_union(&mut self, n1: NFA, n2: NFA) -> NFA {
        let start = self.create_state();
        self.add_transition(start, n1.start, Label::Epsilon);
        self.add_transition(start, n2.start, Label::Epsilon);

        let acc = self.create_state();
        self.add_transition(n1.accept, acc, Label::Epsilon);
        self.add_transition(n2.accept, acc, Label::Epsilon);

        NFA { ns: self, start: start, accept: acc }
    }

    pub fn nfa_concat(&mut self, n1: NFA, n2: NFA) -> NFA {
        self.add_transition(n1.accept, n2.start, Label::Epsilon);
        NFA { ns: self, start: n1.start, accept: n2.accept }
    }

    pub fn nfa_star(&mut self, n: NFA) -> NFA {
        let start = self.create_state();
        let acc = self.create_state();

        // transitions connecting old and new start/accept states
        self.add_transition(start, n.start, Label::Epsilon);
        self.add_transition(n.accept, acc, Label::Epsilon);

        // transition connecting start and accept for 0 occurrences
        self.add_transition(start, acc, Label::Epsilon);

        // loop transition for any number of occurrences
        self.add_transition(n.accept, n.start, Label::Epsilon);

        NFA { ns: self, start: start, accept: acc }
    }
}

// NFAs with a single accepting state, which is sufficient
// for automata generated from regular expressions
struct NFA<'a> {
    ns: &'a NFASet,    // FIX: forces mut borrowing when building NFAs
    start: StateID,
    accept: StateID
}

impl<'a> NFA<'a> {
    fn epsilon_closure(&self, states: Vec<StateID>) -> Vec<StateID> {
        let mut stack : Vec<StateID> = Vec::with_capacity(states.len());

        stack.extend(states.clone());

        while !stack.is_empty() {
            let s = stack.pop().unwrap();
            let st = self.ns.get_state(s).unwrap();
            let ets = st.find_transition(Label::Epsilon);
        }

        states
    }

    pub fn simulate(&self, word: &str) -> bool {
        false
    }
}

#[test]
fn states() {
    let mut ns = NFASet::new();
    let id1 = ns.create_state();
    let id2 = ns.create_state();
    assert_eq!(id1, 0);
    assert_eq!(id2, 1);

    assert!(ns.check_id(id1));
    assert!(ns.check_id(id2));
    assert!(!ns.check_id(100));
}

#[test]
fn add_transition() {
    let mut ns = NFASet::new();
    let id1 = ns.create_state();
    let id2 = ns.create_state();
    let id3 = ns.create_state();
    assert!(ns.add_transition(id1, id2, Label::Epsilon));
    assert!(ns.add_transition(id2, id3, Label::Symbol('a')));

    assert!(!ns.add_transition(id1, 1200, Label::Epsilon));
    assert!(!ns.add_transition(1020, id2, Label::Epsilon));
    assert!(!ns.add_transition(1320, 1200, Label::Epsilon));
}

#[test]
fn transitions() {
    let mut ns = NFASet::new();
    let id1 = ns.create_state();
    let id2 = ns.create_state();
    let id3 = ns.create_state();
    assert!(ns.add_transition(id1, id2, Label::Epsilon));
    assert!(ns.add_transition(id1, id3, Label::Epsilon));
    assert!(ns.add_transition(id2, id3, Label::Symbol('a')));

    let st1 = ns.get_state(id1).unwrap();
    let t0 = st1.find_transition(Label::Symbol('b'));
    assert_eq!(t0.len(), 0);
    let t1 = st1.find_transition(Label::Epsilon);
    assert_eq!(t1.len(), 2);

    let st2 = ns.get_state(t1[0].target).unwrap();
    let t2 = st2.find_transition(Label::Symbol('a'));
    assert_eq!(t2.len(), 1);

    assert_eq!(t2[0].target, id3);
    assert_eq!(t1[1].target, id3);
}

#[test]
fn epsilon() {
    let mut ns = NFASet::new();
    let n1 = ns.nfa_epsilon();

    let st1 = n1.ns.get_state(n1.start).unwrap();  // FIX
    let t1 = st1.find_transition(Label::Epsilon);
    assert_eq!(t1.len(), 1);

    let st2 = n1.ns.get_state(t1[0].target).unwrap(); // FIX
    let t2 = st2.find_transition(Label::Epsilon);
    assert_eq!(t2.len(), 0);
}

struct NFA2 {
    start: StateID,
    accept: StateID,
    states: Vec<State>
}

impl NFA2 {
    pub fn get_state(&self, sid: StateID) -> Option<&State> {
        if sid >= self.states.len() {
            None
        } else {
            Some(&self.states[sid])
        }
    }
}

// specification for a NFA built by translation from a regexp
enum Spec {
    Single(Label),
    Union(Box<Spec>, Box<Spec>),
    Concat(Box<Spec>, Box<Spec>),
    Star(Box<Spec>)
}

impl Spec {
    // helper methods for building specs
    fn single(l: Label) -> Box<Spec> {
        Box::new(Spec::Single(l))
    }

    fn union(s1: Box<Spec>, s2: Box<Spec>) -> Box<Spec> {
        Box::new(Spec::Union(s1, s2))
    }

    fn concat(s1: Box<Spec>, s2: Box<Spec>) -> Box<Spec> {
        Box::new(Spec::Concat(s1, s2))
    }

    fn star(s: Box<Spec>) -> Box<Spec> {
        Box::new(Spec::Star(s))
    }
}

struct NFAid {
    start: StateID,
    accept: StateID
}

struct NFABuilder {
    states: Vec<State>
}

impl NFABuilder {
    pub fn build_from_spec(s: Spec) -> NFA2 {
        let st : Vec<State> = Vec::with_capacity(10);
        let mut builder = NFABuilder { states: st };

        let nid = builder.build(s);

        NFA2 { states: builder.states, start: nid.start, accept: nid.accept }
    }

    fn build(&mut self, s: Spec) -> NFAid {
        match s {
            Spec::Single(l) => self.single(l),
            Spec::Union(s1, s2) => {
                let n1 = self.build(*s1);
                let n2 = self.build(*s2);
                self.union(n1, n2)
            },
            Spec::Concat(s1, s2) => {
                let n1 = self.build(*s1);
                let n2 = self.build(*s2);
                self.concat(n1, n2)
            },
            Spec::Star(s) => {
                let n = self.build(*s);
                self.star(n)
            }
        }
    }

    fn new_state(&mut self) -> StateID {
        let res = self.states.len();
        let trs : Vec<Transition> = Vec::with_capacity(2);
        let st = State { id: res, trans: trs };

        self.states.push(st);
        res
    }

    pub fn check_id(&self, id: StateID) -> bool {
        id < self.states.len()
    }

    fn get_state_mut(&mut self, id: StateID) -> &mut State {
        // TODO: change to safe, checked access
        unsafe {
            let res : &mut State = self.states.get_unchecked_mut(id);
            res
        }
    }

    pub fn get_state(&self, id: StateID) -> Option<&State> {
        self.states.get(id)
    }

    fn add_transition(&mut self, src_id: StateID, dst_id: StateID, label: Label) -> bool {
        if self.check_id(src_id) && self.check_id(dst_id) {
            let src_st = self.get_state_mut(src_id);
            let trans = Transition { label: label, target: dst_id };
            src_st.trans.push(trans);
            true
        }
        else {
            false
        }
    }

    fn single(&mut self, l: Label) -> NFAid {
        let st = self.new_state();
        let acc = self.new_state();

        self.add_transition(st, acc, l);

        NFAid { start: st, accept: acc }
    }

    fn union(&mut self, n1: NFAid, n2: NFAid) -> NFAid {
        let start = self.new_state();
        self.add_transition(start, n1.start, Label::Epsilon);
        self.add_transition(start, n2.start, Label::Epsilon);

        let acc = self.new_state();
        self.add_transition(n1.accept, acc, Label::Epsilon);
        self.add_transition(n2.accept, acc, Label::Epsilon);

        NFAid { start: start, accept: acc }
    }

    fn concat(&mut self, n1: NFAid, n2: NFAid) -> NFAid {
        self.add_transition(n1.accept, n2.start, Label::Epsilon);
        NFAid { start: n1.start, accept: n2.accept }
    }

    fn star(&mut self, n: NFAid) -> NFAid {
        let start = self.new_state();
        let acc = self.new_state();

        // transitions connecting old and new start/accept states
        self.add_transition(start, n.start, Label::Epsilon);
        self.add_transition(n.accept, acc, Label::Epsilon);

        // transition connecting start and accept for 0 occurrences
        self.add_transition(start, acc, Label::Epsilon);

        // loop transition for any number of occurrences
        self.add_transition(n.accept, n.start, Label::Epsilon);

        NFAid { start: start, accept: acc }
    }

}

#[test]
fn test_single() {
    let n1 = NFABuilder::build_from_spec(Spec::Single(Label::Epsilon));

    let s0 = n1.get_state(n1.start).unwrap();
    assert_eq!(s0.trans.len(), 1);
    assert_eq!(s0.trans[0].label, Label::Epsilon);

    let ts = s0.find_transition(Label::Epsilon);
    assert_eq!(ts.len(), 1);
    assert_eq!(ts[0].target, n1.accept);

    let s1 = n1.get_state(ts[0].target).unwrap();
    assert_eq!(s1.trans.len(), 0);
    let t1 = s1.find_transition(Label::Epsilon);
    assert_eq!(t1.len(), 0);
}

#[test]
fn test_union() {
    let spec = Spec::union(Spec::single(Label::Epsilon), Spec::single(Label::Any));
    let nfa = NFABuilder::build_from_spec(*spec);

    let s0 = nfa.get_state(nfa.start).unwrap();
    assert_eq!(s0.trans.len(), 2);
    assert_eq!(s0.trans[0].label, Label::Epsilon);
    assert_eq!(s0.trans[1].label, Label::Epsilon);

    let t0 = s0.find_transition(Label::Epsilon);
    assert_eq!(t0.len(), 2);

    let s1 = nfa.get_state(t0[0].target).unwrap();
    assert_eq!(s1.trans.len(), 1);
    let s2 = nfa.get_state(t0[1].target).unwrap();
    assert_eq!(s2.trans.len(), 1);

    let s3 = nfa.get_state(s1.trans[0].target).unwrap();
    assert_eq!(s3.trans.len(), 1);
    assert_eq!(s3.trans[0].label, Label::Epsilon);
    let s4 = nfa.get_state(s2.trans[0].target).unwrap();
    assert_eq!(s4.trans.len(), 1);
    assert_eq!(s4.trans[0].label, Label::Epsilon);

    assert_eq!(s3.trans[0].target, s4.trans[0].target);
    assert_eq!(s3.trans[0].target, nfa.accept);

    let acc = nfa.get_state(s4.trans[0].target).unwrap();
    assert_eq!(acc.trans.len(), 0);
}
<|endoftext|>


<commit_before>use sys;
use bullet_vector3::BulletVector3;
use collision::collision_shapes::Shape;
use mint::{Vector3, Vector4};

#[repr(u8)]
pub enum ActivationState {
    /// Means active so that the object having the state could be moved in a step simulation.
    /// This is the "normal" state for an object to be in.
    /// Use btCollisionObject::activate() to activate an object,
    /// not btCollisionObject::setActivationState(ACTIVATE_TAG),
    /// or it may get disabled again right away, as the deactivation timer has not been reset.
    ActiveTag = 1,
    /// Makes a body active forever, used for something like a player-controlled object.
    DisableDeactivation = 4,
    /// Making a body deactivated forever.
    DisableSimulation = 5,
    /// Means the body, and it's island, are asleep, since Bullet sleeps objects per-island. You probably don't want or need to set this one manually.
    IslandSleeping = 2,
    /// Means that it's an active object trying to fall asleep,
    /// and Bullet is keeping an eye on its velocity for the next few frames
    /// to see if it's a good candidate.
    /// You probably don't want or need to set this one manually.
    WantsDeactivation = 3,
}

pub struct RigidBody {
    rigid_body: Box<sys::btRigidBody>,
    shape: Box<Shape>,
    motion_state: Box<sys::btDefaultMotionState>,
    construction_info: Box<sys::btRigidBody_btRigidBodyConstructionInfo>,
}

impl RigidBody {
    pub fn new<T1: Into<Vector3<f64>>, T2: Into<Vector3<f64>>, T3: Into<Vector4<f64>>>(
        mass: f64,
        inertia: T1,
        shape: Shape,
        translation: T2,
        orientation: T3,
    ) -> RigidBody {
        let mut inertia: BulletVector3 = inertia.into().into();
        let shape_box = Box::new(shape);
        let translation: BulletVector3 = translation.into().into();
        let orientation: [f64; 4] = orientation.into().into();
        let transform = unsafe {
            sys::btTransform::new1(
                &orientation as *const _ as *const _,
                &translation as *const _ as *const _,
            )
        };
        let mut motion_state_box = Box::new(unsafe {
            sys::btDefaultMotionState::new(&transform as *const _, sys::btTransform::getIdentity())
        });

        let construction_info_box = Box::new(unsafe {
            sys::btRigidBody_btRigidBodyConstructionInfo::new(
                mass,
                &mut *motion_state_box as *mut _ as *mut _,
                shape_box.as_ptr(),
                inertia.0.as_mut_ptr() as *mut _,
            )
        });
        RigidBody {
            rigid_body: Box::new(unsafe {
                sys::btRigidBody::new(&*construction_info_box as *const _)
            }),
            shape: shape_box,
            motion_state: motion_state_box,
            construction_info: construction_info_box,
        }
    }

    pub(crate) unsafe fn motion_state_ptr(&self) -> *mut sys::btDefaultMotionState {
        &*self.motion_state as *const _ as *mut _
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut sys::btRigidBody {
        &*self.rigid_body as *const _ as *mut _
    }
}

impl Drop for RigidBody {
    fn drop(&mut self) {
        unsafe {
            ::sys::btMotionState_btMotionState_destructor(
                &mut *self.motion_state as *mut _ as *mut _,
            );
            ::sys::btRigidBody_btRigidBody_destructor(&mut *self.rigid_body as *mut _);
        }
    }
}

#[derive(Clone)]
pub struct RigidBodyHandle {
    pub(in dynamics) ptr: *mut sys::btRigidBody,
    motion_state: *mut sys::btDefaultMotionState,
    temp_transform: sys::btTransform,
}

impl RigidBodyHandle {
    pub fn new(ptr: *mut sys::btRigidBody, motion_state: *mut sys::btDefaultMotionState) -> Self {
        let temp_transform = unsafe { sys::btTransform::new() };

        RigidBodyHandle {
            ptr,
            motion_state,
            temp_transform,
        }
    }
    pub fn set_restitution(&mut self, restitution: f64) {
        unsafe {
            sys::btCollisionObject_setRestitution(self.ptr as *mut _, restitution);
        }
    }
    pub fn set_friction(&mut self, friction: f64) {
        unsafe {
            sys::btCollisionObject_setFriction(self.ptr as *mut _, friction);
        }
    }
    pub fn set_gravity<T: Into<Vector3<f64>>>(&mut self, gravity: T) {
        let gravity: BulletVector3 = gravity.into().into();
        unsafe {
            sys::btRigidBody_setGravity(self.ptr, gravity.0.as_ptr() as *const _);
        }
    }

    pub fn set_angular_factor<T: Into<Vector3<f64>>>(&mut self, angular_factor: T) {
        let angular_factor: BulletVector3 = angular_factor.into().into();
        unsafe {
            sys::btRigidBody_setAngularFactor(self.ptr, angular_factor.0.as_ptr() as *const _);
        }
    }

    pub fn set_sleeping_thresholds(&mut self, linear: f64, angular: f64) {
        unsafe { sys::btRigidBody_setSleepingThresholds(self.ptr, linear, angular) }
    }

    pub fn set_activation_state(&mut self, activation_state: ActivationState) {
        unsafe {
            sys::btCollisionObject_setActivationState(self.ptr as *mut _, activation_state as i32)
        }
    }

    pub fn apply_central_impulse<T: Into<Vector3<f64>>>(&mut self, impulse: T) {
        let impulse: BulletVector3 = impulse.into().into();
        unsafe {
            sys::btRigidBody_applyCentralImpulse(self.ptr, impulse.0.as_ptr() as *const _);
        }
    }

    pub fn get_linear_velocity(&self) -> Vector3<f64> {
        let velocity = unsafe { sys::btRigidBody_getLinearVelocity(self.ptr) };

        ::bullet_vector3::vector_from_slice(unsafe {
            ::std::slice::from_raw_parts(velocity as *const _, 4)
        })
    }

    /// Override velocity vector.
    pub fn reset_linear_velocity<T>(&mut self, velocity: T)
    where
        T: Into<Vector3<f64>>,
    {
        let velocity: BulletVector3 = velocity.into().into();
        unsafe {
            sys::btRigidBody_setLinearVelocity(self.ptr, velocity.0.as_ptr() as *const _);
        }
    }

    /// Override position vector and rotation quaternion.
    pub fn reset_position_and_orientation<T, T1>(&mut self, position: T, orientation: T1)
    where
        T: Into<Vector3<f64>>,
        T1: Into<Vector4<f64>>,
    {
        let orientation: [f64; 4] = orientation.into().into();
        let position: BulletVector3 = position.into().into();
        let transform = unsafe {
            sys::btTransform::new1(
                &orientation as *const _ as *const _,
                &position as *const _ as *const _,
            )
        };

        unsafe {
            sys::btDefaultMotionState_setWorldTransform(
                &*self.motion_state as *const _ as *mut _,
                &transform as *const _ as *const _,
            );
        }

        unsafe { (*self.ptr)._base.m_worldTransform = transform };
    }

    /// Get position in world space and orientation quaternion
    pub fn get_world_position_and_orientation(&self) -> (Vector3<f64>, Vector4<f64>) {
        unsafe {
            sys::btDefaultMotionState_getWorldTransform(
                &*self.motion_state as *const _ as *mut _,
                &self.temp_transform as *const _ as *mut _,
            );
        }
        let origin = unsafe { self.temp_transform.getOrigin1().as_ref().unwrap() };

        let rotation = unsafe { self.temp_transform.getRotation() };

        (
            ::bullet_vector3::vector_from_slice(&origin.m_floats[0..3]),
            ::bullet_vector3::vector4_from_slice(&rotation._base.m_floats),
        )
    }

    /// Place data on heap as a box and set to rigid body as user pointer
    pub fn set_user_data<T: 'static>(&mut self, data: T) {
        let data_box = Box::new(data);
        unsafe {
            sys::btCollisionObject_setUserPointer(
                self.ptr as *mut _,
                Box::into_raw(data_box) as *mut _,
            )
        };
    }

    /// Get data from rigidbody's user pointer
    /// Getting data from body without previously setted data is fine.
    /// Getting wrong typed data is unsafe and will cause mem::transmute to wrong pointer type.
    pub unsafe fn get_user_data<T: 'static>(&self) -> Option<&T> {
        let pointer = sys::btCollisionObject_getUserPointer(self.ptr as *mut _);
        let pointer: *const T = ::std::mem::transmute(pointer);
        return pointer.as_ref();
    }

    /// Set user index. This will not be used in bullet and this is not related to user_data.
    pub fn set_user_index(&mut self, index: i32) {
        unsafe { sys::btCollisionObject_setUserIndex(self.ptr as *mut _, index) };
    }

    /// Get previously setted user index
    /// If index was not set - will return "-1"
    pub fn get_user_index(&self) -> i32 {
        unsafe { sys::btCollisionObject_getUserIndex(self.ptr as *mut _) }
    }

    /// Was that rigid_body removed with DynamicsWorld::remove_body()
    /// Probably may return true also for any not-added bodys
    pub fn removed(&self) -> bool {
        unsafe { (*self.ptr)._base.m_worldArrayIndex == -1 }
    }
}
<commit_msg>get inner body from rigidbodyhandle<commit_after>use sys;
use bullet_vector3::BulletVector3;
use collision::collision_shapes::Shape;
use mint::{Vector3, Vector4};

#[repr(u8)]
pub enum ActivationState {
    /// Means active so that the object having the state could be moved in a step simulation.
    /// This is the "normal" state for an object to be in.
    /// Use btCollisionObject::activate() to activate an object,
    /// not btCollisionObject::setActivationState(ACTIVATE_TAG),
    /// or it may get disabled again right away, as the deactivation timer has not been reset.
    ActiveTag = 1,
    /// Makes a body active forever, used for something like a player-controlled object.
    DisableDeactivation = 4,
    /// Making a body deactivated forever.
    DisableSimulation = 5,
    /// Means the body, and it's island, are asleep, since Bullet sleeps objects per-island. You probably don't want or need to set this one manually.
    IslandSleeping = 2,
    /// Means that it's an active object trying to fall asleep,
    /// and Bullet is keeping an eye on its velocity for the next few frames
    /// to see if it's a good candidate.
    /// You probably don't want or need to set this one manually.
    WantsDeactivation = 3,
}

pub struct RigidBody {
    rigid_body: Box<sys::btRigidBody>,
    shape: Box<Shape>,
    motion_state: Box<sys::btDefaultMotionState>,
    construction_info: Box<sys::btRigidBody_btRigidBodyConstructionInfo>,
}

impl RigidBody {
    pub fn new<T1: Into<Vector3<f64>>, T2: Into<Vector3<f64>>, T3: Into<Vector4<f64>>>(
        mass: f64,
        inertia: T1,
        shape: Shape,
        translation: T2,
        orientation: T3,
    ) -> RigidBody {
        let mut inertia: BulletVector3 = inertia.into().into();
        let shape_box = Box::new(shape);
        let translation: BulletVector3 = translation.into().into();
        let orientation: [f64; 4] = orientation.into().into();
        let transform = unsafe {
            sys::btTransform::new1(
                &orientation as *const _ as *const _,
                &translation as *const _ as *const _,
            )
        };
        let mut motion_state_box = Box::new(unsafe {
            sys::btDefaultMotionState::new(&transform as *const _, sys::btTransform::getIdentity())
        });

        let construction_info_box = Box::new(unsafe {
            sys::btRigidBody_btRigidBodyConstructionInfo::new(
                mass,
                &mut *motion_state_box as *mut _ as *mut _,
                shape_box.as_ptr(),
                inertia.0.as_mut_ptr() as *mut _,
            )
        });
        RigidBody {
            rigid_body: Box::new(unsafe {
                sys::btRigidBody::new(&*construction_info_box as *const _)
            }),
            shape: shape_box,
            motion_state: motion_state_box,
            construction_info: construction_info_box,
        }
    }

    pub(crate) unsafe fn motion_state_ptr(&self) -> *mut sys::btDefaultMotionState {
        &*self.motion_state as *const _ as *mut _
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut sys::btRigidBody {
        &*self.rigid_body as *const _ as *mut _
    }
}

impl Drop for RigidBody {
    fn drop(&mut self) {
        unsafe {
            ::sys::btMotionState_btMotionState_destructor(
                &mut *self.motion_state as *mut _ as *mut _,
            );
            ::sys::btRigidBody_btRigidBody_destructor(&mut *self.rigid_body as *mut _);
        }
    }
}

#[derive(Clone)]
pub struct RigidBodyHandle {
    pub(in dynamics) ptr: *mut sys::btRigidBody,
    motion_state: *mut sys::btDefaultMotionState,
    temp_transform: sys::btTransform,
}

impl RigidBodyHandle {
    pub fn new(ptr: *mut sys::btRigidBody, motion_state: *mut sys::btDefaultMotionState) -> Self {
        let temp_transform = unsafe { sys::btTransform::new() };

        RigidBodyHandle {
            ptr,
            motion_state,
            temp_transform,
        }
    }
    pub fn set_restitution(&mut self, restitution: f64) {
        unsafe {
            sys::btCollisionObject_setRestitution(self.ptr as *mut _, restitution);
        }
    }
    pub fn set_friction(&mut self, friction: f64) {
        unsafe {
            sys::btCollisionObject_setFriction(self.ptr as *mut _, friction);
        }
    }
    pub fn set_gravity<T: Into<Vector3<f64>>>(&mut self, gravity: T) {
        let gravity: BulletVector3 = gravity.into().into();
        unsafe {
            sys::btRigidBody_setGravity(self.ptr, gravity.0.as_ptr() as *const _);
        }
    }

    pub fn set_angular_factor<T: Into<Vector3<f64>>>(&mut self, angular_factor: T) {
        let angular_factor: BulletVector3 = angular_factor.into().into();
        unsafe {
            sys::btRigidBody_setAngularFactor(self.ptr, angular_factor.0.as_ptr() as *const _);
        }
    }

    pub fn set_sleeping_thresholds(&mut self, linear: f64, angular: f64) {
        unsafe { sys::btRigidBody_setSleepingThresholds(self.ptr, linear, angular) }
    }

    pub fn set_activation_state(&mut self, activation_state: ActivationState) {
        unsafe {
            sys::btCollisionObject_setActivationState(self.ptr as *mut _, activation_state as i32)
        }
    }

    pub fn apply_central_impulse<T: Into<Vector3<f64>>>(&mut self, impulse: T) {
        let impulse: BulletVector3 = impulse.into().into();
        unsafe {
            sys::btRigidBody_applyCentralImpulse(self.ptr, impulse.0.as_ptr() as *const _);
        }
    }

    pub fn get_linear_velocity(&self) -> Vector3<f64> {
        let velocity = unsafe { sys::btRigidBody_getLinearVelocity(self.ptr) };

        ::bullet_vector3::vector_from_slice(unsafe {
            ::std::slice::from_raw_parts(velocity as *const _, 4)
        })
    }

    /// Override velocity vector.
    pub fn reset_linear_velocity<T>(&mut self, velocity: T)
    where
        T: Into<Vector3<f64>>,
    {
        let velocity: BulletVector3 = velocity.into().into();
        unsafe {
            sys::btRigidBody_setLinearVelocity(self.ptr, velocity.0.as_ptr() as *const _);
        }
    }

    /// Override position vector and rotation quaternion.
    pub fn reset_position_and_orientation<T, T1>(&mut self, position: T, orientation: T1)
    where
        T: Into<Vector3<f64>>,
        T1: Into<Vector4<f64>>,
    {
        let orientation: [f64; 4] = orientation.into().into();
        let position: BulletVector3 = position.into().into();
        let transform = unsafe {
            sys::btTransform::new1(
                &orientation as *const _ as *const _,
                &position as *const _ as *const _,
            )
        };

        unsafe {
            sys::btDefaultMotionState_setWorldTransform(
                &*self.motion_state as *const _ as *mut _,
                &transform as *const _ as *const _,
            );
        }

        unsafe { (*self.ptr)._base.m_worldTransform = transform };
    }

    /// Get position in world space and orientation quaternion
    pub fn get_world_position_and_orientation(&self) -> (Vector3<f64>, Vector4<f64>) {
        unsafe {
            sys::btDefaultMotionState_getWorldTransform(
                &*self.motion_state as *const _ as *mut _,
                &self.temp_transform as *const _ as *mut _,
            );
        }
        let origin = unsafe { self.temp_transform.getOrigin1().as_ref().unwrap() };

        let rotation = unsafe { self.temp_transform.getRotation() };

        (
            ::bullet_vector3::vector_from_slice(&origin.m_floats[0..3]),
            ::bullet_vector3::vector4_from_slice(&rotation._base.m_floats),
        )
    }

    /// Place data on heap as a box and set to rigid body as user pointer
    pub fn set_user_data<T: 'static>(&mut self, data: T) {
        let data_box = Box::new(data);
        unsafe {
            sys::btCollisionObject_setUserPointer(
                self.ptr as *mut _,
                Box::into_raw(data_box) as *mut _,
            )
        };
    }

    /// Get data from rigidbody's user pointer
    /// Getting data from body without previously setted data is fine.
    /// Getting wrong typed data is unsafe and will cause mem::transmute to wrong pointer type.
    pub unsafe fn get_user_data<T: 'static>(&self) -> Option<&T> {
        let pointer = sys::btCollisionObject_getUserPointer(self.ptr as *mut _);
        let pointer: *const T = ::std::mem::transmute(pointer);
        return pointer.as_ref();
    }

    /// Set user index. This will not be used in bullet and this is not related to user_data.
    pub fn set_user_index(&mut self, index: i32) {
        unsafe { sys::btCollisionObject_setUserIndex(self.ptr as *mut _, index) };
    }

    /// Get previously setted user index
    /// If index was not set - will return "-1"
    pub fn get_user_index(&self) -> i32 {
        unsafe { sys::btCollisionObject_getUserIndex(self.ptr as *mut _) }
    }

    /// Was that rigid_body removed with DynamicsWorld::remove_body()
    /// Probably may return true also for any not-added bodys
    pub fn removed(&self) -> bool {
        unsafe { (*self.ptr)._base.m_worldArrayIndex == -1 }
    }

    pub unsafe fn ptr(&mut self) -> *mut sys::btRigidBody {
        self.ptr
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate x11;

use std::ptr;
use x11::xlib;
use x11::xlib::Window;
use super::super::libx;

use super::config::Config;
use super::container::{self, Container};
use super::layout;
use super::Workspaces;
use super::handler;

unsafe extern fn error_handler(display: *mut xlib::Display, event: *mut xlib::XErrorEvent) -> libc::c_int {
    // match event.error_code {
    //     xlib::BadAtom => {
    //         println!("bad atom");
    //     }
    //     _ => {}
    // }
    // x11::xmu::XmuSimpleErrorHandler(display, event);
    1
}

extern "C" {
    fn setlocale(category: i32, locale: *const i8) -> *mut i8;
}

fn load_resource(mut context: &mut libx::Context) {
    use std::mem;
    use std::ffi;
    let screen = context.screen_num;
    let root = context.root;
    let display = context.display;
    let mut values: xlib::XGCValues = unsafe{ mem::zeroed() };
    // let gc = libx::create_gc(self.context, self.id, 0, values);
    let gc = libx::default_gc(*context, screen);

    unsafe {
        let black = xlib::XBlackPixel(display, screen);
        let white = xlib::XWhitePixel(display, screen);

        xlib::XSetLineAttributes(display, gc, 5, 0, 0, 0);

        let cmap = xlib::XDefaultColormap(display, screen);
        let mut color: xlib::XColor = mem::zeroed();
        let name = ffi::CString::new("blue").unwrap().as_ptr();
        let r = xlib::XParseColor(display, cmap, name, &mut color);
        xlib::XAllocColor(display, cmap, &mut color);

        context.gc = gc;
        context.focus_bg = black;
        context.focus_fg = color.pixel;
        context.unfocus_bg = black;
        context.unfocus_fg = black;
        context.font_color = white;

        let s = ffi::CString::new("").unwrap().as_ptr();
        let p = setlocale(6, s);
        let res = xlib::XSupportsLocale();
        let res = xlib::XSetLocaleModifiers(s);

        let mut missing_charsets = ptr::null_mut();
        let mut num_missing_charsets: i32 = 0;
        let mut default_string = ptr::null_mut();
        // let name = "-misc-fixed-*-*-*-*-*-130-75-75-*-*-*-*";
        let name = "*";
        let fontbase = ffi::CString::new(name).unwrap().as_ptr();
        let fontset = xlib::XCreateFontSet(display,
                                           fontbase,
                                           &mut missing_charsets,
                                           &mut num_missing_charsets,
                                           &mut default_string);
        if num_missing_charsets > 0 {
            xlib::XFreeStringList(missing_charsets);
        }
        context.fontset = fontset;
    }
}

pub struct WindowManager {
    pub context: libx::Context,
    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	let res = libx::open_display(None);
        let mut context = match res {
            Some(c) => {
                c
            }
            None => {
                panic!("can't open display")
            }
        };

	context.screen_num  = libx::default_screen(context);
	context.root = libx::root_window(context, context.screen_num);
        load_resource(&mut context);

	let mut wm = WindowManager {
            context: context,
            config: Config::new(),
            workspaces: Workspaces::new(context)
        };
        wm
    }

    pub fn clean(&mut self) {
        libx::close_display(self.context);
    }

    pub fn handle_create(&mut self, event: &xlib::XCreateWindowEvent) {
        if event.override_redirect != 0 {
            return;
        }

        let attrs = libx::get_window_attributes(self.context, event.window);
        println!("{} attr {} {}", event.window, attrs.width, attrs.height);
        // get window property
        let n = libx::get_text_property(self.context, event.window, xlib::XA_WM_NAME);
        match n {
            Some(s) => {debug!("create window {} for {}", event.window, s);}
            None => {}
        }

        // let atoms = libx::get_wm_protocols(self.context, event.window);
        // for a in atoms.iter() {
        //     println!("atom {}", a);
        //     let name = libx::get_atom_name(self.context, *a);
        //     match name {
        //         Some(n) => println!("name {}", n),
        //         None => println!("name {}", a),
        //     };
        // }
    }

    pub fn handle_destroy(&mut self, event: &xlib::XDestroyWindowEvent) {
        self.workspaces.remove_window(event.window);
        if self.workspaces.get_focus().is_none() {
            self.workspaces.set_focus(self.context.root);
        }
    }

    pub fn handle_map_request(&mut self, event: &xlib::XMapRequestEvent) {

        // add app top-level window to workspace
        // let window = Window::new(self.context, event.window);
        let manage = Workspaces::can_manage(self.context, event.window);

        if manage {
            debug!("top level window");
            let mut container = Container::from_id(self.context, event.window);
            container.map();
            // container.focus();
            // change attributes before display
            let mask = 0x420010;
            let mask = xlib::EnterWindowMask | xlib::PropertyChangeMask;
            libx::select_input(self.context, container.raw_id(), mask);

            if self.config.titlebar_height > 0 {
                container.titlebar_height = self.config.titlebar_height;
            }
            self.workspaces.insert_window(container);
        }
        else {
            libx::map_window(self.context, event.window);
        }
    }

    pub fn handle_client_message(&mut self, event: &xlib::XClientMessageEvent) {
        println!("message type {}", event.message_type);
        let s = libx::get_atom_name(self.context, event.message_type);
        match s {
            Some(v) => println!("{}", &v),
            None => {}
        }

        match event.format {
            8 => {
                for i in 0..20 {
                    println!("{}", event.data.get_byte(i));
                }
            }
            16 => {
                for i in 0..10 {
                    println!("{}", event.data.get_short(i))
                }
            }
            32 => {
                for i in 0..5 {
                    let a = event.data.get_long(i);
                    if a != 0{
                        let s = libx::get_atom_name(self.context, a as xlib::Atom);
                        match s {
                            Some(v) => println!("{}", v),
                            None => {}
                        }
                    }
                }
            }
            _ => {}
        }
    }

    pub fn handle_button_motion(&mut self, event: &xlib::XMotionEvent) {

    }

    pub fn handle_button_press(&mut self, event: &xlib::XButtonEvent) {

        let id = match self.workspaces.get_container(event.window) {
            Some((_,c)) => {
                let client = c.query_point(event.x, event.y);
                match client {
                    Some(c) => {
                        c.raw_id()
                    }
                    None => { c.raw_id() }
                }
            }
            None => { return }
        };
        self.workspaces.set_focus(id);

        // test if press on boarder
        match self.workspaces.get_container(event.window) {
            Some((_,c)) => {
                let res = c.query_border(event.x, event.y);
                match res {
                    Some(i) => {
                        match c.mode {
                            container::Mode::Normal => {
                                c.mode = container::Mode::Resize(i, event.x, event.y)
                            }
                            container::Mode::Resize(index, x, y) => {

                            }
                            _ => {}
                        }
                    }
                    None => {}
                }
            }
            None => {}
        }
    }

    pub fn handle_button_release(&mut self, event: &xlib::XButtonEvent) {
        match self.workspaces.get_container(event.window) {
            Some((_, c)) => {
                match c.mode {
                    container::Mode::Resize(index, x, y) => {
                        let dx = event.x - x;
                        let dy = event.y - y;
                        let rec = c.rec();
                        let step = match c.direction {
                            layout::Direction::Vertical => {
                                dy as f32 / rec.height as f32
                            }
                            layout::Direction::Horizontal => {
                                dx as f32 / rec.width as f32
                            }
                            _ => { 0.05 }
                        };

                        c.resize_children(index-1, index, step);
                        c.update_layout();
                        c.mode = container::Mode::Normal;
                    }
                    _ => {}
                }
            }
            None => {}
        }
    }

    pub fn handle_key_release(&mut self, event: &xlib::XKeyEvent) {
        if event.state > 0 {
            let sym = libx::lookup_keysym(*event, 0);
            let b = handler::KeyBind {
                key: sym,
                mask: event.state,
            };
            debug!("key {} {}", event.state, sym);

            match self.config.bindsyms.get_mut(&b) {
                Some(handler) => {
                    handler.handle(&mut self.workspaces, self.context);
                }
                None => {
                    println!("no bind");
                }
            }
        }
    }

    pub fn handle_property(&mut self, event: &xlib::XPropertyEvent) {
        let usertime = libx::get_atom(self.context, "_NET_WM_USER_TIME");
        match event.atom {
            usertime => {
                self.workspaces.set_focus(event.window);
            }
        }
    }

    pub fn handle_configure_request(&mut self, event: &xlib::XConfigureRequestEvent) {
        let mut change = xlib::XWindowChanges {
            x: event.x,
            y: event.y,
            width: event.width,
            height: event.height,
            border_width: event.border_width,
            sibling: event.above,
            stack_mode: event.detail
        };
        debug!("config x: {}, y: {}, width: {}, height: {}",
               change.x, change.y, change.width, change.height);
        libx::configure_window(self.context, event.window, event.value_mask as u32, change);
    }

    pub fn handle_focus_in(&mut self, event: &xlib::XFocusChangeEvent) {
        self.workspaces.set_focus(event.window);
    }

    pub fn handle_enter(&mut self, event: &xlib::XCrossingEvent){
        if event.focus == 0 {
            self.workspaces.set_focus(event.window);
        }
    }

    pub fn handle(&mut self, e: xlib::XEvent) {
        let t = e.get_type();
        match t {
            xlib::CreateNotify => {
                let event: xlib::XCreateWindowEvent = From::from(e);
                debug!("create notify {}", event.window);
                self.handle_create(&event);
            }
            xlib::DestroyNotify => {
                let event: xlib::XDestroyWindowEvent = From::from(e);
                debug!("destroy notify {}", event.window);
                self.handle_destroy(&event);
            }
            xlib::MapNotify => {
                let event: xlib::XMapEvent = From::from(e);
                debug!("map notify {}", event.window);
            }
            xlib::UnmapNotify => {
                let event: xlib::XUnmapEvent = From::from(e);
                debug!("unmap notify {}", event.window);
            }
            xlib::MapRequest => {
                let event: xlib::XMapRequestEvent = From::from(e);
                debug!("map request {}", event.window);
                self.handle_map_request(&event);
            }
            xlib::ClientMessage => {
                debug!("client message");
                // let event = cast_event::<xlib::XClientMessageEvent>(&e);
                let event: xlib::XClientMessageEvent = From::from(e);
                self.handle_client_message(&event);
            }
            xlib::KeyRelease => {
                debug!("key release");
                let mut event: xlib::XKeyEvent = From::from(e);
                self.handle_key_release(&mut event);
            }
            xlib::MotionNotify => {
                let mut event: xlib::XMotionEvent = From::from(e);
                debug!("button motion {}", event.window);
                self.handle_button_motion(&event);
            }
            xlib::ButtonRelease => {
                let mut event: xlib::XButtonEvent = From::from(e);
                debug!("button release {}", event.window);
                self.handle_button_release(&event);
            }
            xlib::ButtonPress => {
                let mut event: xlib::XButtonEvent = From::from(e);
                debug!("button press {}", event.window);
                self.handle_button_press(&event);
            }
            xlib::ConfigureNotify => {
                debug!("configure notify");
            }
            xlib::ConfigureRequest =>{
                let mut event: xlib::XConfigureRequestEvent = From::from(e);
                debug!("configure request {}", event.window);
                self.handle_configure_request(&event);
            }
            xlib::FocusIn => {
                let mut event: xlib::XFocusChangeEvent = From::from(e);
                debug!("focus in {}", event.window);
                self.handle_focus_in(&event);

            }
            xlib::FocusOut => {
                let mut event: xlib::XFocusChangeEvent = From::from(e);
                debug!("focus out {}", event.window);
            }
            xlib::EnterNotify => {
                let mut event: xlib::XCrossingEvent = From::from(e);
                debug!("enter window {}", event.window);
                self.handle_enter(&event);
            }
            xlib::PropertyNotify => {
                let mut event: xlib::XPropertyEvent = From::from(e);
                debug!("property notify {}", event.window);
                self.handle_property(&event);
            }
            _ => {
                debug!("unhandled event {}", t);
            }
        }
    }
    pub fn run(&mut self) {
        loop {
            //handle events here
            let mut e = libx::next_event(self.context);
            self.handle(e);
        }
    }

    pub fn init(&mut self) {
        // init connection setting
        let mask = 0x1A0034;
        let mask = xlib::SubstructureRedirectMask | xlib::SubstructureNotifyMask | xlib::ButtonPressMask;

        unsafe{
            xlib::XSetErrorHandler(Some(error_handler));
        }
        let left_ptr: u32 = 68;
        libx::define_cursor(self.context, self.context.root, left_ptr);

        libx::ungrab_button(self.context, 0, 0x8000, self.context.root);
        libx::select_input(self.context, self.context.root,
                           mask);

        // init workspace
        self.init_workspaces();

        // load config file, run exec in config
        self.config.load();

        for bind in self.config.bindsyms.keys() {
            let code = libx::keysym_to_keycode(self.context, bind.key);
            libx::grab_key(self.context, code, bind.mask, self.context.root);
        }
        libx::sync(self.context, 0);
    }

    fn init_workspaces(&mut self) {
        self.workspaces.switch_workspace('1', self.context);
    }
}
<commit_msg>set focus to workspace<commit_after>extern crate libc;
extern crate x11;

use std::ptr;
use x11::xlib;
use x11::xlib::Window;
use super::super::libx;

use super::config::Config;
use super::container::{self, Container};
use super::layout;
use super::Workspaces;
use super::handler;

unsafe extern fn error_handler(display: *mut xlib::Display, event: *mut xlib::XErrorEvent) -> libc::c_int {
    // match event.error_code {
    //     xlib::BadAtom => {
    //         println!("bad atom");
    //     }
    //     _ => {}
    // }
    // x11::xmu::XmuSimpleErrorHandler(display, event);
    1
}

extern "C" {
    fn setlocale(category: i32, locale: *const i8) -> *mut i8;
}

fn load_resource(mut context: &mut libx::Context) {
    use std::mem;
    use std::ffi;
    let screen = context.screen_num;
    let root = context.root;
    let display = context.display;
    let mut values: xlib::XGCValues = unsafe{ mem::zeroed() };
    // let gc = libx::create_gc(self.context, self.id, 0, values);
    let gc = libx::default_gc(*context, screen);

    unsafe {
        let black = xlib::XBlackPixel(display, screen);
        let white = xlib::XWhitePixel(display, screen);

        xlib::XSetLineAttributes(display, gc, 5, 0, 0, 0);

        let cmap = xlib::XDefaultColormap(display, screen);
        let mut color: xlib::XColor = mem::zeroed();
        let name = ffi::CString::new("blue").unwrap().as_ptr();
        let r = xlib::XParseColor(display, cmap, name, &mut color);
        xlib::XAllocColor(display, cmap, &mut color);

        context.gc = gc;
        context.focus_bg = black;
        context.focus_fg = color.pixel;
        context.unfocus_bg = black;
        context.unfocus_fg = black;
        context.font_color = white;

        let s = ffi::CString::new("").unwrap().as_ptr();
        let p = setlocale(6, s);
        let res = xlib::XSupportsLocale();
        let res = xlib::XSetLocaleModifiers(s);

        let mut missing_charsets = ptr::null_mut();
        let mut num_missing_charsets: i32 = 0;
        let mut default_string = ptr::null_mut();
        // let name = "-misc-fixed-*-*-*-*-*-130-75-75-*-*-*-*";
        let name = "*";
        let fontbase = ffi::CString::new(name).unwrap().as_ptr();
        let fontset = xlib::XCreateFontSet(display,
                                           fontbase,
                                           &mut missing_charsets,
                                           &mut num_missing_charsets,
                                           &mut default_string);
        if num_missing_charsets > 0 {
            xlib::XFreeStringList(missing_charsets);
        }
        context.fontset = fontset;
    }
}

pub struct WindowManager {
    pub context: libx::Context,
    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	let res = libx::open_display(None);
        let mut context = match res {
            Some(c) => {
                c
            }
            None => {
                panic!("can't open display")
            }
        };

	context.screen_num  = libx::default_screen(context);
	context.root = libx::root_window(context, context.screen_num);
        load_resource(&mut context);

	let mut wm = WindowManager {
            context: context,
            config: Config::new(),
            workspaces: Workspaces::new(context)
        };
        wm
    }

    pub fn clean(&mut self) {
        libx::close_display(self.context);
    }

    pub fn handle_create(&mut self, event: &xlib::XCreateWindowEvent) {
        if event.override_redirect != 0 {
            return;
        }

        let attrs = libx::get_window_attributes(self.context, event.window);
        println!("{} attr {} {}", event.window, attrs.width, attrs.height);
        // get window property
        let n = libx::get_text_property(self.context, event.window, xlib::XA_WM_NAME);
        match n {
            Some(s) => {debug!("create window {} for {}", event.window, s);}
            None => {}
        }

        // let atoms = libx::get_wm_protocols(self.context, event.window);
        // for a in atoms.iter() {
        //     println!("atom {}", a);
        //     let name = libx::get_atom_name(self.context, *a);
        //     match name {
        //         Some(n) => println!("name {}", n),
        //         None => println!("name {}", a),
        //     };
        // }
    }

    pub fn handle_destroy(&mut self, event: &xlib::XDestroyWindowEvent) {
        self.workspaces.remove_window(event.window);
        if self.workspaces.get_focus().is_none() {
            let id = self.workspaces.current().raw_id();
            self.workspaces.set_focus(id);
        }
    }

    pub fn handle_map_request(&mut self, event: &xlib::XMapRequestEvent) {
        // add app top-level window to workspace
        // let window = Window::new(self.context, event.window);
        let manage = Workspaces::can_manage(self.context, event.window);

        if manage {
            debug!("top level window");
            let mut container = Container::from_id(self.context, event.window);
            container.map();
            // container.focus();
            // change attributes before display
            let mask = 0x420010;
            let mask = xlib::EnterWindowMask | xlib::PropertyChangeMask;
            libx::select_input(self.context, container.raw_id(), mask);

            if self.config.titlebar_height > 0 {
                container.titlebar_height = self.config.titlebar_height;
            }
            self.workspaces.insert_window(container);
        }
        else {
            libx::map_window(self.context, event.window);
        }
    }

    pub fn handle_client_message(&mut self, event: &xlib::XClientMessageEvent) {
        println!("message type {}", event.message_type);
        let s = libx::get_atom_name(self.context, event.message_type);
        match s {
            Some(v) => println!("{}", &v),
            None => {}
        }

        match event.format {
            8 => {
                for i in 0..20 {
                    println!("{}", event.data.get_byte(i));
                }
            }
            16 => {
                for i in 0..10 {
                    println!("{}", event.data.get_short(i))
                }
            }
            32 => {
                for i in 0..5 {
                    let a = event.data.get_long(i);
                    if a != 0{
                        let s = libx::get_atom_name(self.context, a as xlib::Atom);
                        match s {
                            Some(v) => println!("{}", v),
                            None => {}
                        }
                    }
                }
            }
            _ => {}
        }
    }

    pub fn handle_button_motion(&mut self, event: &xlib::XMotionEvent) {

    }

    pub fn handle_button_press(&mut self, event: &xlib::XButtonEvent) {

        let id = match self.workspaces.get_container(event.window) {
            Some((_,c)) => {
                let client = c.query_point(event.x, event.y);
                match client {
                    Some(c) => {
                        c.raw_id()
                    }
                    None => { c.raw_id() }
                }
            }
            None => { return }
        };
        self.workspaces.set_focus(id);

        // test if press on boarder
        match self.workspaces.get_container(event.window) {
            Some((_,c)) => {
                let res = c.query_border(event.x, event.y);
                match res {
                    Some(i) => {
                        match c.mode {
                            container::Mode::Normal => {
                                c.mode = container::Mode::Resize(i, event.x, event.y)
                            }
                            container::Mode::Resize(index, x, y) => {

                            }
                            _ => {}
                        }
                    }
                    None => {}
                }
            }
            None => {}
        }
    }

    pub fn handle_button_release(&mut self, event: &xlib::XButtonEvent) {
        match self.workspaces.get_container(event.window) {
            Some((_, c)) => {
                match c.mode {
                    container::Mode::Resize(index, x, y) => {
                        let dx = event.x - x;
                        let dy = event.y - y;
                        let rec = c.rec();
                        let step = match c.direction {
                            layout::Direction::Vertical => {
                                dy as f32 / rec.height as f32
                            }
                            layout::Direction::Horizontal => {
                                dx as f32 / rec.width as f32
                            }
                            _ => { 0.05 }
                        };

                        c.resize_children(index-1, index, step);
                        c.update_layout();
                        c.mode = container::Mode::Normal;
                    }
                    _ => {}
                }
            }
            None => {}
        }
    }

    pub fn handle_key_release(&mut self, event: &xlib::XKeyEvent) {
        if event.state > 0 {
            let sym = libx::lookup_keysym(*event, 0);
            let b = handler::KeyBind {
                key: sym,
                mask: event.state,
            };
            debug!("key {} {}", event.state, sym);

            match self.config.bindsyms.get_mut(&b) {
                Some(handler) => {
                    handler.handle(&mut self.workspaces, self.context);
                }
                None => {
                    println!("no bind");
                }
            }
        }
    }

    pub fn handle_property(&mut self, event: &xlib::XPropertyEvent) {
        let usertime = libx::get_atom(self.context, "_NET_WM_USER_TIME");
        match event.atom {
            usertime => {
                self.workspaces.set_focus(event.window);
            }
        }
    }

    pub fn handle_configure_request(&mut self, event: &xlib::XConfigureRequestEvent) {
        let mut change = xlib::XWindowChanges {
            x: event.x,
            y: event.y,
            width: event.width,
            height: event.height,
            border_width: event.border_width,
            sibling: event.above,
            stack_mode: event.detail
        };
        debug!("config x: {}, y: {}, width: {}, height: {}",
               change.x, change.y, change.width, change.height);
        libx::configure_window(self.context, event.window, event.value_mask as u32, change);
    }

    pub fn handle_focus_in(&mut self, event: &xlib::XFocusChangeEvent) {
        self.workspaces.set_focus(event.window);
    }

    pub fn handle_enter(&mut self, event: &xlib::XCrossingEvent){
        if event.focus == 0 {
            self.workspaces.set_focus(event.window);
        }
    }

    pub fn handle(&mut self, e: xlib::XEvent) {
        let t = e.get_type();
        match t {
            xlib::CreateNotify => {
                let event: xlib::XCreateWindowEvent = From::from(e);
                debug!("create notify {}", event.window);
                self.handle_create(&event);
            }
            xlib::DestroyNotify => {
                let event: xlib::XDestroyWindowEvent = From::from(e);
                debug!("destroy notify {}", event.window);
                self.handle_destroy(&event);
            }
            xlib::MapNotify => {
                let event: xlib::XMapEvent = From::from(e);
                debug!("map notify {}", event.window);
            }
            xlib::UnmapNotify => {
                let event: xlib::XUnmapEvent = From::from(e);
                debug!("unmap notify {}", event.window);
            }
            xlib::MapRequest => {
                let event: xlib::XMapRequestEvent = From::from(e);
                debug!("map request {}", event.window);
                self.handle_map_request(&event);
            }
            xlib::ClientMessage => {
                debug!("client message");
                // let event = cast_event::<xlib::XClientMessageEvent>(&e);
                let event: xlib::XClientMessageEvent = From::from(e);
                self.handle_client_message(&event);
            }
            xlib::KeyRelease => {
                debug!("key release");
                let mut event: xlib::XKeyEvent = From::from(e);
                self.handle_key_release(&mut event);
            }
            xlib::MotionNotify => {
                let mut event: xlib::XMotionEvent = From::from(e);
                debug!("button motion {}", event.window);
                self.handle_button_motion(&event);
            }
            xlib::ButtonRelease => {
                let mut event: xlib::XButtonEvent = From::from(e);
                debug!("button release {}", event.window);
                self.handle_button_release(&event);
            }
            xlib::ButtonPress => {
                let mut event: xlib::XButtonEvent = From::from(e);
                debug!("button press {}", event.window);
                self.handle_button_press(&event);
            }
            xlib::ConfigureNotify => {
                debug!("configure notify");
            }
            xlib::ConfigureRequest =>{
                let mut event: xlib::XConfigureRequestEvent = From::from(e);
                debug!("configure request {}", event.window);
                self.handle_configure_request(&event);
            }
            xlib::FocusIn => {
                let mut event: xlib::XFocusChangeEvent = From::from(e);
                debug!("focus in {}", event.window);
                self.handle_focus_in(&event);

            }
            xlib::FocusOut => {
                let mut event: xlib::XFocusChangeEvent = From::from(e);
                debug!("focus out {}", event.window);
            }
            xlib::EnterNotify => {
                let mut event: xlib::XCrossingEvent = From::from(e);
                debug!("enter window {}", event.window);
                self.handle_enter(&event);
            }
            xlib::PropertyNotify => {
                let mut event: xlib::XPropertyEvent = From::from(e);
                debug!("property notify {}", event.window);
                self.handle_property(&event);
            }
            _ => {
                debug!("unhandled event {}", t);
            }
        }
    }
    pub fn run(&mut self) {
        loop {
            //handle events here
            let mut e = libx::next_event(self.context);
            self.handle(e);
        }
    }

    pub fn init(&mut self) {
        // init connection setting
        let mask = 0x1A0034;
        let mask = xlib::SubstructureRedirectMask | xlib::SubstructureNotifyMask | xlib::ButtonPressMask;

        unsafe{
            xlib::XSetErrorHandler(Some(error_handler));
        }
        let left_ptr: u32 = 68;
        libx::define_cursor(self.context, self.context.root, left_ptr);

        libx::ungrab_button(self.context, 0, 0x8000, self.context.root);
        libx::select_input(self.context, self.context.root,
                           mask);

        // init workspace
        self.init_workspaces();

        // load config file, run exec in config
        self.config.load();

        for bind in self.config.bindsyms.keys() {
            let code = libx::keysym_to_keycode(self.context, bind.key);
            libx::grab_key(self.context, code, bind.mask, self.context.root);
        }
        libx::sync(self.context, 0);
    }

    fn init_workspaces(&mut self) {
        self.workspaces.switch_workspace('1', self.context);
    }
}
<|endoftext|>