<commit_before>// Learning.

use term::Term;
use stroke::Stroke;
use words::{LearnWord, Words};

use std::io::Write;
use termion::color;

pub struct Learn {
    words: Words,
    term: Term,

    // How many of the words are we getting right.  TODO: Store this in the datafile instead of
    // regenerating it each time.
    ratio: f64,
}

impl Learn {
    pub fn new(words: Words, term: Term) -> Learn {
        Learn {
            words: words,
            term: term,
            ratio: 1.0,
        }
    }

    // Consume the learner, returning the wordset contained in it.
    pub fn into_words(self) -> Words {
        self.words
    }

    pub fn run(&mut self) {
        loop {
            // TODO: Check for things that have expired we need to learn.

            let mut word = match self.words.get_learned() {
                None => {
                    match self.words.get_unlearned() {
                        None => {
                            println!("No more words to learn\r");
                            return;
                        },
                        Some(word) => word,
                    }
                }
                Some(word) => word,
            };

            let status = self.single(&mut word);

            // Return the word.
            self.words.push_word(word);

            match status {
                Status::Stopped => break,
                Status::Continue(true) => {
                    self.ratio = self.ratio * 0.97 + 0.03;
                }
                Status::Continue(false) => {
                    self.ratio = self.ratio * 0.97;
                }
            }
            if status == Status::Stopped {
                break;
            }
        }
    }

    // Learn a single word, updating its timing information based on how well it was learned.
    fn single(&mut self, word: &mut LearnWord) -> Status {
        let counts = self.words.get_counts();

        writeln!(self.term, "\r\nActive: {}, Later: {}, Unlearned: {}, Interval {}, Ratio {:.1}\r",
                 counts.active, counts.later, counts.unlearned,
                 humanize_time(word.interval),
                 self.ratio * 100.0).unwrap();
        for b in &counts.buckets {
            writeln!(self.term, "  {:-4}: {:4} {}\r", b.name, b.count,
                     stars(65, b.count, counts.active + counts.later)).unwrap();
        }
        writeln!(self.term, "\r").unwrap();
        self.term.flush().unwrap();

        let mut state = Single::new(&mut self.term, word);
        state.run()
    }
}

// Format an interval (in seconds) in terms of nicer units.
fn humanize_time(interval: f64) -> String {
    let mut val = interval;
    for unit in UNITS {
        if val < unit.div {
            return format!("{:.1} {}", val, unit.name);
        }
        val /= unit.div;
    }
    // Out of bounds, return the unmodified time.
    format!("{:.1} seconds", interval)
}

struct UnitEntry {
    name: &'static str,
    div: f64,
}

static UNITS: &'static [UnitEntry] = &[
    UnitEntry{ name: "seconds", div: 60.0 },
    UnitEntry{ name: "minutes", div: 60.0 },
    UnitEntry{ name: "hours", div: 24.0 },
    UnitEntry{ name: "days", div: 365.0 },
    UnitEntry{ name: "months", div: 12.0 },
    UnitEntry{ name: "years", div: 1.0e6 },
];

// Print a line of stars resembling a histogram bar.  `len` is the number of stars to use, a is the
// number in question, and total is the expected total.
fn stars(len: usize, value: usize, total: usize) -> String {
    let mut buf = String::new();
    buf.push('|');
    let thresh = value as f64 / total as f64 * len as f64;
    for i in 0 .. len {
        if (i as f64) < thresh {
            buf.push('*');
        } else {
            buf.push(' ');
        };
    }
    buf.push('|');
    buf
}

struct Single<'t, 'w> {
    term: &'t mut Term,
    word: &'w mut LearnWord,
    user: Vec<Stroke>,
    errors: u32,
}

impl<'t, 'w> Single<'t, 'w> {
    fn new<'tt, 'ww>(term: &'tt mut Term, word: &'ww mut LearnWord) -> Single<'tt, 'ww> {
        Single {
            term: term,
            word: word,
            user: vec![],
            errors: 0,
        }
    }

    fn prompt(&mut self) {
        write!(self.term, "\r\x1b[J{:20}: {}{}",
               self.word.english,
               if self.word.strokes == self.user {
                   if self.errors == 0 { '✓' } else { '✗' }
               } else { ' ' },
               slashed(&self.user, &self.word.strokes)).unwrap();
        if self.errors > 0 {
            write!(self.term, "  ({})", slashed(&self.word.strokes, &self.word.strokes)).unwrap();
        }
        self.term.flush().unwrap();
    }

    fn run(&mut self) -> Status {
        let result;
        loop {
            self.prompt();
            if self.word.strokes == self.user {
                result = Status::Continue(self.errors == 0);
                break;
            }

            let stroke = match self.term.read_stroke().unwrap() {
                None => { result = Status::Stopped; break; }
                Some(st) => st,
            };
            if stroke.is_star() {
                self.user.pop();
            } else {
                self.user.push(stroke);
                let pos = self.user.len();
                if pos > self.word.strokes.len() ||
                    self.user[pos-1] != self.word.strokes[pos-1]
                {
                    self.errors += 1;
                }
            }
        }

        match result {
            Status::Continue(right) => {
                if right {
                    self.word.correct();
                } else {
                    self.word.incorrect();
                }

                writeln!(self.term, "\r\nNew interval {}\r", humanize_time(self.word.interval)).unwrap();
            }
            Status::Stopped => {
                writeln!(self.term, "\r").unwrap();
            }
        }
        self.term.flush().unwrap();
        result
    }
}

// Generate a slash separated version of the given stroke list.
fn slashed(strokes: &[Stroke], expected: &[Stroke]) -> String {
    let mut buf = vec![];
    let mut first = true;

    for (i, st) in strokes.iter().enumerate() {
        if !first {
            buf.push(b'/');
        }
        first = false;

        let correct = expected.get(i) == Some(st);
        if !correct {
            write!(&mut buf, "{}{}",
                   color::Bg(color::LightRed),
                   color::Fg(color::Black)).unwrap();
        }
        write!(&mut buf, "{}", st).unwrap();
        if !correct {
            write!(&mut buf, "{}{}",
                   color::Bg(color::Reset),
                   color::Fg(color::Reset)).unwrap();
        }
    }
    String::from_utf8(buf).unwrap()
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Status {
    // Continue learning, and returns if the word is correct.
    Continue(bool),
    Stopped,
}
<commit_msg>Only update ratio on learned words<commit_after>// Learning.

use term::Term;
use stroke::Stroke;
use words::{LearnWord, Words};

use std::io::Write;
use termion::color;

pub struct Learn {
    words: Words,
    term: Term,

    // How many of the words are we getting right.  TODO: Store this in the datafile instead of
    // regenerating it each time.
    ratio: f64,
}

impl Learn {
    pub fn new(words: Words, term: Term) -> Learn {
        Learn {
            words: words,
            term: term,
            ratio: 1.0,
        }
    }

    // Consume the learner, returning the wordset contained in it.
    pub fn into_words(self) -> Words {
        self.words
    }

    pub fn run(&mut self) {
        loop {
            // TODO: Check for things that have expired we need to learn.

            let mut word = match self.words.get_learned() {
                None => {
                    match self.words.get_unlearned() {
                        None => {
                            println!("No more words to learn\r");
                            return;
                        },
                        Some(word) => word,
                    }
                }
                Some(word) => word,
            };

            let status = self.single(&mut word);

            // Update the stastics, but only of words that have some chance to be learned.  The
            // interval reaching an hour seems like a good guess for this.
            if word.interval > 60.0 * 60.0 {
                match status {
                    Status::Stopped => break,
                    Status::Continue(true) => {
                        self.ratio = self.ratio * 0.97 + 0.03;
                    }
                    Status::Continue(false) => {
                        self.ratio = self.ratio * 0.97;
                    }
                }
            }

            // Return the word.
            self.words.push_word(word);
        }
    }

    // Learn a single word, updating its timing information based on how well it was learned.
    fn single(&mut self, word: &mut LearnWord) -> Status {
        let counts = self.words.get_counts();

        writeln!(self.term, "\r\nActive: {}, Later: {}, Unlearned: {}, Interval {}, Ratio {:.1}\r",
                 counts.active, counts.later, counts.unlearned,
                 humanize_time(word.interval),
                 self.ratio * 100.0).unwrap();
        for b in &counts.buckets {
            writeln!(self.term, "  {:-4}: {:4} {}\r", b.name, b.count,
                     stars(65, b.count, counts.active + counts.later)).unwrap();
        }
        writeln!(self.term, "\r").unwrap();
        self.term.flush().unwrap();

        let mut state = Single::new(&mut self.term, word);
        state.run()
    }
}

// Format an interval (in seconds) in terms of nicer units.
fn humanize_time(interval: f64) -> String {
    let mut val = interval;
    for unit in UNITS {
        if val < unit.div {
            return format!("{:.1} {}", val, unit.name);
        }
        val /= unit.div;
    }
    // Out of bounds, return the unmodified time.
    format!("{:.1} seconds", interval)
}

struct UnitEntry {
    name: &'static str,
    div: f64,
}

static UNITS: &'static [UnitEntry] = &[
    UnitEntry{ name: "seconds", div: 60.0 },
    UnitEntry{ name: "minutes", div: 60.0 },
    UnitEntry{ name: "hours", div: 24.0 },
    UnitEntry{ name: "days", div: 365.0 },
    UnitEntry{ name: "months", div: 12.0 },
    UnitEntry{ name: "years", div: 1.0e6 },
];

// Print a line of stars resembling a histogram bar.  `len` is the number of stars to use, a is the
// number in question, and total is the expected total.
fn stars(len: usize, value: usize, total: usize) -> String {
    let mut buf = String::new();
    buf.push('|');
    let thresh = value as f64 / total as f64 * len as f64;
    for i in 0 .. len {
        if (i as f64) < thresh {
            buf.push('*');
        } else {
            buf.push(' ');
        };
    }
    buf.push('|');
    buf
}

struct Single<'t, 'w> {
    term: &'t mut Term,
    word: &'w mut LearnWord,
    user: Vec<Stroke>,
    errors: u32,
}

impl<'t, 'w> Single<'t, 'w> {
    fn new<'tt, 'ww>(term: &'tt mut Term, word: &'ww mut LearnWord) -> Single<'tt, 'ww> {
        Single {
            term: term,
            word: word,
            user: vec![],
            errors: 0,
        }
    }

    fn prompt(&mut self) {
        write!(self.term, "\r\x1b[J{:20}: {}{}",
               self.word.english,
               if self.word.strokes == self.user {
                   if self.errors == 0 { '✓' } else { '✗' }
               } else { ' ' },
               slashed(&self.user, &self.word.strokes)).unwrap();
        if self.errors > 0 {
            write!(self.term, "  ({})", slashed(&self.word.strokes, &self.word.strokes)).unwrap();
        }
        self.term.flush().unwrap();
    }

    fn run(&mut self) -> Status {
        let result;
        loop {
            self.prompt();
            if self.word.strokes == self.user {
                result = Status::Continue(self.errors == 0);
                break;
            }

            let stroke = match self.term.read_stroke().unwrap() {
                None => { result = Status::Stopped; break; }
                Some(st) => st,
            };
            if stroke.is_star() {
                self.user.pop();
            } else {
                self.user.push(stroke);
                let pos = self.user.len();
                if pos > self.word.strokes.len() ||
                    self.user[pos-1] != self.word.strokes[pos-1]
                {
                    self.errors += 1;
                }
            }
        }

        match result {
            Status::Continue(right) => {
                if right {
                    self.word.correct();
                } else {
                    self.word.incorrect();
                }

                writeln!(self.term, "\r\nNew interval {}\r", humanize_time(self.word.interval)).unwrap();
            }
            Status::Stopped => {
                writeln!(self.term, "\r").unwrap();
            }
        }
        self.term.flush().unwrap();
        result
    }
}

// Generate a slash separated version of the given stroke list.
fn slashed(strokes: &[Stroke], expected: &[Stroke]) -> String {
    let mut buf = vec![];
    let mut first = true;

    for (i, st) in strokes.iter().enumerate() {
        if !first {
            buf.push(b'/');
        }
        first = false;

        let correct = expected.get(i) == Some(st);
        if !correct {
            write!(&mut buf, "{}{}",
                   color::Bg(color::LightRed),
                   color::Fg(color::Black)).unwrap();
        }
        write!(&mut buf, "{}", st).unwrap();
        if !correct {
            write!(&mut buf, "{}{}",
                   color::Bg(color::Reset),
                   color::Fg(color::Reset)).unwrap();
        }
    }
    String::from_utf8(buf).unwrap()
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Status {
    // Continue learning, and returns if the word is correct.
    Continue(bool),
    Stopped,
}
<|endoftext|>


<commit_before>use std::str::Chars;
use std::iter::Peekable;
use errors::{CalcrResult, CalcrError};
use token::Token;
use token::TokVal::*;
use ast::OpKind::*;

pub fn lex_equation(eq: &String) -> CalcrResult<Vec<Token>> {
    let mut lexer = Lexer {
        pos: 0,
        iter: eq.chars().peekable(),
    };
    lexer.lex_equation()
}

pub struct Lexer<'a> {
    pos: usize,
    iter: Peekable<Chars<'a>>,
}

impl<'a> Lexer<'a> {
    pub fn lex_equation(&mut self) -> CalcrResult<Vec<Token>> {
        let mut out = Vec::new();
        loop {
            self.consume_whitespace();
            let tok = match self.peek_char() {
                Some(ch) if ch.is_numeric() => try!(self.lex_number()),
                Some(ch) if ch.is_alphabetic() => try!(self.lex_name()),
                Some(_) => try!(self.lex_single_char()),
                None => break,
            };
            out.push(tok);
        }
        Ok(out)
    }

    fn lex_number(&mut self) -> CalcrResult<Token> {
        let num_str = self.consume_while(|ch| ch.is_numeric() || ch == '.');
        if let Ok(num) = num_str.parse::<f64>() {
            Ok(Token {
                val: Num(num),
                span: (self.pos - num_str.len(), self.pos),
            })
        } else {
            Err(CalcrError {
                desc: format!("Invalid number: {}", num_str),
                span: Some((self.pos - num_str.len(), self.pos)),
            })
        }
    }

    fn lex_name(&mut self) -> CalcrResult<Token> {
        let name_str = self.consume_while(|ch| ch.is_alphabetic());
        let name_len = name_str.chars().count();
        Ok(Token {
            val: Name(name_str),
            span: (self.pos - name_len, self.pos),
        })
    }

    fn lex_single_char(&mut self) -> CalcrResult<Token> {
        let val = match self.consume_char() {
            '+' => Op(Plus),
            '-' => Op(Minus),
            '*' => Op(Mult),
            '/' => Op(Div),
            '^' => Op(Pow),
            '!' => Op(Fact),
            '√' => Name("sqrt".to_string()),
            '(' => ParenOpen,
            ')' => ParenClose,
            '|' => AbsDelim,
            ch => return Err(CalcrError {
                desc: format!("Invalid char: {}", ch),
                span: Some((self.pos - 1, self.pos)),
            }),
        };
        Ok(Token {
            val: val,
            span: (self.pos - 1, self.pos),
        })
    }

    /// Peeks at the next `char` and returns `Some` if one was found, or `None` if none are left
    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().map(|ch| *ch)
    }

    /// Consumes a `char` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more chars to consume
    fn consume_char(&mut self) -> char {
        let ch = self.iter.next();
        self.pos += 1;
        ch.unwrap().to_lowercase().next().unwrap()
    }

    /// Consumes `char`s long as `pred` returns true and we are not eof
    ///
    /// The `char`s are returned as a `String`. Note that unlike `consume_char` this function will
    /// not panic.
    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        loop {
            match self.peek_char() {
                Some(ch) if pred(ch) => out.push(self.consume_char()),
                _ => break,
            }
        }
        out
    }

    /// Consumes any current whitespace
    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }
}

#[cfg(test)]
mod tests {
    use super::lex_equation;
    use token::Token;
    use token::TokVal::*;
    use ast::OpKind::*;

    #[test]
    fn empty() {
        let eq = "".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!()));
    }

    #[test]
    fn single_char() {
        let eq = "2".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Num(2.0), span: (0, 1) })));
    }

    #[test]
    fn utf8() {
        let eq = "π𐍈".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Name(eq), span: (0, 2) })));
    }

    #[test]
    fn ops() {
        let eq = "+-*/!^".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Op(Plus), span: (0,1) },
                                 Token { val: Op(Minus), span: (1,2) },
                                 Token { val: Op(Mult), span: (2,3) },
                                 Token { val: Op(Div), span: (3,4) },
                                 Token { val: Op(Fact), span: (4,5) },
                                 Token { val: Op(Pow), span: (5,6) })));
    }

    #[test]
    fn invalid_char() {
        let eq = "?".to_string();
        let err = lex_equation(&eq);
        assert!(err.is_err());
    }
}<commit_msg>Allow numbers in names<commit_after>use std::str::Chars;
use std::iter::Peekable;
use errors::{CalcrResult, CalcrError};
use token::Token;
use token::TokVal::*;
use ast::OpKind::*;

pub fn lex_equation(eq: &String) -> CalcrResult<Vec<Token>> {
    let mut lexer = Lexer {
        pos: 0,
        iter: eq.chars().peekable(),
    };
    lexer.lex_equation()
}

pub struct Lexer<'a> {
    pos: usize,
    iter: Peekable<Chars<'a>>,
}

impl<'a> Lexer<'a> {
    pub fn lex_equation(&mut self) -> CalcrResult<Vec<Token>> {
        let mut out = Vec::new();
        loop {
            self.consume_whitespace();
            let tok = match self.peek_char() {
                Some(ch) if ch.is_numeric() => try!(self.lex_number()),
                Some(ch) if ch.is_alphabetic() => try!(self.lex_name()),
                Some(_) => try!(self.lex_single_char()),
                None => break,
            };
            out.push(tok);
        }
        Ok(out)
    }

    fn lex_number(&mut self) -> CalcrResult<Token> {
        let num_str = self.consume_while(|ch| ch.is_numeric() || ch == '.');
        if let Ok(num) = num_str.parse::<f64>() {
            Ok(Token {
                val: Num(num),
                span: (self.pos - num_str.len(), self.pos),
            })
        } else {
            Err(CalcrError {
                desc: format!("Invalid number: {}", num_str),
                span: Some((self.pos - num_str.len(), self.pos)),
            })
        }
    }

    fn lex_name(&mut self) -> CalcrResult<Token> {
        let name_str = self.consume_while(|ch| ch.is_alphabetic() || ch.is_numeric());
        let name_len = name_str.chars().count();
        Ok(Token {
            val: Name(name_str),
            span: (self.pos - name_len, self.pos),
        })
    }

    fn lex_single_char(&mut self) -> CalcrResult<Token> {
        let val = match self.consume_char() {
            '+' => Op(Plus),
            '-' => Op(Minus),
            '*' => Op(Mult),
            '/' => Op(Div),
            '^' => Op(Pow),
            '!' => Op(Fact),
            '√' => Name("sqrt".to_string()),
            '(' => ParenOpen,
            ')' => ParenClose,
            '|' => AbsDelim,
            ch => return Err(CalcrError {
                desc: format!("Invalid char: {}", ch),
                span: Some((self.pos - 1, self.pos)),
            }),
        };
        Ok(Token {
            val: val,
            span: (self.pos - 1, self.pos),
        })
    }

    /// Peeks at the next `char` and returns `Some` if one was found, or `None` if none are left
    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().map(|ch| *ch)
    }

    /// Consumes a `char` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more chars to consume
    fn consume_char(&mut self) -> char {
        let ch = self.iter.next();
        self.pos += 1;
        ch.unwrap().to_lowercase().next().unwrap()
    }

    /// Consumes `char`s long as `pred` returns true and we are not eof
    ///
    /// The `char`s are returned as a `String`. Note that unlike `consume_char` this function will
    /// not panic.
    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        loop {
            match self.peek_char() {
                Some(ch) if pred(ch) => out.push(self.consume_char()),
                _ => break,
            }
        }
        out
    }

    /// Consumes any current whitespace
    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }
}

#[cfg(test)]
mod tests {
    use super::lex_equation;
    use token::Token;
    use token::TokVal::*;
    use ast::OpKind::*;

    #[test]
    fn empty() {
        let eq = "".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!()));
    }

    #[test]
    fn single_char() {
        let eq = "2".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Num(2.0), span: (0, 1) })));
    }

    #[test]
    fn utf8() {
        let eq = "π𐍈".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Name(eq), span: (0, 2) })));
    }

    #[test]
    fn ops() {
        let eq = "+-*/!^".to_string();
        let toks = lex_equation(&eq);
        assert_eq!(toks, Ok(vec!(Token { val: Op(Plus), span: (0,1) },
                                 Token { val: Op(Minus), span: (1,2) },
                                 Token { val: Op(Mult), span: (2,3) },
                                 Token { val: Op(Div), span: (3,4) },
                                 Token { val: Op(Fact), span: (4,5) },
                                 Token { val: Op(Pow), span: (5,6) })));
    }

    #[test]
    fn invalid_char() {
        let eq = "?".to_string();
        let err = lex_equation(&eq);
        assert!(err.is_err());
    }
}<|endoftext|>


<commit_before>use futures::{Async, Future, Poll, Sink, Stream};
use futures::stream;
use futures::sync::mpsc::{self, Receiver, Sender};
use std::io::BufRead;
use std::thread;
use std::time::{Duration, Instant};
use {Error, Result};

/// A stream over each non-empty line on a `BufRead`.
pub struct Lines {
    rx: Receiver<Result<String>>,
    timer: Instant,
}

/// Adds to `Sender` an ability to send an `Error` to its corresponding `Receiver` while panicking.
struct SenderPanicGuard(Option<Sender<Result<String>>>);

/// Returns a stream over each non-empty line on `a`.
#[allow(unused_variables)]
pub fn lines<A: BufRead + Send + 'static>(a: A) -> Lines {
    let (tx, rx) = mpsc::channel(8);

    thread::Builder::new().name("twitter_user_stream_sender".into()).spawn(move || {
        let txg = SenderPanicGuard(Some(tx.clone()));
        let stream = stream::iter(a.lines().map(|r| Ok(r.map_err(Error::from))));
        info!("starting to listen on a stream");
        tx.send_all(stream).wait().unwrap();
    }).unwrap();

    Lines {
        rx: rx,
        timer: Instant::now(),
    }
}

impl Stream for Lines {
    type Item = String;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<String>, Error> {
        loop {
            match self.rx.poll().expect("Receiver failed") {
                Async::Ready(Some(line)) => {
                    info!("duration since last message: {}", {
                        let elapsed = self.timer.elapsed();
                        elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000f64
                    });
                    self.timer = Instant::now();
                    let line = line?;
                    if !line.is_empty() {
                        return Ok(Some(line).into());
                    }
                },
                Async::Ready(None) => return Ok(None.into()),
                Async::NotReady => {
                    if self.timer.elapsed() < Duration::from_secs(95) {
                        return Ok(Async::NotReady);
                    } else {
                        return Err(Error::TimedOut.into());
                    }
                },
            }
        }
    }
}

impl Drop for SenderPanicGuard {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        if thread::panicking() {
            if let Some(tx) = self.0.take() {
                tx.send(Err(Error::InternalPanicError)).wait();
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io::Cursor;
    use super::*;

    #[test]
    fn lines_test() {
        let input = b"\
            {\"friends\":[123456789,234567890,345678901,4567890123,567890123,678901234]}

\
            {\"event\":\"favorite\",\"created_at\":\"Sun Jan 01 00:00:00 +0000 2017\",\"source\":{\"id\":1234567890,\"id_str\":\"1234567890\",\"name\":\"test\",\"screen_name\":\"twitter_test\",\"location\":\"somewhere\",\"url\":null,\"description\":\"test\",\"protected\":false,\"followers_count\":123456789,\"friends_count\":123,\"listed_count\":12,\"created_at\":\"Sat Dec 01 00:00:00 +0000 2016\",\"favourites_count\":1,\"utc_offset\":00000,\"time_zone\":\"London\",\"geo_enabled\":false,\"verified\":false,\"statuses_count\":1234,\"lang\":\"en\",\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\/\\/abs.twimg.com\\/images\\/themes\\/theme1\\/bg.png\",\"profile_background_image_url_https\":\"https:\\/\\/abs.twimg.com\\/images\\/themes\\/theme1\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_0_normal.png\",\"profile_image_url_https\":\"https:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_0_normal.png\",\"profile_banner_url\":null,\"profile_link_color\":\"000000\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"default_profile\":false,\"default_profile_image\":true,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"target\":{\"id\":2345678901,\"id_str\":\"2345678901\",\"name\":\"Test\",\"screen_name\":\"test_twitter\",\"location\":\"Twitter\",\"url\":\"https://example.com/\",\"description\":\"Test\",\"protected\":false,\"followers_count\":12,\"friends_count\":1,\"listed_count\":0,\"created_at\":\"Fri Jan 01 00:00:00 +0000 2016\",\"favourites_count\":1234,\"utc_offset\":00000,\"time_zone\":\"London\",\"geo_enabled\":false,\"verified\":false,\"statuses_count\":12,\"lang\":\"en\",\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http://abs.twimg.com/images/themes//theme1/bg.png\",\"profile_background_image_url_https\":\"https://abs.twimg.com/images/themes//theme1/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_1_normal.png\",\"profile_image_url_https\":\"https:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_1_normal.png\",\"profile_banner_url\":\"https:\\/\\/pbs.twimg.com\\/profile_banners\\/6253282\\/1347394302\",\"profile_link_color\":\"FFFFFF\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":true,\"default_profile\":false,\"default_profile_image\":true,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"none\"}}
\
            {\"event\":\"unfavorite\",\"created_at\":\"Sun Jan 01 00:00:00 +0000 2017\",\"source\":{\"id\":1234567890,\"id_str\":\"1234567890\",\"name\":\"test\",\"screen_name\":\"twitter_test\",\"location\":\"somewhere\",\"url\":null,\"description\":\"test\",\"protected\":false,\"followers_count\":123456789,\"friends_count\":123,\"listed_count\":12,\"created_at\":\"Sat Dec 01 00:00:00 +0000 2016\",\"favourites_count\":1,\"utc_offset\":00000,\"time_zone\":\"London\",\"geo_enabled\":false,\"verified\":false,\"statuses_count\":1234,\"lang\":\"en\",\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\/\\/abs.twimg.com\\/images\\/themes\\/theme1\\/bg.png\",\"profile_background_image_url_https\":\"https:\\/\\/abs.twimg.com\\/images\\/themes\\/theme1\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_0_normal.png\",\"profile_image_url_https\":\"https:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_0_normal.png\",\"profile_banner_url\":null,\"profile_link_color\":\"000000\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"default_profile\":false,\"default_profile_image\":true,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"target\":{\"id\":2345678901,\"id_str\":\"2345678901\",\"name\":\"Test\",\"screen_name\":\"test_twitter\",\"location\":\"Twitter\",\"url\":\"https://example.com/\",\"description\":\"Test\",\"protected\":false,\"followers_count\":12,\"friends_count\":1,\"listed_count\":0,\"created_at\":\"Fri Jan 01 00:00:00 +0000 2016\",\"favourites_count\":1234,\"utc_offset\":00000,\"time_zone\":\"London\",\"geo_enabled\":false,\"verified\":false,\"statuses_count\":12,\"lang\":\"en\",\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http://abs.twimg.com/images/themes//theme1/bg.png\",\"profile_background_image_url_https\":\"https://abs.twimg.com/images/themes//theme1/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_1_normal.png\",\"profile_image_url_https\":\"https:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_1_normal.png\",\"profile_banner_url\":\"https:\\/\\/pbs.twimg.com\\/profile_banners\\/6253282\\/1347394302\",\"profile_link_color\":\"FFFFFF\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":true,\"default_profile\":false,\"default_profile_image\":true,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"none\"}}

\
            ";

        let mut iter = lines(Cursor::new(input.to_vec())).wait();

        assert_eq!(
            &iter.next().unwrap().unwrap(),
            "{\"friends\":[123456789,234567890,345678901,4567890123,567890123,678901234]}"
        );
        assert_eq!(
            &iter.next().unwrap().unwrap(),
            "{\"event\":\"favorite\",\"created_at\":\"Sun Jan 01 00:00:00 +0000 2017\",\"source\":{\"id\":1234567890,\"id_str\":\"1234567890\",\"name\":\"test\",\"screen_name\":\"twitter_test\",\"location\":\"somewhere\",\"url\":null,\"description\":\"test\",\"protected\":false,\"followers_count\":123456789,\"friends_count\":123,\"listed_count\":12,\"created_at\":\"Sat Dec 01 00:00:00 +0000 2016\",\"favourites_count\":1,\"utc_offset\":00000,\"time_zone\":\"London\",\"geo_enabled\":false,\"verified\":false,\"statuses_count\":1234,\"lang\":\"en\",\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\/\\/abs.twimg.com\\/images\\/themes\\/theme1\\/bg.png\",\"profile_background_image_url_https\":\"https:\\/\\/abs.twimg.com\\/images\\/themes\\/theme1\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_0_normal.png\",\"profile_image_url_https\":\"https:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_0_normal.png\",\"profile_banner_url\":null,\"profile_link_color\":\"000000\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"default_profile\":false,\"default_profile_image\":true,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"target\":{\"id\":2345678901,\"id_str\":\"2345678901\",\"name\":\"Test\",\"screen_name\":\"test_twitter\",\"location\":\"Twitter\",\"url\":\"https://example.com/\",\"description\":\"Test\",\"protected\":false,\"followers_count\":12,\"friends_count\":1,\"listed_count\":0,\"created_at\":\"Fri Jan 01 00:00:00 +0000 2016\",\"favourites_count\":1234,\"utc_offset\":00000,\"time_zone\":\"London\",\"geo_enabled\":false,\"verified\":false,\"statuses_count\":12,\"lang\":\"en\",\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http://abs.twimg.com/images/themes//theme1/bg.png\",\"profile_background_image_url_https\":\"https://abs.twimg.com/images/themes//theme1/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_1_normal.png\",\"profile_image_url_https\":\"https:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_1_normal.png\",\"profile_banner_url\":\"https:\\/\\/pbs.twimg.com\\/profile_banners\\/6253282\\/1347394302\",\"profile_link_color\":\"FFFFFF\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":true,\"default_profile\":false,\"default_profile_image\":true,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"none\"}}"
        );
        assert_eq!(
            &iter.next().unwrap().unwrap(),
            "{\"event\":\"unfavorite\",\"created_at\":\"Sun Jan 01 00:00:00 +0000 2017\",\"source\":{\"id\":1234567890,\"id_str\":\"1234567890\",\"name\":\"test\",\"screen_name\":\"twitter_test\",\"location\":\"somewhere\",\"url\":null,\"description\":\"test\",\"protected\":false,\"followers_count\":123456789,\"friends_count\":123,\"listed_count\":12,\"created_at\":\"Sat Dec 01 00:00:00 +0000 2016\",\"favourites_count\":1,\"utc_offset\":00000,\"time_zone\":\"London\",\"geo_enabled\":false,\"verified\":false,\"statuses_count\":1234,\"lang\":\"en\",\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"000000\",\"profile_background_image_url\":\"http:\\/\\/abs.twimg.com\\/images\\/themes\\/theme1\\/bg.png\",\"profile_background_image_url_https\":\"https:\\/\\/abs.twimg.com\\/images\\/themes\\/theme1\\/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_0_normal.png\",\"profile_image_url_https\":\"https:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_0_normal.png\",\"profile_banner_url\":null,\"profile_link_color\":\"000000\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":false,\"default_profile\":false,\"default_profile_image\":true,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"regular\"},\"target\":{\"id\":2345678901,\"id_str\":\"2345678901\",\"name\":\"Test\",\"screen_name\":\"test_twitter\",\"location\":\"Twitter\",\"url\":\"https://example.com/\",\"description\":\"Test\",\"protected\":false,\"followers_count\":12,\"friends_count\":1,\"listed_count\":0,\"created_at\":\"Fri Jan 01 00:00:00 +0000 2016\",\"favourites_count\":1234,\"utc_offset\":00000,\"time_zone\":\"London\",\"geo_enabled\":false,\"verified\":false,\"statuses_count\":12,\"lang\":\"en\",\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"FFFFFF\",\"profile_background_image_url\":\"http://abs.twimg.com/images/themes//theme1/bg.png\",\"profile_background_image_url_https\":\"https://abs.twimg.com/images/themes//theme1/bg.png\",\"profile_background_tile\":false,\"profile_image_url\":\"http:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_1_normal.png\",\"profile_image_url_https\":\"https:\\/\\/abs.twimg.com\\/sticky\\/default_profile_images\\/default_profile_1_normal.png\",\"profile_banner_url\":\"https:\\/\\/pbs.twimg.com\\/profile_banners\\/6253282\\/1347394302\",\"profile_link_color\":\"FFFFFF\",\"profile_sidebar_border_color\":\"000000\",\"profile_sidebar_fill_color\":\"000000\",\"profile_text_color\":\"000000\",\"profile_use_background_image\":true,\"default_profile\":false,\"default_profile_image\":true,\"following\":null,\"follow_request_sent\":null,\"notifications\":null,\"translator_type\":\"none\"}}"
        );
        assert!(iter.next().is_none());
    }
}
<commit_msg>Remove from Lines the responsibility to strip empty lines<commit_after>use futures::{Async, Future, Poll, Sink, Stream};
use futures::stream::{self, AndThen, MapErr};
use futures::sync::mpsc::{self, Receiver, Sender};
use std::io::BufRead;
use std::thread;
use std::time::{Duration, Instant};
use Error;

type Result = ::Result<String>;

/// A stream over each non-empty line on a `BufRead`.
pub type Lines = AndThen<
    MapErr<
        Receiver<Result>,
        fn(()) -> Error
    >,
    fn(Result) -> Result,
    Result
>;

/// Adds to `Sender` an ability to send an `Error` to its corresponding `Receiver` while panicking.
struct SenderPanicGuard(Option<Sender<Result>>);

/// Returns a stream over each non-empty line on `a`.
#[allow(unused_variables)]
pub fn lines<A: BufRead + Send + 'static>(a: A) -> Lines {
    let (tx, rx) = mpsc::channel(8);

    thread::Builder::new().name("twitter_user_stream_sender".into()).spawn(move || {
        let txg = SenderPanicGuard(Some(tx.clone()));
        let stream = stream::iter(a.lines().map(|r| Ok(r.map_err(Error::from))));
        tx.send_all(stream).wait().unwrap();
    }).unwrap();

    let rx = rx.map_err(err_map as fn(_) -> _).and_then(id as fn(_) -> _);
    fn err_map(_: ()) -> Error { panic!("Receiver failed") }
    fn id(r: Result) -> Result { r }

    rx
}

impl Drop for SenderPanicGuard {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        if thread::panicking() {
            if let Some(tx) = self.0.take() {
                tx.send(Err(Error::InternalPanicError)).wait();
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use super::daemon::*;
use std::io::{Error, ErrorKind};
use std::sync::mpsc::channel;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::Sender;
use std::sync::StaticMutex;
use std::sync::MUTEX_INIT;

static LOCK: StaticMutex = MUTEX_INIT;

static mut daemon_static:*mut DaemonStatic = 0 as *mut DaemonStatic;

struct DaemonStatic
{
	holder: Box<DaemonFunc>,
}

trait DaemonFunc
{
	fn exec(&mut self) -> Result<(), Error>;
	fn send(&mut self, state: State) -> Result<(), Error>;
	fn take_tx(&mut self) -> Option<Sender<State>>;
}

struct DaemonFuncHolder <F: FnOnce(Receiver<State>)>
{
	tx: Option<Sender<State>>,
	func: Option<(F, Receiver<State>)>,
}

impl <F: FnOnce(Receiver<State>)> DaemonFunc for DaemonFuncHolder<F>
{
	fn exec(&mut self) -> Result<(), Error>
	{
		match self.func.take()
		{
			Some((func, rx)) => {
				func(rx);
				Ok(())
			}
			None => Err(Error::new(ErrorKind::Other, "INTERNAL ERROR: Can't unwrap daemon function"))
		}
	}

	fn send(&mut self, state: State) -> Result<(), Error>
	{
		match self.tx
		{
			Some(ref tx) => match tx.send(state)
			{
				Err(e) => Err(format! ("Send new state error: {:?}", e)),
				Ok(_) => Ok(()),
			},
			None => Err(format! ("Service is already exited")),
		}
	}

	fn take_tx(&mut self) -> Option<Sender<State>>
	{
		self.tx.take()
	}
}

impl DaemonRunner for Daemon
{
	fn run<F: 'static + FnOnce(Receiver<State>)>(&self, func: F) -> Result<(), Error> {
		let (tx, rx) = channel();
		tx.send(State::Start).unwrap();
		let mut daemon = DaemonStatic
		{
			holder: Box::new(DaemonFuncHolder
			{
				tx: Some(tx),
				func: Some((func, rx)),
			}),
		};
		try! (guard_compare_and_swap(daemon_null(), &mut daemon));
		let result = daemon_console(&mut daemon);
		try! (guard_compare_and_swap(&mut daemon, daemon_null()));
		result
	}
}

fn guard_compare_and_swap(old_value: *mut DaemonStatic, new_value: *mut DaemonStatic) -> Result<(), Error>
{
	unsafe
	{
		let guard = LOCK.lock().unwrap();
		if daemon_static != old_value
		{
			return Err("This function is not reentrant.".to_string());
		}
		daemon_static = new_value;
		let _ = guard;
	}
	Ok(())
}

fn daemon_console(daemon: &mut DaemonStatic) -> Result<(), Error>
{
	let result;
	unsafe
	{
		//if SetConsoleCtrlHandler(Some(console_handler), TRUE) == FALSE
		//{
		//	return Err(format! ("Failed SetConsoleCtrlHandler: {}", error_string(GetLastError() as i32)));
		//}
		result = daemon.holder.exec();
		//if SetConsoleCtrlHandler(Some(console_handler), FALSE) == FALSE
		//{
		//	return Err(format! ("Failed SetConsoleCtrlHandler: {}", error_string(GetLastError() as i32)));
		//}
	}
	result
}

unsafe extern "system" fn signal_handler(sig: libc::c_int)
{
	let guard = LOCK.lock().unwrap();
	if daemon_static != daemon_null()
	{
		let daemon = &mut *daemon_static;
		return match daemon.holder.take_tx()
		{
			Some(ref tx) => {
				let _ = tx.send(State::Stop);
			}
			None => ()
		}
	}
	let _ = guard;
}

fn daemon_null() -> *mut DaemonStatic {
	0 as *mut DaemonStatic
}

extern "C" {
	fn raise(sig: libc::c_int) -> libc::c_int;
	fn signal(sig: libc::c_int, handler: *const libc::c_void) -> libc::c_int;
	fn kill(pid: libc::pid_t, sig: libc::c_int) -> libc::c_int;
}
<commit_msg>Fix Linux compilation<commit_after>extern crate libc;

use super::daemon::*;
use std::io::{Error, ErrorKind};
use std::sync::mpsc::channel;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::Sender;
use std::sync::StaticMutex;
use std::sync::MUTEX_INIT;

static LOCK: StaticMutex = MUTEX_INIT;

static mut daemon_static:*mut DaemonStatic = 0 as *mut DaemonStatic;

struct DaemonStatic
{
	holder: Box<DaemonFunc>,
}

trait DaemonFunc
{
	fn exec(&mut self) -> Result<(), Error>;
	fn send(&mut self, state: State) -> Result<(), Error>;
	fn take_tx(&mut self) -> Option<Sender<State>>;
}

struct DaemonFuncHolder <F: FnOnce(Receiver<State>)>
{
	tx: Option<Sender<State>>,
	func: Option<(F, Receiver<State>)>,
}

impl <F: FnOnce(Receiver<State>)> DaemonFunc for DaemonFuncHolder<F>
{
	fn exec(&mut self) -> Result<(), Error>
	{
		match self.func.take()
		{
			Some((func, rx)) => {
				func(rx);
				Ok(())
			}
			None => Err(Error::new(ErrorKind::Other, "INTERNAL ERROR: Can't unwrap daemon function"))
		}
	}

	fn send(&mut self, state: State) -> Result<(), Error>
	{
		match self.tx
		{
			Some(ref tx) => match tx.send(state)
			{
				Ok(_) => Ok(()),
				Err(e) => Err(Error::new(ErrorKind::Other, e)),
			},
			None => Err(Error::new(ErrorKind::Other, "Service is already exited")),
		}
	}

	fn take_tx(&mut self) -> Option<Sender<State>>
	{
		self.tx.take()
	}
}

impl DaemonRunner for Daemon
{
	fn run<F: 'static + FnOnce(Receiver<State>)>(&self, func: F) -> Result<(), Error> {
		let (tx, rx) = channel();
		tx.send(State::Start).unwrap();
		let mut daemon = DaemonStatic
		{
			holder: Box::new(DaemonFuncHolder
			{
				tx: Some(tx),
				func: Some((func, rx)),
			}),
		};
		try! (guard_compare_and_swap(daemon_null(), &mut daemon));
		let result = daemon_console(&mut daemon);
		try! (guard_compare_and_swap(&mut daemon, daemon_null()));
		result
	}
}

fn guard_compare_and_swap(old_value: *mut DaemonStatic, new_value: *mut DaemonStatic) -> Result<(), Error>
{
	unsafe
	{
		let guard = LOCK.lock().unwrap();
		if daemon_static != old_value
		{
			return Err(Error::new(ErrorKind::Other, "This function is not reentrant."));
		}
		daemon_static = new_value;
		let _ = guard;
	}
	Ok(())
}

fn daemon_console(daemon: &mut DaemonStatic) -> Result<(), Error>
{
	let result;
	unsafe
	{
		//if SetConsoleCtrlHandler(Some(console_handler), TRUE) == FALSE
		//{
		//	return Err(format! ("Failed SetConsoleCtrlHandler: {}", error_string(GetLastError() as i32)));
		//}
		result = daemon.holder.exec();
		//if SetConsoleCtrlHandler(Some(console_handler), FALSE) == FALSE
		//{
		//	return Err(format! ("Failed SetConsoleCtrlHandler: {}", error_string(GetLastError() as i32)));
		//}
	}
	result
}

unsafe extern "system" fn signal_handler(sig: libc::c_int)
{
	let guard = LOCK.lock().unwrap();
	if daemon_static != daemon_null()
	{
		let daemon = &mut *daemon_static;
		return match daemon.holder.take_tx()
		{
			Some(ref tx) => {
				let _ = tx.send(State::Stop);
			}
			None => ()
		}
	}
	let _ = guard;
}

fn daemon_null() -> *mut DaemonStatic {
	0 as *mut DaemonStatic
}

extern "C" {
	fn raise(sig: libc::c_int) -> libc::c_int;
	fn signal(sig: libc::c_int, handler: *const libc::c_void) -> libc::c_int;
	fn kill(pid: libc::pid_t, sig: libc::c_int) -> libc::c_int;
}
<|endoftext|>


<commit_before>//!-----------------------------------------------------------------------------------------------
//!`src/io/interrupt/mod.rs`
//!
//!Structures for manipulating the IDT.
//!-----------------------------------------------------------------------------------------------

pub mod keyboard;

use io::cpuio::Port;
use CODE_SEG;

pub struct Entry {
	offset_low: u16,
	selector: u16,
	zero1: u8,
	type_attr: u8,
	offset_mid: u16,
	offset_high: u32,
	zero2: u32,
}

impl Entry {
	pub fn new(offset_low: u16, selector: u16, type_attr: u8,
		offset_mid: u16, offset_high: u32) -> Entry{
		Entry {
			offset_low: offset_low,
			selector: selector,
			zero1: 0,
			type_attr: type_attr,
			offset_mid: offset_mid,
			offset_high: offset_high,
			zero2: 0
		}
	}
}

pub struct IDTR {
	limit: u16,
	offset: u64,
}

impl IDTR {
	pub fn new(limit: u16, offset: u64) -> IDTR {
		IDTR {limit: limit, offset: offset}
	}
}

pub fn init_idt() {
	let kb_addr: *const ();
	unsafe {
		kb_addr = asm_kb_handler as *const () as usize;
	}

	let mut idt: [Entry; 1] = [
		Entry::new(kb_addr & 0xffff as u16, 0x8, 0x8e,
			(kb_addr & 0xffff0000) >> 16 as u16,
			(kb_addr & 0xffffffff00000000) >> 32 as u32)
	];

	let init1 = Port::new(0x20);
	let init2 = Port::new(0xA0);
	let cfg1 = Port::new(0x21);
	let cfg2 = Port::new(0xA1);

	//Start config
	init1.outb(0x11);
	init2.outb(0x11);

	cfg1.outb(0x20);
	cfg2.outb(0x28);

	cfg1.outb(0x00);
	cfg2.outb(0x00);

	cfg1.outb(0x01);
	cfg2.outb(0x01);

	cfg1.outb(0xff);
	cfg2.outb(0xff);

	let idt_addr;
	unsafe {idt_addr = &idt as *const _;}
	let idtr = IDTR::new((12 * idt.len()) as u16, idt_addr as u64);

	unsafe {
		asm_lidt(&idtr as *const _ as u64);
	}

	cfg1.outb(0xfd);

}

//Assembly interrupt wrappers
extern {
	fn asm_lidt(idtr: u64);
	fn asm_kb_handler();
}
<commit_msg>Broken merge<commit_after>//!-----------------------------------------------------------------------------------------------
//!`src/io/interrupt/mod.rs`
//!
//!Structures for manipulating the IDT.
//!-----------------------------------------------------------------------------------------------

pub mod keyboard;

use io::cpuio::Port;
<<<<<<< HEAD
use CODE_SEG;
=======
>>>>>>> 20e60cf813b3e607ecbd79a6f274dd4a17023802

pub struct Entry {
	offset_low: u16,
	selector: u16,
	zero1: u8,
	type_attr: u8,
	offset_mid: u16,
	offset_high: u32,
	zero2: u32,
}

impl Entry {
	pub fn new(offset_low: u16, selector: u16, type_attr: u8,
		offset_mid: u16, offset_high: u32) -> Entry{
		Entry {
			offset_low: offset_low,
			selector: selector,
			zero1: 0,
			type_attr: type_attr,
			offset_mid: offset_mid,
			offset_high: offset_high,
			zero2: 0
		}
	}
}

pub struct IDTR {
	limit: u16,
	offset: u64,
}

impl IDTR {
	pub fn new(limit: u16, offset: u64) -> IDTR {
		IDTR {limit: limit, offset: offset}
	}
}

pub fn init_idt() {
	let kb_addr: *const ();
	unsafe {
		kb_addr = asm_kb_handler as *const () as usize;
	}

	let mut idt: [Entry; 1] = [
		Entry::new(kb_addr & 0xffff as u16, 0x8, 0x8e,
			(kb_addr & 0xffff0000) >> 16 as u16,
			(kb_addr & 0xffffffff00000000) >> 32 as u32)
	];

	let init1 = Port::new(0x20);
	let init2 = Port::new(0xA0);
	let cfg1 = Port::new(0x21);
	let cfg2 = Port::new(0xA1);

	//Start config
	init1.outb(0x11);
	init2.outb(0x11);

	cfg1.outb(0x20);
	cfg2.outb(0x28);

	cfg1.outb(0x00);
	cfg2.outb(0x00);

	cfg1.outb(0x01);
	cfg2.outb(0x01);

	cfg1.outb(0xff);
	cfg2.outb(0xff);

	let idt_addr;
	unsafe {idt_addr = &idt as *const _;}
	let idtr = IDTR::new((12 * idt.len()) as u16, idt_addr as u64);

	unsafe {
		asm_lidt(&idtr as *const _ as u64);
	}

	cfg1.outb(0xfd);
}

//Assembly interrupt wrappers
extern {
	fn asm_lidt(idtr: u64);
	fn asm_kb_handler();
}
<|endoftext|>


<commit_before>//! Handle input from glutin
//!
//! Certain key combinations should send some escape sequence back to the pty.
//! In order to figure that out, state about which modifier keys are pressed
//! needs to be tracked. Additionally, we need a bit of a state machine to
//! determine what to do when a non-modifier key is pressed.
//!
//! TODO would be nice to generalize this so it could work with other windowing
//! APIs
//!
//! TODO handling xmodmap would be good
use glutin::{ElementState, VirtualKeyCode};

use term::mode::{self, TermMode};

/// Modifier keys
///
/// Contains a bitflags for modifier keys which are now namespaced thanks to
/// this module wrapper.
mod modifier {
    use glutin::ElementState;

    bitflags! {
        /// Flags indicating active modifier keys
        pub flags Keys: u8 {
            /// Left shift
            const SHIFT_LEFT    = 0b00000001,
            /// Right shift
            const SHIFT_RIGHT   = 0b00000010,
            /// Left meta
            const META_LEFT     = 0b00000100,
            /// Right meta
            const META_RIGHT    = 0b00001000,
            /// Left control
            const CONTROL_LEFT  = 0b00010000,
            /// Right control
            const CONTROL_RIGHT = 0b00100000,
            /// Left alt
            const ALT_LEFT      = 0b01000000,
            /// Right alt
            const ALT_RIGHT     = 0b10000000,
            /// Any shift key
            const SHIFT         = SHIFT_LEFT.bits
                                | SHIFT_RIGHT.bits,
            /// Any control key
            const CONTROL       = CONTROL_LEFT.bits
                                | CONTROL_RIGHT.bits,
            /// Any alt key
            const ALT           = ALT_LEFT.bits
                                | ALT_RIGHT.bits,
            /// Any meta key
            const META          = META_LEFT.bits
                                | META_RIGHT.bits,
            /// Any mod
            const ANY           = 0b11111111,
            /// No mod
            const NONE          = 0b00000000,
        }
    }

    impl Default for Keys {
        fn default() -> Keys {
            Keys::empty()
        }
    }

    impl Keys {
        /// Take appropriate action given a modifier key and its state
        #[inline]
        pub fn update(&mut self, state: ElementState, key: Keys) {
            match state {
                ElementState::Pressed => self.insert(key),
                ElementState::Released => self.remove(key),
            }
        }
    }
}

/// Processes input from glutin.
///
/// An escape sequence may be emitted in case specific keys or key combinations
/// are activated.
///
/// TODO also need terminal state when processing input
#[derive(Default)]
pub struct Processor {
    /// Active modifier keys
    mods: modifier::Keys,
}

/// Types that are notified of escape sequences from the input::Processor.
pub trait Notify {
    /// Notify that an escape sequence should be written to the pty
    fn notify(&mut self, &str);
}

/// Describes a key combination that should emit a control sequence
///
/// The actual triggering key is omitted here since bindings are grouped by the trigger key.
#[derive(Debug)]
pub struct Binding {
    /// Modifier keys required to activate binding
    mods: modifier::Keys,
    /// String to send to pty if mods and mode match
    send: &'static str,
    /// Terminal mode required to activate binding
    mode: TermMode,
    /// excluded terminal modes where the binding won't be activated
    notmode: TermMode,
}

/// Bindings for the LEFT key.
static LEFT_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::SHIFT,   send: "\x1b[1;2D", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::CONTROL, send: "\x1b[1;5D", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ALT,     send: "\x1b[1;3D", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ANY,     send: "\x1b[D",    mode: mode::ANY,        notmode: mode::APP_CURSOR },
    Binding { mods: modifier::ANY,     send: "\x1bOD",    mode: mode::APP_CURSOR, notmode: mode::NONE },
];

/// Bindings for the RIGHT key
static RIGHT_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::SHIFT,   send: "\x1b[1;2C", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::CONTROL, send: "\x1b[1;5C", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ALT,     send: "\x1b[1;3C", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ANY,     send: "\x1b[C",    mode: mode::ANY,        notmode: mode::APP_CURSOR },
    Binding { mods: modifier::ANY,     send: "\x1bOC",    mode: mode::APP_CURSOR, notmode: mode::NONE },
];

/// Bindings for the UP key
static UP_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::SHIFT,   send: "\x1b[1;2A", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::CONTROL, send: "\x1b[1;5A", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ALT,     send: "\x1b[1;3A", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ANY,     send: "\x1b[A",    mode: mode::ANY,        notmode: mode::APP_CURSOR },
    Binding { mods: modifier::ANY,     send: "\x1bOA",    mode: mode::APP_CURSOR, notmode: mode::NONE },
];

/// Bindings for the DOWN key
static DOWN_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::SHIFT,   send: "\x1b[1;2B", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::CONTROL, send: "\x1b[1;5B", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ALT,     send: "\x1b[1;3B", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ANY,     send: "\x1b[B",    mode: mode::ANY,        notmode: mode::APP_CURSOR },
    Binding { mods: modifier::ANY,     send: "\x1bOB",    mode: mode::APP_CURSOR, notmode: mode::NONE },
];

//   key               mods            escape      appkey appcursor crlf
//
// notes: appkey = DECPAM (application keypad mode); not enabled is "normal keypad"
//     appcursor = DECCKM (application cursor mode);
//          crlf = LNM    (Linefeed/new line); wtf is this

impl Processor {
    pub fn new() -> Processor {
        Default::default()
    }

    pub fn process<N>(&mut self,
                      state: ElementState,
                      key: Option<VirtualKeyCode>,
                      notifier: &mut N,
                      mode: TermMode)
        where N: Notify
    {
        if let Some(key) = key {

            // Handle state updates
            match key {
                VirtualKeyCode::LAlt => self.mods.update(state, modifier::ALT_LEFT),
                VirtualKeyCode::RAlt => self.mods.update(state, modifier::ALT_RIGHT),
                VirtualKeyCode::LShift => self.mods.update(state, modifier::SHIFT_LEFT),
                VirtualKeyCode::RShift => self.mods.update(state, modifier::SHIFT_RIGHT),
                VirtualKeyCode::LControl => self.mods.update(state, modifier::CONTROL_LEFT),
                VirtualKeyCode::RControl => self.mods.update(state, modifier::CONTROL_RIGHT),
                VirtualKeyCode::LWin => self.mods.update(state, modifier::META_LEFT),
                VirtualKeyCode::RWin => self.mods.update(state, modifier::META_RIGHT),
                _ => ()
            }

            // Ignore release events
            if state == ElementState::Released {
                return;
            }

            let bindings = match key {
                VirtualKeyCode::Left => LEFT_BINDINGS,
                VirtualKeyCode::Up => UP_BINDINGS,
                VirtualKeyCode::Down => DOWN_BINDINGS,
                VirtualKeyCode::Right => RIGHT_BINDINGS,
                // Mode keys ignored now
                VirtualKeyCode::LAlt | VirtualKeyCode::RAlt | VirtualKeyCode::LShift |
                VirtualKeyCode::RShift | VirtualKeyCode::LControl | VirtualKeyCode::RControl |
                VirtualKeyCode::LWin | VirtualKeyCode::RWin => return,
                // All of the alphanumeric keys get passed through here as well, but there's no work
                // to be done for them.
                VirtualKeyCode::A | VirtualKeyCode::B | VirtualKeyCode::C | VirtualKeyCode::D |
                VirtualKeyCode::E | VirtualKeyCode::F | VirtualKeyCode::G | VirtualKeyCode::H |
                VirtualKeyCode::I | VirtualKeyCode::J | VirtualKeyCode::K | VirtualKeyCode::L |
                VirtualKeyCode::M | VirtualKeyCode::N | VirtualKeyCode::O | VirtualKeyCode::P |
                VirtualKeyCode::Q | VirtualKeyCode::R | VirtualKeyCode::S | VirtualKeyCode::T |
                VirtualKeyCode::U | VirtualKeyCode::V | VirtualKeyCode::W | VirtualKeyCode::X |
                VirtualKeyCode::Y | VirtualKeyCode::Z => return,
                VirtualKeyCode::Key1 | VirtualKeyCode::Key2 | VirtualKeyCode::Key3 |
                VirtualKeyCode::Key4 | VirtualKeyCode::Key5 | VirtualKeyCode::Key6 |
                VirtualKeyCode::Key7 | VirtualKeyCode::Key8 | VirtualKeyCode::Key9 |
                VirtualKeyCode::Key0 => return,
                // Log something by default
                _ => {
                    println!("Unhandled key: {:?}; state: {:?}; mods: {:?}",
                             key, state, self.mods);
                    return;
                },
            };

            self.process_bindings(bindings, mode, notifier);
        }
    }

    fn process_bindings<N>(&self, bindings: &[Binding], mode: TermMode, notifier: &mut N)
        where N: Notify
    {
        // Check each binding
        for binding in bindings {
            // TermMode positive
            if binding.mode.is_all() || mode.intersects(binding.mode) {
                // TermMode negative
                if binding.notmode.is_empty() || !mode.intersects(binding.notmode) {
                    // Modifier keys
                    if binding.mods.is_all() || self.mods.intersects(binding.mods) {
                        // everything matches
                        notifier.notify(binding.send);
                        break;
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use term::mode::{self, TermMode};

    use super::Processor;
    use super::modifier;
    use super::Binding;

    /// Receiver that keeps a copy of any strings it is notified with
    #[derive(Default)]
    struct Receiver {
        pub got: Option<String>
    }

    impl super::Notify for Receiver {
        fn notify(&mut self, s: &str) {
            self.got = Some(String::from(s));
        }
    }

    macro_rules! test_process_binding {
        {
            name: $name:ident,
            binding: $binding:expr,
            expect: $expect:expr,
            mode: $mode:expr,
            mods: $mods:expr
        } => {
            #[test]
            fn $name() {
                let bindings = &[$binding];

                let mut processor = Processor::new();
                processor.mods.insert($mods);
                let mut receiver = Receiver::default();

                processor.process_bindings(bindings, $mode, &mut receiver);
                assert_eq!(receiver.got, $expect);
            }
        }
    }

    test_process_binding! {
        name: process_binding_nomode_shiftmod_require_shift,
        binding: Binding { mods: modifier::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE },
        expect: Some(String::from("\x1b[1;2D")),
        mode: mode::NONE,
        mods: modifier::SHIFT
    }

    test_process_binding! {
        name: process_binding_nomode_nomod_require_shift,
        binding: Binding { mods: modifier::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE },
        expect: None,
        mode: mode::NONE,
        mods: modifier::NONE
    }

    test_process_binding! {
        name: process_binding_nomode_controlmod,
        binding: Binding { mods: modifier::CONTROL, send: "\x1b[1;5D", mode: mode::ANY, notmode: mode::NONE },
        expect: Some(String::from("\x1b[1;5D")),
        mode: mode::NONE,
        mods: modifier::CONTROL
    }

    test_process_binding! {
        name: process_binding_nomode_nomod_require_not_appcursor,
        binding: Binding { mods: modifier::ANY, send: "\x1b[D", mode: mode::ANY, notmode: mode::APP_CURSOR },
        expect: Some(String::from("\x1b[D")),
        mode: mode::NONE,
        mods: modifier::NONE
    }

    test_process_binding! {
        name: process_binding_appcursormode_nomod_require_appcursor,
        binding: Binding { mods: modifier::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE },
        expect: Some(String::from("\x1bOD")),
        mode: mode::APP_CURSOR,
        mods: modifier::NONE
    }

    test_process_binding! {
        name: process_binding_nomode_nomod_require_appcursor,
        binding: Binding { mods: modifier::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE },
        expect: None,
        mode: mode::NONE,
        mods: modifier::NONE
    }
}
<commit_msg>Function keys send escape sequences<commit_after>//! Handle input from glutin
//!
//! Certain key combinations should send some escape sequence back to the pty.
//! In order to figure that out, state about which modifier keys are pressed
//! needs to be tracked. Additionally, we need a bit of a state machine to
//! determine what to do when a non-modifier key is pressed.
//!
//! TODO would be nice to generalize this so it could work with other windowing
//! APIs
//!
//! TODO handling xmodmap would be good
use glutin::{ElementState, VirtualKeyCode};

use term::mode::{self, TermMode};

/// Modifier keys
///
/// Contains a bitflags for modifier keys which are now namespaced thanks to
/// this module wrapper.
mod modifier {
    use glutin::ElementState;

    bitflags! {
        /// Flags indicating active modifier keys
        pub flags Keys: u8 {
            /// Left shift
            const SHIFT_LEFT    = 0b00000001,
            /// Right shift
            const SHIFT_RIGHT   = 0b00000010,
            /// Left meta
            const META_LEFT     = 0b00000100,
            /// Right meta
            const META_RIGHT    = 0b00001000,
            /// Left control
            const CONTROL_LEFT  = 0b00010000,
            /// Right control
            const CONTROL_RIGHT = 0b00100000,
            /// Left alt
            const ALT_LEFT      = 0b01000000,
            /// Right alt
            const ALT_RIGHT     = 0b10000000,
            /// Any shift key
            const SHIFT         = SHIFT_LEFT.bits
                                | SHIFT_RIGHT.bits,
            /// Any control key
            const CONTROL       = CONTROL_LEFT.bits
                                | CONTROL_RIGHT.bits,
            /// Any alt key
            const ALT           = ALT_LEFT.bits
                                | ALT_RIGHT.bits,
            /// Any meta key
            const META          = META_LEFT.bits
                                | META_RIGHT.bits,
            /// Any mod
            const ANY           = 0b11111111,
            /// No mod
            const NONE          = 0b00000000,
        }
    }

    impl Default for Keys {
        fn default() -> Keys {
            Keys::empty()
        }
    }

    impl Keys {
        /// Take appropriate action given a modifier key and its state
        #[inline]
        pub fn update(&mut self, state: ElementState, key: Keys) {
            match state {
                ElementState::Pressed => self.insert(key),
                ElementState::Released => self.remove(key),
            }
        }
    }
}

/// Processes input from glutin.
///
/// An escape sequence may be emitted in case specific keys or key combinations
/// are activated.
///
/// TODO also need terminal state when processing input
#[derive(Default)]
pub struct Processor {
    /// Active modifier keys
    mods: modifier::Keys,
}

/// Types that are notified of escape sequences from the input::Processor.
pub trait Notify {
    /// Notify that an escape sequence should be written to the pty
    fn notify(&mut self, &str);
}

/// Describes a key combination that should emit a control sequence
///
/// The actual triggering key is omitted here since bindings are grouped by the trigger key.
#[derive(Debug)]
pub struct Binding {
    /// Modifier keys required to activate binding
    mods: modifier::Keys,
    /// String to send to pty if mods and mode match
    send: &'static str,
    /// Terminal mode required to activate binding
    mode: TermMode,
    /// excluded terminal modes where the binding won't be activated
    notmode: TermMode,
}

/// Bindings for the LEFT key.
static LEFT_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::SHIFT,   send: "\x1b[1;2D", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::CONTROL, send: "\x1b[1;5D", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ALT,     send: "\x1b[1;3D", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ANY,     send: "\x1b[D",    mode: mode::ANY,        notmode: mode::APP_CURSOR },
    Binding { mods: modifier::ANY,     send: "\x1bOD",    mode: mode::APP_CURSOR, notmode: mode::NONE },
];

/// Bindings for the RIGHT key
static RIGHT_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::SHIFT,   send: "\x1b[1;2C", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::CONTROL, send: "\x1b[1;5C", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ALT,     send: "\x1b[1;3C", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ANY,     send: "\x1b[C",    mode: mode::ANY,        notmode: mode::APP_CURSOR },
    Binding { mods: modifier::ANY,     send: "\x1bOC",    mode: mode::APP_CURSOR, notmode: mode::NONE },
];

/// Bindings for the UP key
static UP_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::SHIFT,   send: "\x1b[1;2A", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::CONTROL, send: "\x1b[1;5A", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ALT,     send: "\x1b[1;3A", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ANY,     send: "\x1b[A",    mode: mode::ANY,        notmode: mode::APP_CURSOR },
    Binding { mods: modifier::ANY,     send: "\x1bOA",    mode: mode::APP_CURSOR, notmode: mode::NONE },
];

/// Bindings for the DOWN key
static DOWN_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::SHIFT,   send: "\x1b[1;2B", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::CONTROL, send: "\x1b[1;5B", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ALT,     send: "\x1b[1;3B", mode: mode::ANY,        notmode: mode::NONE },
    Binding { mods: modifier::ANY,     send: "\x1b[B",    mode: mode::ANY,        notmode: mode::APP_CURSOR },
    Binding { mods: modifier::ANY,     send: "\x1bOB",    mode: mode::APP_CURSOR, notmode: mode::NONE },
];

/// Bindings for the F1 key
static F1_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1bOP", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F2 key
static F2_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1bOQ", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F3 key
static F3_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1bOR", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F4 key
static F4_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1bOS", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F5 key
static F5_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1b[15~", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F6 key
static F6_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1b[17~", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F7 key
static F7_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1b[18~", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F8 key
static F8_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1b[19~", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F9 key
static F9_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1b[20~", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F10 key
static F10_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1b[21~", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F11 key
static F11_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1b[23~", mode: mode::ANY, notmode: mode::NONE },
];

/// Bindings for the F11 key
static F12_BINDINGS: &'static [Binding] = &[
    Binding { mods: modifier::ANY, send: "\x1b[24~", mode: mode::ANY, notmode: mode::NONE },
];

//   key               mods            escape      appkey appcursor crlf
//
// notes: appkey = DECPAM (application keypad mode); not enabled is "normal keypad"
//     appcursor = DECCKM (application cursor mode);
//          crlf = LNM    (Linefeed/new line); wtf is this

impl Processor {
    pub fn new() -> Processor {
        Default::default()
    }

    pub fn process<N>(&mut self,
                      state: ElementState,
                      key: Option<VirtualKeyCode>,
                      notifier: &mut N,
                      mode: TermMode)
        where N: Notify
    {
        if let Some(key) = key {

            // Handle state updates
            match key {
                VirtualKeyCode::LAlt => self.mods.update(state, modifier::ALT_LEFT),
                VirtualKeyCode::RAlt => self.mods.update(state, modifier::ALT_RIGHT),
                VirtualKeyCode::LShift => self.mods.update(state, modifier::SHIFT_LEFT),
                VirtualKeyCode::RShift => self.mods.update(state, modifier::SHIFT_RIGHT),
                VirtualKeyCode::LControl => self.mods.update(state, modifier::CONTROL_LEFT),
                VirtualKeyCode::RControl => self.mods.update(state, modifier::CONTROL_RIGHT),
                VirtualKeyCode::LWin => self.mods.update(state, modifier::META_LEFT),
                VirtualKeyCode::RWin => self.mods.update(state, modifier::META_RIGHT),
                _ => ()
            }

            // Ignore release events
            if state == ElementState::Released {
                return;
            }

            let bindings = match key {
                // Arrows
                VirtualKeyCode::Left => LEFT_BINDINGS,
                VirtualKeyCode::Up => UP_BINDINGS,
                VirtualKeyCode::Down => DOWN_BINDINGS,
                VirtualKeyCode::Right => RIGHT_BINDINGS,
                // Function keys
                VirtualKeyCode::F1 => F1_BINDINGS,
                VirtualKeyCode::F2 => F2_BINDINGS,
                VirtualKeyCode::F3 => F3_BINDINGS,
                VirtualKeyCode::F4 => F4_BINDINGS,
                VirtualKeyCode::F5 => F5_BINDINGS,
                VirtualKeyCode::F6 => F6_BINDINGS,
                VirtualKeyCode::F7 => F7_BINDINGS,
                VirtualKeyCode::F8 => F8_BINDINGS,
                VirtualKeyCode::F9 => F9_BINDINGS,
                VirtualKeyCode::F10 => F10_BINDINGS,
                VirtualKeyCode::F11 => F11_BINDINGS,
                VirtualKeyCode::F12 => F12_BINDINGS,
                // Mode keys ignored now
                VirtualKeyCode::LAlt | VirtualKeyCode::RAlt | VirtualKeyCode::LShift |
                VirtualKeyCode::RShift | VirtualKeyCode::LControl | VirtualKeyCode::RControl |
                VirtualKeyCode::LWin | VirtualKeyCode::RWin => return,
                // All of the alphanumeric keys get passed through here as well, but there's no work
                // to be done for them.
                VirtualKeyCode::A | VirtualKeyCode::B | VirtualKeyCode::C | VirtualKeyCode::D |
                VirtualKeyCode::E | VirtualKeyCode::F | VirtualKeyCode::G | VirtualKeyCode::H |
                VirtualKeyCode::I | VirtualKeyCode::J | VirtualKeyCode::K | VirtualKeyCode::L |
                VirtualKeyCode::M | VirtualKeyCode::N | VirtualKeyCode::O | VirtualKeyCode::P |
                VirtualKeyCode::Q | VirtualKeyCode::R | VirtualKeyCode::S | VirtualKeyCode::T |
                VirtualKeyCode::U | VirtualKeyCode::V | VirtualKeyCode::W | VirtualKeyCode::X |
                VirtualKeyCode::Y | VirtualKeyCode::Z => return,
                VirtualKeyCode::Key1 | VirtualKeyCode::Key2 | VirtualKeyCode::Key3 |
                VirtualKeyCode::Key4 | VirtualKeyCode::Key5 | VirtualKeyCode::Key6 |
                VirtualKeyCode::Key7 | VirtualKeyCode::Key8 | VirtualKeyCode::Key9 |
                VirtualKeyCode::Key0 => return,
                // Log something by default
                _ => {
                    println!("Unhandled key: {:?}; state: {:?}; mods: {:?}",
                             key, state, self.mods);
                    return;
                },
            };

            self.process_bindings(bindings, mode, notifier);
        }
    }

    fn process_bindings<N>(&self, bindings: &[Binding], mode: TermMode, notifier: &mut N)
        where N: Notify
    {
        // Check each binding
        for binding in bindings {
            // TermMode positive
            if binding.mode.is_all() || mode.intersects(binding.mode) {
                // TermMode negative
                if binding.notmode.is_empty() || !mode.intersects(binding.notmode) {
                    // Modifier keys
                    if binding.mods.is_all() || self.mods.intersects(binding.mods) {
                        // everything matches
                        notifier.notify(binding.send);
                        break;
                    }
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use term::mode::{self, TermMode};

    use super::Processor;
    use super::modifier;
    use super::Binding;

    /// Receiver that keeps a copy of any strings it is notified with
    #[derive(Default)]
    struct Receiver {
        pub got: Option<String>
    }

    impl super::Notify for Receiver {
        fn notify(&mut self, s: &str) {
            self.got = Some(String::from(s));
        }
    }

    macro_rules! test_process_binding {
        {
            name: $name:ident,
            binding: $binding:expr,
            expect: $expect:expr,
            mode: $mode:expr,
            mods: $mods:expr
        } => {
            #[test]
            fn $name() {
                let bindings = &[$binding];

                let mut processor = Processor::new();
                processor.mods.insert($mods);
                let mut receiver = Receiver::default();

                processor.process_bindings(bindings, $mode, &mut receiver);
                assert_eq!(receiver.got, $expect);
            }
        }
    }

    test_process_binding! {
        name: process_binding_nomode_shiftmod_require_shift,
        binding: Binding { mods: modifier::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE },
        expect: Some(String::from("\x1b[1;2D")),
        mode: mode::NONE,
        mods: modifier::SHIFT
    }

    test_process_binding! {
        name: process_binding_nomode_nomod_require_shift,
        binding: Binding { mods: modifier::SHIFT, send: "\x1b[1;2D", mode: mode::ANY, notmode: mode::NONE },
        expect: None,
        mode: mode::NONE,
        mods: modifier::NONE
    }

    test_process_binding! {
        name: process_binding_nomode_controlmod,
        binding: Binding { mods: modifier::CONTROL, send: "\x1b[1;5D", mode: mode::ANY, notmode: mode::NONE },
        expect: Some(String::from("\x1b[1;5D")),
        mode: mode::NONE,
        mods: modifier::CONTROL
    }

    test_process_binding! {
        name: process_binding_nomode_nomod_require_not_appcursor,
        binding: Binding { mods: modifier::ANY, send: "\x1b[D", mode: mode::ANY, notmode: mode::APP_CURSOR },
        expect: Some(String::from("\x1b[D")),
        mode: mode::NONE,
        mods: modifier::NONE
    }

    test_process_binding! {
        name: process_binding_appcursormode_nomod_require_appcursor,
        binding: Binding { mods: modifier::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE },
        expect: Some(String::from("\x1bOD")),
        mode: mode::APP_CURSOR,
        mods: modifier::NONE
    }

    test_process_binding! {
        name: process_binding_nomode_nomod_require_appcursor,
        binding: Binding { mods: modifier::ANY, send: "\x1bOD", mode: mode::APP_CURSOR, notmode: mode::NONE },
        expect: None,
        mode: mode::NONE,
        mods: modifier::NONE
    }
}
<|endoftext|>


<commit_before>use ::kdtree::*;

enum PointsWereOnSide {
    Left,
    Right,
    Both,
}

struct PartitionPointHelper {
    points_were_on_side: PointsWereOnSide,
    midpoint_split_value: f64,
    index_of_splitter: usize,
}

fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> PartitionPointHelper {
    let mut closest_index = 0;
    let mut closest_distance = (vec[0].dims()[partition_on_dimension] - midpoint_value).abs();

    const HAS_POINTS_ON_LEFT_SIDE: i32 = 0b01;
    const HAS_POINTS_ON_RIGHT_SIDE: i32 = 0b10;
    const HAS_POINTS_ON_BOTH_SIDES: i32 = HAS_POINTS_ON_RIGHT_SIDE | HAS_POINTS_ON_LEFT_SIDE;
    let mut has_points_on_sides = 0;

    for i in 0..vec.len() {
        let p = vec.get(i).unwrap();
        if p.dims()[partition_on_dimension] <= midpoint_value {
            has_points_on_sides |= HAS_POINTS_ON_LEFT_SIDE;
        } else {
            has_points_on_sides |= HAS_POINTS_ON_RIGHT_SIDE;
        }

        let dist = (p.dims()[partition_on_dimension] - midpoint_value).abs();

        if dist < closest_distance {
            closest_distance = dist;
            closest_index = i;
        }
    }

    if has_points_on_sides != HAS_POINTS_ON_BOTH_SIDES {
        return PartitionPointHelper {
            index_of_splitter: closest_index,
            midpoint_split_value: vec.get(closest_index).unwrap().dims()[partition_on_dimension],
            points_were_on_side: if has_points_on_sides == HAS_POINTS_ON_LEFT_SIDE { PointsWereOnSide::Left } else { PointsWereOnSide::Right }
        }
    }
    return PartitionPointHelper {
        index_of_splitter: closest_index,
        midpoint_split_value: midpoint_value,
        points_were_on_side: PointsWereOnSide::Both
    }
}

pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> (usize, f64) {
    let vec_len = vec.len();
    debug_assert!(vec[0].dims().len() > partition_on_dimension);
    debug_assert!(vec.len() > 1);

    let partition_point_data = partition_sliding_midpoint_helper(vec, midpoint_value, partition_on_dimension);

    match partition_point_data.points_were_on_side {
        PointsWereOnSide::Left => {
            vec.swap(partition_point_data.index_of_splitter, vec_len - 1);
            (vec_len - 1, partition_point_data.midpoint_split_value)
        },
        PointsWereOnSide::Right => {
            vec.swap(partition_point_data.index_of_splitter, 0);
            (0, partition_point_data.midpoint_split_value)
        }
        PointsWereOnSide::Both => {
            let index_of_splitting_point = partition_kdtree(vec, partition_point_data.index_of_splitter, partition_on_dimension);
            (index_of_splitting_point, partition_point_data.midpoint_split_value)
        }
    }
}

fn partition_kdtree<T: KdtreePointTrait>(vec: &mut Vec<T>, index_of_splitting_point: usize, partition_on_dimension: usize) -> usize {
    if vec.len() == 1 {
        return 0;
    }

    let pivot = vec[index_of_splitting_point].dims()[partition_on_dimension];
    let vec_len = vec.len();

    vec.swap(index_of_splitting_point, vec_len - 1);

    let mut left = 0usize;
    let mut right = vec.len() - 2;
    let mut last_succesful_swap = vec.len() -1;

    //variant of Lomuto algo.
    loop {
        while left <= right && vec[left].dims()[partition_on_dimension] <= pivot {
            left += 1;
        }

        while right > left && vec[right].dims()[partition_on_dimension] > pivot {
            right -= 1;
        }

        if right > left {
            vec.swap(left, right);
            last_succesful_swap = right;

            left += 1;
            right -= 1;

        } else {
            break;
        }
    }

    if last_succesful_swap == vec_len -1 && vec[right].dims()[partition_on_dimension] > pivot {
        vec.swap(right, last_succesful_swap);
        last_succesful_swap = right;
    } else if vec[left].dims()[partition_on_dimension] > pivot {
        vec.swap(left, vec_len -1);
        last_succesful_swap = left;
    } else {
        vec.swap(last_succesful_swap, vec_len - 1);
    }

    last_succesful_swap
}

#[cfg(test)]
mod tests {
    use ::kdtree::*;
    use ::kdtree::test_common::tests_utils::*;

    use ::rand::distributions::{IndependentSample, Range};
    use ::rand::*;

    use super::*;
    use super::partition_kdtree;

    #[test]
    fn parition_kdtree_works() {
        let p1 = Point2WithId::new(0, 1., 4.);
        let p2 = Point2WithId::new(1, 2., 6.);
        let p3 = Point2WithId::new(2, 3., 8.);
        let p4 = Point2WithId::new(3, 0., 8.);
        let p5 = Point2WithId::new(4, -1., 8.);
        let p6 = Point2WithId::new(5, 3., 8.);
        let p7 = Point2WithId::new(6, 4., 8.);

        let mut vec = vec![p1, p2, p3, p4, p5, p6, p7];
        assert_eq! (1, partition_kdtree(&mut vec.clone(), 3, 0));

        assert_eq! (6, partition_kdtree(&mut vec.clone(), 6, 0));

        assert_eq! (0, partition_kdtree(&mut vec.clone(), 4, 0));

        assert_eq! (5, partition_kdtree(&mut vec.clone(), 2, 0));
    }

    quickcheck! {
        fn partition_kdtree_qc(xs: Vec<f64>) -> bool {
            let mut vec : Vec<Point1WithId> = vec![];

            for i in 0 .. xs.len() {
                let p = Point1WithId::new(i as i32, xs[i]);
                vec.push(p);
            }

            if(xs.len() == 0 ) {
                return true;
            }
            let between = Range::new(0, xs.len());
            let mut rng = thread_rng();

            for i in 0 .. 5 {
                let random_splitting_index = between.ind_sample(&mut rng);

                let mut vec = vec.clone();

                let index_of_splitting_point = partition_kdtree(&mut vec, random_splitting_index, 0);
                return assert_partition(&vec, index_of_splitting_point);
            }

            true
        }
    }

    #[test]
    #[ignore]
    fn partition_given_midpoint_exactly_in_between_points_returns_smaller_index() {
        let p1 = Point2WithId::new(1, 2., 4.);
        let p2 = Point2WithId::new(1, 4., 6.);
        let mut vec = vec![p1, p2];

        assert_eq! ((0, 3.), partition_sliding_midpoint(&mut vec, 3., 0));
        assert_eq! ((0, 5.), partition_sliding_midpoint(&mut vec, 5., 1));
    }

    #[test]
    #[ignore]
    fn partition_given_midpoint_which_has_all_points_on_one_side_slides_split_plane_and_returns_index_to_closest_element() {
        let p1 = Point2WithId::new(1, 2., 4.);
        let p2 = Point2WithId::new(2, 4., 6.);
        let p3 = Point2WithId::new(3, 3., 7.);
        let p4 = Point2WithId::new(4, 0., 8.);
        let mut vec = vec![p1, p2, p3];

        assert_eq! ((0, 2.), partition_sliding_midpoint(&mut vec, 1.9, 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((0, 2.), partition_sliding_midpoint(&mut vec, -5000., 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((2, 4.), partition_sliding_midpoint(&mut vec, 10., 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (3, vec[1].id);
        assert_eq! (2, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((2, 7.), partition_sliding_midpoint(&mut vec, 10., 1));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3, p4];
        assert_eq! ((0, 0.), partition_sliding_midpoint(&mut vec, -5000., 0));
        assert_eq! (4, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);
        assert_eq! (1, vec[3].id);
    }

    fn assert_partition(v: &Vec<Point1WithId>, index_of_splitting_point: usize) -> bool {
        let pivot = v[index_of_splitting_point].dims()[0];

        for i in 0..index_of_splitting_point {
            if v[i].dims()[0] > pivot {
                return false;
            }
        }

        for i in index_of_splitting_point + 1..v.len() {
            if v[i].dims()[0] < pivot {
                return false;
            }
        }

        true
    }
}<commit_msg>Formatted code slightly<commit_after>use ::kdtree::*;

enum PointsWereOnSide {
    Left,
    Right,
    Both,
}

struct PartitionPointHelper {
    points_were_on_side: PointsWereOnSide,
    midpoint_split_value: f64,
    index_of_splitter: usize,
}

fn partition_sliding_midpoint_helper<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> PartitionPointHelper {
    let mut closest_index = 0;
    let mut closest_distance = (vec[0].dims()[partition_on_dimension] - midpoint_value).abs();

    const HAS_POINTS_ON_LEFT_SIDE: i32 = 0b01;
    const HAS_POINTS_ON_RIGHT_SIDE: i32 = 0b10;
    const HAS_POINTS_ON_BOTH_SIDES: i32 = HAS_POINTS_ON_RIGHT_SIDE | HAS_POINTS_ON_LEFT_SIDE;
    let mut has_points_on_sides = 0;

    for i in 0..vec.len() {
        let p = vec.get(i).unwrap();
        if p.dims()[partition_on_dimension] <= midpoint_value {
            has_points_on_sides |= HAS_POINTS_ON_LEFT_SIDE;
        } else {
            has_points_on_sides |= HAS_POINTS_ON_RIGHT_SIDE;
        }

        let dist = (p.dims()[partition_on_dimension] - midpoint_value).abs();

        if dist < closest_distance {
            closest_distance = dist;
            closest_index = i;
        }
    }

    if has_points_on_sides != HAS_POINTS_ON_BOTH_SIDES {
        return PartitionPointHelper {
            index_of_splitter: closest_index,
            midpoint_split_value: vec.get(closest_index).unwrap().dims()[partition_on_dimension],
            points_were_on_side: if has_points_on_sides == HAS_POINTS_ON_LEFT_SIDE { PointsWereOnSide::Left } else { PointsWereOnSide::Right }
        }
    }
    return PartitionPointHelper {
        index_of_splitter: closest_index,
        midpoint_split_value: midpoint_value,
        points_were_on_side: PointsWereOnSide::Both
    }
}

pub fn partition_sliding_midpoint<T: KdtreePointTrait>(vec: &mut Vec<T>, midpoint_value: f64, partition_on_dimension: usize) -> (usize, f64) {
    let vec_len = vec.len();
    debug_assert!(vec[0].dims().len() > partition_on_dimension);
    debug_assert!(vec.len() > 1);

    let partition_point_data = partition_sliding_midpoint_helper(vec, midpoint_value, partition_on_dimension);

    match partition_point_data.points_were_on_side {
        PointsWereOnSide::Left => {
            vec.swap(partition_point_data.index_of_splitter, vec_len - 1);
            (vec_len - 1, partition_point_data.midpoint_split_value)
        },
        PointsWereOnSide::Right => {
            vec.swap(partition_point_data.index_of_splitter, 0);
            (0, partition_point_data.midpoint_split_value)
        }
        PointsWereOnSide::Both => {
            let index_of_splitting_point = partition_kdtree(vec, partition_point_data.index_of_splitter, partition_on_dimension);
            (index_of_splitting_point, partition_point_data.midpoint_split_value)
        }
    }
}

fn partition_kdtree<T: KdtreePointTrait>(vec: &mut Vec<T>, index_of_splitting_point: usize, partition_on_dimension: usize) -> usize {
    if vec.len() == 1 {
        return 0;
    }

    let pivot = vec[index_of_splitting_point].dims()[partition_on_dimension];
    let vec_len = vec.len();

    vec.swap(index_of_splitting_point, vec_len - 1);

    let mut left = 0usize;
    let mut right = vec.len() - 2;
    let mut last_succesful_swap = vec.len() - 1;

    //variant of Lomuto algo.
    loop {
        while left <= right && vec[left].dims()[partition_on_dimension] <= pivot {
            left += 1;
        }

        while right > left && vec[right].dims()[partition_on_dimension] > pivot {
            right -= 1;
        }

        if right > left {
            vec.swap(left, right);
            last_succesful_swap = right;

            left += 1;
            right -= 1;
        } else {
            break;
        }
    }

    if last_succesful_swap == vec_len - 1 && vec[right].dims()[partition_on_dimension] > pivot {
        vec.swap(right, last_succesful_swap);
        last_succesful_swap = right;
    } else if vec[left].dims()[partition_on_dimension] > pivot {
        vec.swap(left, vec_len - 1);
        last_succesful_swap = left;
    } else {
        vec.swap(last_succesful_swap, vec_len - 1);
    }

    last_succesful_swap
}

#[cfg(test)]
mod tests {
    use ::kdtree::*;
    use ::kdtree::test_common::tests_utils::*;

    use ::rand::distributions::{IndependentSample, Range};
    use ::rand::*;

    use super::*;
    use super::partition_kdtree;

    #[test]
    fn parition_kdtree_works() {
        let p1 = Point2WithId::new(0, 1., 4.);
        let p2 = Point2WithId::new(1, 2., 6.);
        let p3 = Point2WithId::new(2, 3., 8.);
        let p4 = Point2WithId::new(3, 0., 8.);
        let p5 = Point2WithId::new(4, -1., 8.);
        let p6 = Point2WithId::new(5, 3., 8.);
        let p7 = Point2WithId::new(6, 4., 8.);

        let mut vec = vec![p1, p2, p3, p4, p5, p6, p7];
        assert_eq! (1, partition_kdtree(&mut vec.clone(), 3, 0));

        assert_eq! (6, partition_kdtree(&mut vec.clone(), 6, 0));

        assert_eq! (0, partition_kdtree(&mut vec.clone(), 4, 0));

        assert_eq! (5, partition_kdtree(&mut vec.clone(), 2, 0));
    }

    quickcheck! {
        fn partition_kdtree_qc(xs: Vec<f64>) -> bool {
            let mut vec : Vec<Point1WithId> = vec![];

            for i in 0 .. xs.len() {
                let p = Point1WithId::new(i as i32, xs[i]);
                vec.push(p);
            }

            if(xs.len() == 0 ) {
                return true;
            }
            let between = Range::new(0, xs.len());
            let mut rng = thread_rng();

            for i in 0 .. 5 {
                let random_splitting_index = between.ind_sample(&mut rng);

                let mut vec = vec.clone();

                let index_of_splitting_point = partition_kdtree(&mut vec, random_splitting_index, 0);
                return assert_partition(&vec, index_of_splitting_point);
            }

            true
        }
    }

    #[test]
    #[ignore]
    fn partition_given_midpoint_exactly_in_between_points_returns_smaller_index() {
        let p1 = Point2WithId::new(1, 2., 4.);
        let p2 = Point2WithId::new(1, 4., 6.);
        let mut vec = vec![p1, p2];

        assert_eq! ((0, 3.), partition_sliding_midpoint(&mut vec, 3., 0));
        assert_eq! ((0, 5.), partition_sliding_midpoint(&mut vec, 5., 1));
    }

    #[test]
    #[ignore]
    fn partition_given_midpoint_which_has_all_points_on_one_side_slides_split_plane_and_returns_index_to_closest_element() {
        let p1 = Point2WithId::new(1, 2., 4.);
        let p2 = Point2WithId::new(2, 4., 6.);
        let p3 = Point2WithId::new(3, 3., 7.);
        let p4 = Point2WithId::new(4, 0., 8.);
        let mut vec = vec![p1, p2, p3];

        assert_eq! ((0, 2.), partition_sliding_midpoint(&mut vec, 1.9, 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((0, 2.), partition_sliding_midpoint(&mut vec, -5000., 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((2, 4.), partition_sliding_midpoint(&mut vec, 10., 0));
        assert_eq! (1, vec[0].id);
        assert_eq! (3, vec[1].id);
        assert_eq! (2, vec[2].id);

        let mut vec = vec![p1, p2, p3];
        assert_eq! ((2, 7.), partition_sliding_midpoint(&mut vec, 10., 1));
        assert_eq! (1, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);

        let mut vec = vec![p1, p2, p3, p4];
        assert_eq! ((0, 0.), partition_sliding_midpoint(&mut vec, -5000., 0));
        assert_eq! (4, vec[0].id);
        assert_eq! (2, vec[1].id);
        assert_eq! (3, vec[2].id);
        assert_eq! (1, vec[3].id);
    }

    fn assert_partition(v: &Vec<Point1WithId>, index_of_splitting_point: usize) -> bool {
        let pivot = v[index_of_splitting_point].dims()[0];

        for i in 0..index_of_splitting_point {
            if v[i].dims()[0] > pivot {
                return false;
            }
        }

        for i in index_of_splitting_point + 1..v.len() {
            if v[i].dims()[0] < pivot {
                return false;
            }
        }

        true
    }
}<|endoftext|>