<commit_before>
extern crate libc;
extern crate termios;
use std::str;
use std::env::home_dir;
use std::fs::File;
use std::io::Read;
use std::io;
use std::io::Write;
use std::os::unix::io::RawFd;
use self::termios::{
    Termios, tcsetattr, TCSANOW, ICANON, ECHO
};
const STDIN_FILENO: i32 = 0;
const NEWLINE: i32 = 10;
const ESC: i32 = 27;
const ARROW: i32 = 91;
const UP: i32 = 65;
const DOWN: i32 = 66;
const LEFT: i32 = 68;
const RIGHT: i32 = 67;
const BACKSPACE: i32 = 127;

fn get_win_size() -> (usize, usize) {
    use std::mem::zeroed;
    unsafe {
        let mut size: libc::winsize = zeroed();
        match libc::ioctl(libc::STDOUT_FILENO, libc::TIOCGWINSZ, &mut size) {
            0 => (size.ws_col as usize, size.ws_row as usize),
            _ => (80, 24),
        }
    }
}

fn get_cols() -> usize {
    let (cols,_) = get_win_size();
    return cols;
}

struct HistoryNode{
    s: String,
    next: Option<Box<HistoryNode>>
}
pub struct History{
    first: Option<Box<HistoryNode>>
}

impl History{
    pub fn get(&self, index: usize) -> Option<String> {
        if index==0 {return None;}
        if let Some(ref first) = self.first {
            let mut p = first;
            for _ in 0..index-1 {
                if let Some(ref next) = p.next {
                    p = next;
                }else{
                    return None;
                }
            }
            return Some(p.s.clone());
        }
        return None;
    }
    pub fn new() -> History{
        return History{first: None};
    }
    pub fn append(&mut self, s: &str){
        if let Some(ref first) = self.first {
            if &first.s==s {return;}
        }
        self.first = Some(Box::new(HistoryNode{
            s: String::from(s), next: self.first.take()
        }));
    }
}

fn getchar() -> i32 {
    unsafe{libc::getchar()}
}

fn number_of_bytes(c: u8) -> usize {
    let x=c;
    let mut i: i32 =7;
    while i>=0 && x>>i&1 == 1 {
        i-=1;
    }
    return 7-i as usize;
}

fn number_of_lines(cols: usize, prompt: &str, a: &Vec<char>) -> usize{
    let n = prompt.len()+a.len();
    return if n==0 {1} else {(n-1)/cols+1};
}

fn clear_input(lines: usize){
    print!("\x1b[2K\r");
    for _ in 1..lines {
        print!("\x1b[1A");
        print!("\x1b[2K\r");
    }
}

pub fn getline_history(prompt: &str, history: &History)
-> io::Result<String>
{
    let fd: RawFd = STDIN_FILENO;
    let tio_backup = try!(Termios::from_fd(fd));
    let mut tio = tio_backup.clone();

    tio.c_lflag &= !(ICANON|ECHO);
    try!(tcsetattr(fd, TCSANOW, &tio));
    let mut a: Vec<char> = Vec::new();
    let mut history_index=0;
    print!("{}",prompt);
    io::stdout().flush().ok();
    let mut i=0;
    let mut n=0;
    loop{
        let c = getchar();
        if c==NEWLINE {
            println!();
            break;
        }else if c<32 {
            if c==ESC {
                let c2 = getchar();
                if c2==ARROW {
                    let c3 = getchar();
                    if c3==LEFT {
                        if i>0 {i-=1;}
                    }else if c3==RIGHT {
                        if i<n {i+=1;}
                    }else if c3==UP {
                        if let Some(x) = history.get(history_index+1) {
                            a = x.chars().collect();
                            n = a.len(); i=n;
                            history_index+=1;
                        }
                    }else if c3==DOWN {
                        if history_index>0 {
                            if history_index==1 {
                                history_index=0;
                                a = vec![];
                                i=0; n=0;
                            }else if let Some(x) = history.get(history_index-1) {
                                history_index-=1;
                                a = x.chars().collect();
                                n = a.len(); i=n;
                            }else{
                                panic!();
                            }
                        }
                    }
                }
            }else{
                continue;
            }
        }else if c==BACKSPACE {
            if i>0 {
                for j in i..n {
                    a[j-1]=a[j];
                }
                a.pop();
                n-=1; i-=1;
            }
        }else{
            let cu32 = if c>127 {
                let mut buffer: [u8;8] = [0,0,0,0,0,0,0,0];
                let bytes = number_of_bytes(c as u8);
                match bytes {
                    2 => {
                        buffer[0]=c as u8;
                        buffer[1]=getchar() as u8;
                    },
                    3 => {
                        buffer[0]=c as u8;
                        buffer[1]=getchar() as u8;
                        buffer[2]=getchar() as u8;
                    },
                    4 => {
                        buffer[0]=c as u8;
                        buffer[1]=getchar() as u8;
                        buffer[2]=getchar() as u8;
                        buffer[3]=getchar() as u8;
                    },
                    _ => panic!()
                };
                let s = match str::from_utf8(&buffer[0..bytes]) {
                    Ok(s) => s, Err(_) => "?"
                };
                match s.chars().next() {
                    Some(x) => x, None => '?'
                }
            }else{
                c as u8 as char
            };
            a.push('0');
            for j in (i..n).rev() {
                a[j+1]=a[j];
            }
            a[i] = cu32;
            n+=1; i+=1;
        }
        let cols = get_cols();
        let lines = number_of_lines(cols,prompt,&a);
        clear_input(lines);
        print!("{}",prompt);
        for x in &a {print!("{}",x);}

        // Bug: a hanzi, say 0x4567, hampers the cursor
        // to move backward by one character.
        // (GNOME Terminal 3.18.3)
        for _ in i..n {print!("\x1b[D");}
        io::stdout().flush().ok();
    }

    try!(tcsetattr(fd, TCSANOW, &tio_backup));
    let s: String = a.into_iter().collect();
    return Ok(s);
}

pub fn getline(prompt: &str) -> io::Result<String>{
    let history = History{first: None};
    return getline_history(prompt,&history);
}

/*
pub fn getline(prompt: &str) -> io::Result<String>{
    print!("> ");
    io::stdout().flush().ok();
    let mut input = String::new();
    return match io::stdin().read_line(&mut input) {
        Ok(_) => Ok(input),
        Err(x) => Err(x)
    };
}
*/

pub fn read_module_file(id: &str) -> Result<String,String> {
    let mut path = id.to_string();
    path.push_str(".moss");
    let mut f = match File::open(&path) {
        Ok(f) => f,
        Err(_) => {
            let mut path = match home_dir() {
                Some(path) => path,
                None => {
                    return Err("Error in load: unable to get the home directory.".to_string());
                }
            };
            path.push(".moss");
            path.push(id);
            path.set_extension("moss");
            // println!("path: '{}'",path.to_str().unwrap());
            match File::open(&path) {
                Ok(f) => f,
                Err(_) => {
                    return Err(format!("Error in load: could not open file '{}.moss'.",id));
                }
            }
        }
    };
    let mut s = String::new();
    if let Err(_) = f.read_to_string(&mut s) {
        return Err(format!("Error in load: could not read file '{}.moss'.",id));
    }
    return Ok(s);
}

pub fn read_file(id: &str) -> Result<String,String> {
    let mut f = match File::open(id) {
        Ok(f) => f,
        Err(_) => return Err(format!("Error in read: could not open file '{}'.",id))
    };
    let mut s = String::new();
    if let Err(_) = f.read_to_string(&mut s) {
        return Err(format!("Error in read: could not read file '{}'.",id));
    }
    return Ok(s);
}
<commit_msg>update<commit_after>
extern crate libc;
extern crate termios;
use std::str;
use std::env::home_dir;
use std::fs::File;
use std::io::Read;
use std::io;
use std::io::Write;
use std::os::unix::io::RawFd;
use self::termios::{
    Termios, tcsetattr, TCSANOW, ICANON, ECHO
};
const STDIN_FILENO: i32 = 0;
const TAB: i32 = 9;
const NEWLINE: i32 = 10;
const ESC: i32 = 27;
const ARROW: i32 = 91;
const UP: i32 = 65;
const DOWN: i32 = 66;
const LEFT: i32 = 68;
const RIGHT: i32 = 67;
const BACKSPACE: i32 = 127;

fn get_win_size() -> (usize, usize) {
    use std::mem::zeroed;
    unsafe {
        let mut size: libc::winsize = zeroed();
        match libc::ioctl(libc::STDOUT_FILENO, libc::TIOCGWINSZ, &mut size) {
            0 => (size.ws_col as usize, size.ws_row as usize),
            _ => (80, 24),
        }
    }
}

fn get_cols() -> usize {
    let (cols,_) = get_win_size();
    return cols;
}

struct HistoryNode{
    s: String,
    next: Option<Box<HistoryNode>>
}
pub struct History{
    first: Option<Box<HistoryNode>>
}

impl History{
    pub fn get(&self, index: usize) -> Option<String> {
        if index==0 {return None;}
        if let Some(ref first) = self.first {
            let mut p = first;
            for _ in 0..index-1 {
                if let Some(ref next) = p.next {
                    p = next;
                }else{
                    return None;
                }
            }
            return Some(p.s.clone());
        }
        return None;
    }
    pub fn new() -> History{
        return History{first: None};
    }
    pub fn append(&mut self, s: &str){
        if let Some(ref first) = self.first {
            if &first.s==s {return;}
        }
        self.first = Some(Box::new(HistoryNode{
            s: String::from(s), next: self.first.take()
        }));
    }
}

fn getchar() -> i32 {
    unsafe{libc::getchar()}
}

fn flush() {
    io::stdout().flush().ok();
}

fn print_flush(s: &str) {
    print!("{}",s);
    io::stdout().flush().ok();
}

fn clear(cols: usize, prompt: &str, a: &Vec<char>){
    let lines = number_of_lines(cols,prompt,&a);
    clear_input(lines);
}

fn print_prompt_flush(prompt: &str, a: &Vec<char>) {
    print!("{}",prompt);
    for x in a {print!("{}",x);}
    flush();
}

fn number_of_bytes(c: u8) -> usize {
    let x=c;
    let mut i: i32 =7;
    while i>=0 && x>>i&1 == 1 {
        i-=1;
    }
    return 7-i as usize;
}

fn number_of_lines(cols: usize, prompt: &str, a: &Vec<char>) -> usize{
    let n = prompt.len()+a.len();
    return if n==0 {1} else {(n-1)/cols+1};
}

fn clear_input(lines: usize){
    print!("\x1b[2K\r");
    for _ in 1..lines {
        print!("\x1b[1A");
        print!("\x1b[2K\r");
    }
}

fn complete_u32_char(c: i32) -> char {
    if c>127 {
        let mut buffer: [u8;8] = [0,0,0,0,0,0,0,0];
        let bytes = number_of_bytes(c as u8);
        match bytes {
            2 => {
                buffer[0]=c as u8;
                buffer[1]=getchar() as u8;
            },
            3 => {
                buffer[0]=c as u8;
                buffer[1]=getchar() as u8;
                buffer[2]=getchar() as u8;
            },
            4 => {
                buffer[0]=c as u8;
                buffer[1]=getchar() as u8;
                buffer[2]=getchar() as u8;
                buffer[3]=getchar() as u8;
            },
            _ => panic!()
        };
        let s = match str::from_utf8(&buffer[0..bytes]) {
            Ok(s) => s, Err(_) => "?"
        };
        return match s.chars().next() {
            Some(x) => x, None => '?'
        };
    }else{
        return c as u8 as char;
    }
}

pub fn getline_history(prompt: &str, history: &History) -> io::Result<String> {
    let fd: RawFd = STDIN_FILENO;
    let tio_backup = try!(Termios::from_fd(fd));
    let mut tio = tio_backup.clone();

    tio.c_lflag &= !(ICANON|ECHO);
    try!(tcsetattr(fd, TCSANOW, &tio));
    print!("{}",prompt);
    flush();

    let mut history_index=0;
    let cols = get_cols();

    let mut a: Vec<char> = Vec::new();
    let mut i: usize = 0;
    let mut n: usize = 0;

    loop{
        let c = getchar();
        if c==NEWLINE {
            println!();
            break;
        }else if c<32 {
            if c==ESC {
                let c2 = getchar();
                if c2==ARROW {
                    let c3 = getchar();
                    if c3==LEFT {
                        if i>0 {i-=1; print_flush("\x1b[1D");}
                        continue;
                    }else if c3==RIGHT {
                        if i<n {i+=1; print_flush("\x1b[1C");}
                        continue;
                    }else if c3==UP {
                        if let Some(x) = history.get(history_index+1) {
                            clear(cols,prompt,&a);
                            a = x.chars().collect();
                            n = a.len(); i=n;
                            history_index+=1;
                            print_prompt_flush(prompt,&a);
                        }
                        continue;
                    }else if c3==DOWN {
                        if history_index>0 {
                            if history_index==1 {
                                clear(cols,prompt,&a);
                                history_index=0;
                                a = vec![];
                                i=0; n=0;
                                print_prompt_flush(prompt,&a);
                            }else if let Some(x) = history.get(history_index-1) {
                                clear(cols,prompt,&a);
                                history_index-=1;
                                a = x.chars().collect();
                                n = a.len(); i=n;
                                print_prompt_flush(prompt,&a);
                            }else{
                                panic!();
                            }
                        }
                        continue;
                    }else{
                        continue;
                    }
                }else{
                    continue;
                }
            }else if c != TAB {
                continue;
            }
        }else if c==BACKSPACE {
            if i>0 {
                for j in i..n {
                    a[j-1]=a[j];
                }
                a.pop();
                n-=1; i-=1;
                print!("\x1b[D");
                for j in i..n {
                    print!("{}",a[j]);
                }
                print!(" ");
                for _ in i..n+1 {
                    print!("\x1b[D");
                }
                flush();
            }
            continue;
        }
        let cu32 = complete_u32_char(c);
        a.push('0');
        for j in (i..n).rev() {
            a[j+1]=a[j];
        }
        a[i] = cu32;
        i+=1; n+=1;
        for j in i-1..n {
            print!("{}",a[j]);
        }

        // Bug: a hanzi, say 0x4567, hampers the cursor
        // to move backward by one character.
        // (GNOME Terminal 3.18.3)
        for _ in i..n {print!("\x1b[D");}
        flush();
    }
    try!(tcsetattr(fd, TCSANOW, &tio_backup));
    let s: String = a.into_iter().collect();
    return Ok(s);
}

pub fn getline(prompt: &str) -> io::Result<String>{
    let history = History{first: None};
    return getline_history(prompt,&history);
}

/*
pub fn getline(prompt: &str) -> io::Result<String>{
    print!("> ");
    io::stdout().flush().ok();
    let mut input = String::new();
    return match io::stdin().read_line(&mut input) {
        Ok(_) => Ok(input),
        Err(x) => Err(x)
    };
}
*/

pub fn read_module_file(id: &str) -> Result<String,String> {
    let mut path = id.to_string();
    path.push_str(".moss");
    let mut f = match File::open(&path) {
        Ok(f) => f,
        Err(_) => {
            let mut path = match home_dir() {
                Some(path) => path,
                None => {
                    return Err("Error in load: unable to get the home directory.".to_string());
                }
            };
            path.push(".moss");
            path.push(id);
            path.set_extension("moss");
            // println!("path: '{}'",path.to_str().unwrap());
            match File::open(&path) {
                Ok(f) => f,
                Err(_) => {
                    return Err(format!("Error in load: could not open file '{}.moss'.",id));
                }
            }
        }
    };
    let mut s = String::new();
    if let Err(_) = f.read_to_string(&mut s) {
        return Err(format!("Error in load: could not read file '{}.moss'.",id));
    }
    return Ok(s);
}

pub fn read_file(id: &str) -> Result<String,String> {
    let mut f = match File::open(id) {
        Ok(f) => f,
        Err(_) => return Err(format!("Error in read: could not open file '{}'.",id))
    };
    let mut s = String::new();
    if let Err(_) = f.read_to_string(&mut s) {
        return Err(format!("Error in read: could not read file '{}'.",id));
    }
    return Ok(s);
}
<|endoftext|>


<commit_before>use tensor::Tensor;

#[test]
fn add_axis() {
    let mut a: Tensor<f64> = Tensor::range(2*3*4).reshaped(&[2, 3, 4]);

    let answer0 = Tensor::new(vec![12., 14., 16., 18.,
                                   20., 22., 24., 26.,
                                   28., 30., 32., 34.]).reshaped(&[3, 4]);

    let answer1 = Tensor::new(vec![12., 15., 18., 21.,
                                   48., 51., 54., 57.]).reshaped(&[2, 4]);

    let answer2 = Tensor::new(vec![6., 22., 38.,
                                   54., 70., 86.]).reshaped(&[2, 3]);

    let c0 = a.sum_axis(0);
    assert!(c0 == answer0);

    let c1 = a.sum_axis(1);
    assert!(c1 == answer1);

    let c2 = a.sum_axis(2);
    assert!(c2 == answer2);
}

#[test]
fn bitand_axis() {
    let mut a = Tensor::new(vec![true, true, true,
                                 false, true, false]).reshaped(&[2, 3]);

    let answer0 = Tensor::new(vec![false, true, false]);
    let answer1 = Tensor::new(vec![true, false]);

    let c0 = a.bitand_axis(0);
    assert!(c0 == answer0);

    let c1 = a.bitand_axis(1);
    assert!(c1 == answer1);
}
<commit_msg>Removed warnings<commit_after>#[allow(unused_imports)]
use tensor::Tensor;

#[test]
fn add_axis() {
    let a: Tensor<f64> = Tensor::range(2*3*4).reshaped(&[2, 3, 4]);

    let answer0 = Tensor::new(vec![12., 14., 16., 18.,
                                   20., 22., 24., 26.,
                                   28., 30., 32., 34.]).reshaped(&[3, 4]);

    let answer1 = Tensor::new(vec![12., 15., 18., 21.,
                                   48., 51., 54., 57.]).reshaped(&[2, 4]);

    let answer2 = Tensor::new(vec![6., 22., 38.,
                                   54., 70., 86.]).reshaped(&[2, 3]);

    let c0 = a.sum_axis(0);
    assert!(c0 == answer0);

    let c1 = a.sum_axis(1);
    assert!(c1 == answer1);

    let c2 = a.sum_axis(2);
    assert!(c2 == answer2);
}

#[test]
fn bitand_axis() {
    let a = Tensor::new(vec![true, true, true,
                             false, true, false]).reshaped(&[2, 3]);

    let answer0 = Tensor::new(vec![false, true, false]);
    let answer1 = Tensor::new(vec![true, false]);

    let c0 = a.bitand_axis(0);
    assert!(c0 == answer0);

    let c1 = a.bitand_axis(1);
    assert!(c1 == answer1);
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashMap};

use search::term::Term;
use search::document::Document;

#[derive(Debug)]
pub struct MemoryIndexStore {
    docs: BTreeMap<u64, Document>,
    index: BTreeMap<Term, BTreeMap<String, Vec<(u64, u32)>>>,
    next_doc_num: u64,
    doc_id_map: HashMap<String, u64>,
}

impl MemoryIndexStore {
    pub fn new() -> MemoryIndexStore {
        MemoryIndexStore {
            docs: BTreeMap::new(),
            index: BTreeMap::new(),
            next_doc_num: 1,
            doc_id_map: HashMap::new(),
        }
    }

    pub fn get_document_by_id(&self, id: &str) -> Option<&Document> {
        match self.doc_id_map.get(id) {
            Some(doc_num) => self.docs.get(doc_num),
            None => None,
        }
    }

    pub fn contains_document_id(&self, id: &str) -> bool {
        self.doc_id_map.contains_key(id)
    }

    pub fn remove_document_by_id(&mut self, id: &str) -> bool {
        match self.doc_id_map.remove(id) {
            Some(doc_num) => {
                self.docs.remove(&doc_num);

                true
            }
            None => false
        }
    }

    pub fn insert_or_update_document(&mut self, doc: Document) {
        let doc_num = self.next_doc_num;
        self.next_doc_num += 1;

        // Put field contents in inverted index
        for (field_name, tokens) in doc.fields.iter() {
            let mut position: u32 = 1;

            for token in tokens.iter() {
                if !self.index.contains_key(&token.term) {
                    self.index.insert(token.term.clone(), BTreeMap::new());
                }

                let mut index_fields = self.index.get_mut(&token.term).unwrap();

                if !index_fields.contains_key(field_name) {
                    index_fields.insert(field_name.clone(), Vec::new());
                }

                let mut postings_list = index_fields.get_mut(field_name).unwrap();
                postings_list.push((doc_num, token.position));
            }
        }

        self.doc_id_map.insert(doc.id.clone(), doc_num);
        self.docs.insert(doc_num, doc);
    }

    pub fn next_phrase(&self, terms: &Vec<Term>, field_name: &str, position: Option<(u64, u32)>) -> Option<(u64, u32)> {
        let mut v = position;

        for term in terms.iter() {
            v = self.next(term, field_name, v);

            if v == None {
                return None;
            }
        }

        let mut u = v;
        for term in terms.iter().rev().skip(1) {
            u = self.prev(term, field_name, u);

            if u == None {
                return None;
            }
        }

        let v = v.unwrap();
        let u = u.unwrap();
        if v.0 == u.0 && v.1 - u.1 == terms.len() as u32 - 1 {
            Some((v.0, u.1))
        } else {
            self.next_phrase(terms, field_name, Some(u))
        }
    }

    pub fn next(&self, term: &Term, field_name: &str, position: Option<(u64, u32)>) -> Option<(u64, u32)> {
        let posting_fields = match self.index.get(term) {
            Some(posting_fields) => posting_fields,
            None => return None,
        };

        let postings = match posting_fields.get(field_name) {
            Some(postings) => postings,
            None => return None,
        };

        match position {
            Some(position) => {
                // Find first posting after specified position
                // TODO: Speed this up (see section 2.1.2 of the IR book)
                for posting in postings.iter() {
                    if *posting > position {
                        return Some(posting.clone());
                    }
                }

                // Ran out of postings
                return None;
            }
            None => {
                // Position not specified, return first posting
                return postings.first().cloned();
            }
        }
    }

    pub fn prev(&self, term: &Term, field_name: &str, position: Option<(u64, u32)>) -> Option<(u64, u32)> {
        let posting_fields = match self.index.get(term) {
            Some(posting_fields) => posting_fields,
            None => return None,
        };

        let postings = match posting_fields.get(field_name) {
            Some(postings) => postings,
            None => return None,
        };

        match position {
            Some(position) => {
                // Find first posting before specified position
                // TODO: Speed this up (see section 2.1.2 of the IR book)
                for posting in postings.iter().rev() {
                    if *posting < position {
                        return Some(posting.clone());
                    }
                }

                // Ran out of postings
                return None;
            }
            None => {
                // Position not specified, return last posting
                return postings.last().cloned();
            }
        }
    }

    pub fn num_docs(&self) -> usize {
        self.docs.len()
    }

    pub fn iter_docs<'a>(&'a self) -> Box<Iterator<Item=&'a Document> + 'a> {
        Box::new(self.docs.values())
    }
}
<commit_msg>Removed unused index iteration functions<commit_after>use std::collections::{BTreeMap, HashMap};

use search::term::Term;
use search::document::Document;

#[derive(Debug)]
pub struct MemoryIndexStore {
    docs: BTreeMap<u64, Document>,
    index: BTreeMap<Term, BTreeMap<String, Vec<(u64, u32)>>>,
    next_doc_num: u64,
    doc_id_map: HashMap<String, u64>,
}

impl MemoryIndexStore {
    pub fn new() -> MemoryIndexStore {
        MemoryIndexStore {
            docs: BTreeMap::new(),
            index: BTreeMap::new(),
            next_doc_num: 1,
            doc_id_map: HashMap::new(),
        }
    }

    pub fn get_document_by_id(&self, id: &str) -> Option<&Document> {
        match self.doc_id_map.get(id) {
            Some(doc_num) => self.docs.get(doc_num),
            None => None,
        }
    }

    pub fn contains_document_id(&self, id: &str) -> bool {
        self.doc_id_map.contains_key(id)
    }

    pub fn remove_document_by_id(&mut self, id: &str) -> bool {
        match self.doc_id_map.remove(id) {
            Some(doc_num) => {
                self.docs.remove(&doc_num);

                true
            }
            None => false
        }
    }

    pub fn insert_or_update_document(&mut self, doc: Document) {
        let doc_num = self.next_doc_num;
        self.next_doc_num += 1;

        // Put field contents in inverted index
        for (field_name, tokens) in doc.fields.iter() {
            let mut position: u32 = 1;

            for token in tokens.iter() {
                if !self.index.contains_key(&token.term) {
                    self.index.insert(token.term.clone(), BTreeMap::new());
                }

                let mut index_fields = self.index.get_mut(&token.term).unwrap();

                if !index_fields.contains_key(field_name) {
                    index_fields.insert(field_name.clone(), Vec::new());
                }

                let mut postings_list = index_fields.get_mut(field_name).unwrap();
                postings_list.push((doc_num, token.position));
            }
        }

        self.doc_id_map.insert(doc.id.clone(), doc_num);
        self.docs.insert(doc_num, doc);
    }

    pub fn num_docs(&self) -> usize {
        self.docs.len()
    }

    pub fn iter_docs<'a>(&'a self) -> Box<Iterator<Item=&'a Document> + 'a> {
        Box::new(self.docs.values())
    }
}
<|endoftext|>


<commit_before>use roaring::RoaringBitmap;

use std::collections::{BTreeMap, HashMap};
use std::collections::Bound::{Excluded, Unbounded};

use search::term::Term;
use search::document::Document;
use search::index::reader::{IndexReader, DocRefIterator};

#[derive(Debug)]
pub struct MemoryIndexStore {
    docs: BTreeMap<u64, Document>,
    index: BTreeMap<Term, BTreeMap<String, RoaringBitmap<u64>>>,
    next_doc_id: u64,
    doc_key2id_map: HashMap<String, u64>,
}

impl MemoryIndexStore {
    pub fn new() -> MemoryIndexStore {
        MemoryIndexStore {
            docs: BTreeMap::new(),
            index: BTreeMap::new(),
            next_doc_id: 1,
            doc_key2id_map: HashMap::new(),
        }
    }

    pub fn get_document_by_key(&self, doc_key: &str) -> Option<&Document> {
        match self.doc_key2id_map.get(doc_key) {
            Some(doc_id) => self.docs.get(doc_id),
            None => None,
        }
    }

    pub fn get_document_by_id(&self, doc_id: &u64) -> Option<&Document> {
        self.docs.get(doc_id)
    }

    pub fn contains_document_key(&self, doc_key: &str) -> bool {
        self.doc_key2id_map.contains_key(doc_key)
    }

    pub fn remove_document_by_key(&mut self, doc_key: &str) -> bool {
        match self.doc_key2id_map.remove(doc_key) {
            Some(doc_id) => {
                self.docs.remove(&doc_id);

                true
            }
            None => false
        }
    }

    pub fn insert_or_update_document(&mut self, doc: Document) {
        let doc_id = self.next_doc_id;
        self.next_doc_id += 1;

        // Put field contents in inverted index
        for (field_name, tokens) in doc.fields.iter() {
            let mut position: u32 = 1;

            for token in tokens.iter() {
                if !self.index.contains_key(&token.term) {
                    self.index.insert(token.term.clone(), BTreeMap::new());
                }

                let mut index_fields = self.index.get_mut(&token.term).unwrap();
                if !index_fields.contains_key(field_name) {
                    index_fields.insert(field_name.clone(), RoaringBitmap::new());
                }

                let mut index_docs = index_fields.get_mut(field_name).unwrap();
                index_docs.insert(doc_id);
            }
        }

        self.doc_key2id_map.insert(doc.key.clone(), doc_id);
        self.docs.insert(doc_id, doc);
    }

    pub fn next_doc(&self, term: &Term, field_name: &str, previous_doc: Option<u64>) -> Option<u64> {
        let fields = match self.index.get(term) {
            Some(fields) => fields,
            None => return None,
        };

        let docs = match fields.get(field_name) {
            Some(docs) => docs,
            None => return None,
        };

        match previous_doc {
            Some(previous_doc) => {
                // Find first doc after specified doc
                // TODO: Speed this up (see section 2.1.2 of the IR book)
                for doc_id in docs.iter() {
                    if doc_id > previous_doc {
                        return Some(doc_id);
                    }
                }

                // Ran out of docs
                return None;
            }
            None => {
                // Previous doc not specified, return first doc
                match docs.iter().next() {
                    Some(doc_id) => Some(doc_id),
                    None => None,
                }
            }
        }
    }

    pub fn next_doc_all(&self, position: Option<u64>) -> Option<u64> {
        match position {
            Some(doc_id) => {
                self.docs.range(Excluded(&doc_id), Unbounded).map(|(doc_id, doc)| *doc_id).nth(0)
            }
            None => {
                self.docs.keys().nth(0).cloned()
            }
        }
    }
}

impl<'a> IndexReader<'a> for MemoryIndexStore {
    type AllDocRefIterator = MemoryIndexStoreAllDocRefIterator<'a>;
    type TermDocRefIterator = MemoryIndexStoreTermDocRefIterator<'a>;

    fn num_docs(&self) -> usize {
        self.docs.len()
    }

    fn iter_docids_all(&'a self) -> MemoryIndexStoreAllDocRefIterator<'a> {
        MemoryIndexStoreAllDocRefIterator {
            store: self,
            last_doc: None,
        }
    }

    fn iter_docids_with_term(&'a self, term: Term, field_name: String) -> MemoryIndexStoreTermDocRefIterator<'a> {
        MemoryIndexStoreTermDocRefIterator {
            store: self,
            term: term,
            field_name: field_name,
            last_doc: None,
        }
    }

    fn iter_terms(&'a self) -> Box<Iterator<Item=&'a Term> + 'a> {
        Box::new(self.index.keys())
    }
}

pub struct MemoryIndexStoreAllDocRefIterator<'a> {
    store: &'a MemoryIndexStore,
    last_doc: Option<u64>,
}

impl<'a> Iterator for MemoryIndexStoreAllDocRefIterator<'a> {
    type Item = u64;

    fn next(&mut self) -> Option<u64> {
        self.last_doc = self.store.next_doc_all(self.last_doc);

        self.last_doc
    }
}

impl<'a> DocRefIterator<'a> for MemoryIndexStoreAllDocRefIterator<'a> {

}

pub struct MemoryIndexStoreTermDocRefIterator<'a> {
    store: &'a MemoryIndexStore,
    term: Term,
    field_name: String,
    last_doc: Option<u64>,
}

impl<'a> Iterator for MemoryIndexStoreTermDocRefIterator<'a> {
    type Item = u64;

    fn next(&mut self) -> Option<u64> {
        self.last_doc = match self.store.next_doc(&self.term, &self.field_name, self.last_doc) {
            Some(doc_id) => Some(doc_id),
            None => None,
        };

        self.last_doc
    }
}

impl<'a> DocRefIterator<'a> for MemoryIndexStoreTermDocRefIterator<'a> {

}

#[cfg(test)]
mod tests {
    use super::MemoryIndexStore;

    use search::term::Term;
    use search::analysis::Analyzer;
    use search::document::Document;
    use search::index::reader::IndexReader;

    fn make_test_store() -> MemoryIndexStore {
        let mut store = MemoryIndexStore::new();

        store.insert_or_update_document(Document {
            key: "test_doc".to_string(),
            fields: btreemap! {
                "title".to_string() => Analyzer::Standard.run("hello world".to_string()),
                "body".to_string() => Analyzer::Standard.run("lorem ipsum dolar".to_string()),
            }
        });

        store.insert_or_update_document(Document {
            key: "test_doc".to_string(),
            fields: btreemap! {
                "title".to_string() => Analyzer::Standard.run("howdy partner".to_string()),
                "body".to_string() => Analyzer::Standard.run("lorem ipsum dolar".to_string()),
            }
        });

        store
    }

    #[test]
    fn test_num_docs() {
        let store = make_test_store();

        assert_eq!(store.num_docs(), 2);
    }

    #[test]
    fn test_all_docs_iterator() {
        let store = make_test_store();

        assert_eq!(store.iter_docids_all().count(), 2);
    }

    #[test]
    fn test_term_docs_iterator() {
        let store = make_test_store();

        assert_eq!(store.iter_docids_with_term(Term::String("hello".to_string()), "title".to_string()).count(), 1);
    }
}
<commit_msg>Optimise all docs iterator<commit_after>use roaring::RoaringBitmap;

use std::collections::{BTreeMap, HashMap};
use std::collections::Bound::{Excluded, Unbounded};
use std::collections::btree_map::Keys;

use search::term::Term;
use search::document::Document;
use search::index::reader::{IndexReader, DocRefIterator};

#[derive(Debug)]
pub struct MemoryIndexStore {
    docs: BTreeMap<u64, Document>,
    index: BTreeMap<Term, BTreeMap<String, RoaringBitmap<u64>>>,
    next_doc_id: u64,
    doc_key2id_map: HashMap<String, u64>,
}

impl MemoryIndexStore {
    pub fn new() -> MemoryIndexStore {
        MemoryIndexStore {
            docs: BTreeMap::new(),
            index: BTreeMap::new(),
            next_doc_id: 1,
            doc_key2id_map: HashMap::new(),
        }
    }

    pub fn get_document_by_key(&self, doc_key: &str) -> Option<&Document> {
        match self.doc_key2id_map.get(doc_key) {
            Some(doc_id) => self.docs.get(doc_id),
            None => None,
        }
    }

    pub fn get_document_by_id(&self, doc_id: &u64) -> Option<&Document> {
        self.docs.get(doc_id)
    }

    pub fn contains_document_key(&self, doc_key: &str) -> bool {
        self.doc_key2id_map.contains_key(doc_key)
    }

    pub fn remove_document_by_key(&mut self, doc_key: &str) -> bool {
        match self.doc_key2id_map.remove(doc_key) {
            Some(doc_id) => {
                self.docs.remove(&doc_id);

                true
            }
            None => false
        }
    }

    pub fn insert_or_update_document(&mut self, doc: Document) {
        let doc_id = self.next_doc_id;
        self.next_doc_id += 1;

        // Put field contents in inverted index
        for (field_name, tokens) in doc.fields.iter() {
            let mut position: u32 = 1;

            for token in tokens.iter() {
                if !self.index.contains_key(&token.term) {
                    self.index.insert(token.term.clone(), BTreeMap::new());
                }

                let mut index_fields = self.index.get_mut(&token.term).unwrap();
                if !index_fields.contains_key(field_name) {
                    index_fields.insert(field_name.clone(), RoaringBitmap::new());
                }

                let mut index_docs = index_fields.get_mut(field_name).unwrap();
                index_docs.insert(doc_id);
            }
        }

        self.doc_key2id_map.insert(doc.key.clone(), doc_id);
        self.docs.insert(doc_id, doc);
    }

    pub fn next_doc(&self, term: &Term, field_name: &str, previous_doc: Option<u64>) -> Option<u64> {
        let fields = match self.index.get(term) {
            Some(fields) => fields,
            None => return None,
        };

        let docs = match fields.get(field_name) {
            Some(docs) => docs,
            None => return None,
        };

        match previous_doc {
            Some(previous_doc) => {
                // Find first doc after specified doc
                // TODO: Speed this up (see section 2.1.2 of the IR book)
                for doc_id in docs.iter() {
                    if doc_id > previous_doc {
                        return Some(doc_id);
                    }
                }

                // Ran out of docs
                return None;
            }
            None => {
                // Previous doc not specified, return first doc
                match docs.iter().next() {
                    Some(doc_id) => Some(doc_id),
                    None => None,
                }
            }
        }
    }
}

impl<'a> IndexReader<'a> for MemoryIndexStore {
    type AllDocRefIterator = MemoryIndexStoreAllDocRefIterator<'a>;
    type TermDocRefIterator = MemoryIndexStoreTermDocRefIterator<'a>;

    fn num_docs(&self) -> usize {
        self.docs.len()
    }

    fn iter_docids_all(&'a self) -> MemoryIndexStoreAllDocRefIterator<'a> {
        MemoryIndexStoreAllDocRefIterator {
            keys: self.docs.keys(),
        }
    }

    fn iter_docids_with_term(&'a self, term: Term, field_name: String) -> MemoryIndexStoreTermDocRefIterator<'a> {
        MemoryIndexStoreTermDocRefIterator {
            store: self,
            term: term,
            field_name: field_name,
            last_doc: None,
        }
    }

    fn iter_terms(&'a self) -> Box<Iterator<Item=&'a Term> + 'a> {
        Box::new(self.index.keys())
    }
}

pub struct MemoryIndexStoreAllDocRefIterator<'a> {
    keys: Keys<'a, u64, Document>,
}

impl<'a> Iterator for MemoryIndexStoreAllDocRefIterator<'a> {
    type Item = u64;

    fn next(&mut self) -> Option<u64> {
        self.keys.next().cloned()
    }
}

impl<'a> DocRefIterator<'a> for MemoryIndexStoreAllDocRefIterator<'a> {

}

pub struct MemoryIndexStoreTermDocRefIterator<'a> {
    store: &'a MemoryIndexStore,
    term: Term,
    field_name: String,
    last_doc: Option<u64>,
}

impl<'a> Iterator for MemoryIndexStoreTermDocRefIterator<'a> {
    type Item = u64;

    fn next(&mut self) -> Option<u64> {
        self.last_doc = match self.store.next_doc(&self.term, &self.field_name, self.last_doc) {
            Some(doc_id) => Some(doc_id),
            None => None,
        };

        self.last_doc
    }
}

impl<'a> DocRefIterator<'a> for MemoryIndexStoreTermDocRefIterator<'a> {

}

#[cfg(test)]
mod tests {
    use super::MemoryIndexStore;

    use search::term::Term;
    use search::analysis::Analyzer;
    use search::document::Document;
    use search::index::reader::IndexReader;

    fn make_test_store() -> MemoryIndexStore {
        let mut store = MemoryIndexStore::new();

        store.insert_or_update_document(Document {
            key: "test_doc".to_string(),
            fields: btreemap! {
                "title".to_string() => Analyzer::Standard.run("hello world".to_string()),
                "body".to_string() => Analyzer::Standard.run("lorem ipsum dolar".to_string()),
            }
        });

        store.insert_or_update_document(Document {
            key: "test_doc".to_string(),
            fields: btreemap! {
                "title".to_string() => Analyzer::Standard.run("howdy partner".to_string()),
                "body".to_string() => Analyzer::Standard.run("lorem ipsum dolar".to_string()),
            }
        });

        store
    }

    #[test]
    fn test_num_docs() {
        let store = make_test_store();

        assert_eq!(store.num_docs(), 2);
    }

    #[test]
    fn test_all_docs_iterator() {
        let store = make_test_store();

        assert_eq!(store.iter_docids_all().count(), 2);
    }

    #[test]
    fn test_term_docs_iterator() {
        let store = make_test_store();

        assert_eq!(store.iter_docids_with_term(Term::String("hello".to_string()), "title".to_string()).count(), 1);
    }
}
<|endoftext|>


<commit_before>//! Methods for converting shapes into triangles.

use {Matrix2d, Rectangle};

#[inline(always)]
fn tx(m: &Matrix2d, x: f64, y: f64) -> f32 {
    (m[0] * x + m[1] * y + m[2]) as f32
}

#[inline(always)]
fn ty(m: &Matrix2d, x: f64, y: f64) -> f32 {
    (m[3] * x + m[4] * y + m[5]) as f32
}

/// Splits polygon into convex segments with one color per vertex.
/// Create a buffer that fits into L1 cache with 1KB overhead.
pub fn with_polygon_tri_list_xy_rgba_f32(
    m: &Matrix2d,
    polygon: &[f64],
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    if polygon.len() < 2 { return; }
    let mut vertices: [f32, ..740] = [0.0, ..740];
    let mut colors: [f32, ..1480] = [0.0, ..1480];
    // Draw first triangle for testing.
    let triangles = (polygon.len() - 4) / 2;
    // Get the first point which will be used a lot.
    let fx = polygon[0];
    let fy = polygon[1];
    let (fx, fy) = (tx(m, fx, fy), ty(m, fx, fy));
    for i in range(0u, triangles) {
        // Set the first point in triangle to use the beginning.
        let ind_out = i * 2 * 3;
        vertices[ind_out + 0] = fx;
        vertices[ind_out + 1] = fy;
        for k in range(1u, 3) {
            // Copy vertex.
            let ind_in = i * 2 + k * 2;
            let ind_out = i * 2 * 3 + k * 2;
            let (x, y) = (polygon[ind_in + 0], polygon[ind_in + 1]);
            vertices[ind_out + 0] = tx(m, x, y);
            vertices[ind_out + 1] = ty(m, x, y);
        }

        for k in range(0u, 3) {
            // Copy color.
            let ind_out = i * 4 * 3 + k * 4;
            colors[ind_out + 0] = color[0];
            colors[ind_out + 1] = color[1];
            colors[ind_out + 2] = color[2];
            colors[ind_out + 3] = color[3];
        }
    }

    f(vertices.slice(0, triangles * 2 * 3),
        colors.slice(0, triangles * 4 * 3));
}

/// Creates triangle list vertices from rectangle.
pub fn rect_tri_list_xy_f32(m: &Matrix2d, rect: &Rectangle) -> [f32, ..12] {
    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let (x2, y2) = (x + w, y + h);
    [tx(m,x,y), ty(m,x,y), tx(m,x2,y), ty(m,x2,y), tx(m,x,y2), ty(m,x,y2),
     tx(m,x2,y), ty(m,x2,y), tx(m,x2,y2), ty(m,x2,y2), tx(m,x,y2), ty(m,x,y2)]
}

/// Creates triangle list colors from rectangle.
pub fn rect_tri_list_rgba_f32(color: [f32, ..4]) -> [f32, ..48] {
    let (r, g, b, a) = (color[0], color[1], color[2], color[3]);
    [r, g, b, a, // 0
     r, g, b, a, // 1
     r, g, b, a, // 2
     r, g, b, a, // 3
     r, g, b, a, // 4
     r, g, b, a, // 5
     r, g, b, a, // 6
     r, g, b, a, // 7
     r, g, b, a, // 8
     r, g, b, a, // 9
     r, g, b, a, // 10
     r, g, b, a]
}

<commit_msg>Added stream_polygon_tri_list_xy_rgba_f32<commit_after>//! Methods for converting shapes into triangles.

use {Matrix2d, Rectangle};

#[inline(always)]
fn tx(m: &Matrix2d, x: f64, y: f64) -> f32 {
    (m[0] * x + m[1] * y + m[2]) as f32
}

#[inline(always)]
fn ty(m: &Matrix2d, x: f64, y: f64) -> f32 {
    (m[3] * x + m[4] * y + m[5]) as f32
}

/// Streams a polygon into tri list with color per vertex.
/// Uses buffers that fit inside L1 cache.
pub fn stream_polygon_tri_list_xy_rgba_f32(
    m: &Matrix2d,
    polygon: || -> Option<[f64, ..2]>,
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    let mut vertices: [f32, ..740] = [0.0, ..740];
    let mut colors: [f32, ..1480] = [0.0, ..1480];
    // Draw first triangle for testing.
    // Get the first point which will be used a lot.
    let fp = match polygon() { None => return, Some(val) => val };
    let (fx, fy) = (tx(m, fp[0], fp[1]), ty(m, fp[0], fp[1]));
    let mut i = 0;
    'read_vertices: loop {
        // Set the first point in triangle to use the beginning.
        let ind_out = i * 2 * 3;
        vertices[ind_out + 0] = fx;
        vertices[ind_out + 1] = fy;
        let ind_out = i * 4 * 3;
        vertices[ind_out + 0] = color[0];
        vertices[ind_out + 1] = color[1];
        vertices[ind_out + 2] = color[2];
        vertices[ind_out + 3] = color[3];

        for k in range(1u, 3) {
            // Copy vertex.
            let ind_out = i * 2 * 3 + k * 2;
            let p =
                match polygon() {
                    None => break 'read_vertices,
                    Some(val) => val,
                };
            vertices[ind_out + 0] = tx(m, p[0], p[1]);
            vertices[ind_out + 1] = ty(m, p[0], p[1]);
            let ind_out = i * 4 * 3 + k * 3;
            colors[ind_out + 0] = color[0];
            colors[ind_out + 1] = color[1];
            colors[ind_out + 2] = color[2];
            colors[ind_out + 3] = color[3];
        }

        i += 1;
    }

    f(vertices.slice(0, i * 2 * 3),
        colors.slice(0, i * 4 * 3));
}

/// Splits polygon into convex segments with one color per vertex.
/// Create a buffer that fits into L1 cache with 1KB overhead.
pub fn with_polygon_tri_list_xy_rgba_f32(
    m: &Matrix2d,
    polygon: &[f64],
    color: [f32, ..4],
    f: |vertices: &[f32], colors: &[f32]|) {

    if polygon.len() < 2 { return; }
    let mut vertices: [f32, ..740] = [0.0, ..740];
    let mut colors: [f32, ..1480] = [0.0, ..1480];
    // Draw first triangle for testing.
    let triangles = (polygon.len() - 4) / 2;
    // Get the first point which will be used a lot.
    let fx = polygon[0];
    let fy = polygon[1];
    let (fx, fy) = (tx(m, fx, fy), ty(m, fx, fy));
    for i in range(0u, triangles) {
        // Set the first point in triangle to use the beginning.
        let ind_out = i * 2 * 3;
        vertices[ind_out + 0] = fx;
        vertices[ind_out + 1] = fy;
        for k in range(1u, 3) {
            // Copy vertex.
            let ind_in = i * 2 + k * 2;
            let ind_out = i * 2 * 3 + k * 2;
            let (x, y) = (polygon[ind_in + 0], polygon[ind_in + 1]);
            vertices[ind_out + 0] = tx(m, x, y);
            vertices[ind_out + 1] = ty(m, x, y);
        }

        for k in range(0u, 3) {
            // Copy color.
            let ind_out = i * 4 * 3 + k * 4;
            colors[ind_out + 0] = color[0];
            colors[ind_out + 1] = color[1];
            colors[ind_out + 2] = color[2];
            colors[ind_out + 3] = color[3];
        }
    }

    f(vertices.slice(0, triangles * 2 * 3),
        colors.slice(0, triangles * 4 * 3));
}

/// Creates triangle list vertices from rectangle.
pub fn rect_tri_list_xy_f32(m: &Matrix2d, rect: &Rectangle) -> [f32, ..12] {
    let (x, y, w, h) = (rect[0], rect[1], rect[2], rect[3]);
    let (x2, y2) = (x + w, y + h);
    [tx(m,x,y), ty(m,x,y), tx(m,x2,y), ty(m,x2,y), tx(m,x,y2), ty(m,x,y2),
     tx(m,x2,y), ty(m,x2,y), tx(m,x2,y2), ty(m,x2,y2), tx(m,x,y2), ty(m,x,y2)]
}

/// Creates triangle list colors from rectangle.
pub fn rect_tri_list_rgba_f32(color: [f32, ..4]) -> [f32, ..48] {
    let (r, g, b, a) = (color[0], color[1], color[2], color[3]);
    [r, g, b, a, // 0
     r, g, b, a, // 1
     r, g, b, a, // 2
     r, g, b, a, // 3
     r, g, b, a, // 4
     r, g, b, a, // 5
     r, g, b, a, // 6
     r, g, b, a, // 7
     r, g, b, a, // 8
     r, g, b, a, // 9
     r, g, b, a, // 10
     r, g, b, a]
}

<|endoftext|>


<commit_before>//! TODO Documentation

use std::{panic, ptr};
use std::marker::PhantomData;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;

use libc;
use wlroots_sys::{timespec, wlr_surface, wlr_surface_get_main_surface, wlr_surface_get_matrix,
                  wlr_surface_has_buffer, wlr_surface_send_enter, wlr_surface_send_frame_done,
                  wlr_surface_send_leave, wlr_surface_state};

use Output;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use render::Texture;
use utils::c_to_rust_string;

/// The state stored in the wlr_surface user data.
struct InternalSurfaceState {
    /// Used to reconstruct a SurfaceHandle from just an *mut wlr_surface.
    handle: Weak<AtomicBool>
}

/// Surface state as reported by wlroots.
pub struct SurfaceState<'surface> {
    state: *mut wlr_surface_state,
    phantom: PhantomData<&'surface Surface>
}

/// A Wayland object that represents the data that we display on the screen.
///
/// Most surfaces come from Wayland clients, though they can also be created
/// by the compositor directly.
#[derive(Debug)]
pub struct Surface {
    /// The structe that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `SurfaceHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `SurfaceHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

/// See `Surface` for more information on how to use this structure.
#[derive(Clone, Debug)]
pub struct SurfaceHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

impl Surface {
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_surface {
        self.surface
    }

    pub(crate) unsafe fn from_ptr(surface: *mut wlr_surface) -> Self {
        if !(*surface).data.is_null() {
            panic!("Tried to construct a Surface from an already initialized wlr_surface");
        }
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        (*surface).data = Box::into_raw(Box::new(InternalSurfaceState { handle })) as _;
        let liveliness = Some(liveliness);
        Surface { liveliness,
                  surface }
    }

    /// Get the surface state.
    pub fn current_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            SurfaceState { state: (*self.surface).current,
                           phantom: PhantomData }
        }
    }

    /// Get the pending surface state.
    pub fn pending_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            SurfaceState { state: (*self.surface).pending,
                           phantom: PhantomData }
        }
    }

    /// Get the texture of this surface.
    pub fn texture(&self) -> Texture {
        unsafe { Texture::from_ptr((*self.surface).texture) }
    }

    /// Get the lifetime bound role (if one exists) for this surface.
    pub fn role(&self) -> Option<String> {
        unsafe { c_to_rust_string((*self.surface).role) }
    }

    /// Gets a matrix you can pass into wlr_render_with_matrix to display this
    /// surface.
    ///
    /// `matrix` is the output matrix, `projection` is the wlr_output
    /// projection matrix, and `transform` is any additional transformations you want
    /// to perform on the surface (or None/the identity matrix if you don't).
    ///
    /// `transform` is used before the surface is scaled, so its geometry extends
    /// from 0 to 1 in both dimensions.
    pub fn get_matrix<'a, T>(&mut self,
                             matrix: &mut [f32; 16],
                             projection: &[f32; 16],
                             transform: T)
        where T: Into<Option<&'a [f32; 16]>>
    {
        let transform = transform.into()
                                 .map(|transform| transform as *const _)
                                 .unwrap_or_else(|| ptr::null());
        unsafe { wlr_surface_get_matrix(self.surface, matrix, projection, transform) }
    }

    /// Whether or not this surface currently has an attached buffer.
    ///
    /// A surface has an attached buffer when it commits with a non-null buffer in its pending
    /// state.
    ///
    /// A surface will not have a buffer if it has never committed one, has
    /// committed a null buffer, or something went wrong with uploading the buffer.
    pub fn has_buffer(&self) -> bool {
        unsafe { wlr_surface_has_buffer(self.surface) }
    }

    /// Get the top of the subsurface tree for this surface.
    pub fn get_main_surface(&self) -> Option<SurfaceHandle> {
        unsafe {
            let surface = wlr_surface_get_main_surface(self.surface);
            if surface.is_null() {
                None
            } else {
                Some(SurfaceHandle::from_ptr(surface))
            }
        }
    }

    pub fn send_enter(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_enter(self.surface, output.as_ptr()) }
    }

    pub fn send_leave(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_leave(self.surface, output.as_ptr()) }
    }

    /// Send the frame done event.
    pub fn send_frame_done(&mut self, duration: Duration) {
        unsafe {
            // FIXME
            // This is converting from a u64 -> i64
            // Something bad could happen!
            let when = timespec { tv_sec: duration.as_secs() as i64,
                                  tv_nsec: duration.subsec_nanos() as i64 };
            wlr_surface_send_frame_done(self.surface, &when);
        }
    }

    /// Get the matrix used to convert the internal byte buffer to use in the
    /// surface.
    pub fn buffer_to_surface_matrix(&self) -> [f32; 16] {
        unsafe { (*self.surface).buffer_to_surface_matrix }
    }

    /// Get the matrix used to convert the surface back to the internal byte
    /// buffer.
    pub fn surface_to_buffer_matrix(&self) -> [f32; 16] {
        unsafe { (*self.surface).surface_to_buffer_matrix }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Surface")
            .store(val, Ordering::Release);
    }

    unsafe fn from_handle(handle: &SurfaceHandle) -> Self {
        Surface { liveliness: None,
                  surface: handle.surface }
    }
}

impl SurfaceHandle {
    /// Creates an SurfaceHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(surface: *mut wlr_surface) -> Self {
        let data = (*surface).data as *mut InternalSurfaceState;
        let handle = (*data).handle.clone();
        SurfaceHandle { handle, surface }
    }

    /// Upgrades the surface handle to a reference to the backing `Surface`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Surface`
    /// which may live forever..
    /// But no surface lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Surface> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(Surface::from_handle(self))
            })
    }

    /// Run a function on the referenced Surface, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the surface
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Surface does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Surface`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Surface) -> R
    {
        let mut surface = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut surface)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running surface callback, mutable lock \
                                                    was false for: {:?}",
                                                   surface);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }
}

impl<'surface> SurfaceState<'surface> {
    pub fn width(&self) -> libc::c_int {
        unsafe { (*self.state).width }
    }

    pub fn height(&self) -> libc::c_int {
        unsafe { (*self.state).height }
    }
}
<commit_msg>Added ability to get subsurface<commit_after>//! TODO Documentation

use std::{panic, ptr};
use std::marker::PhantomData;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;

use libc;
use wlroots_sys::{timespec, wlr_surface, wlr_surface_get_main_surface, wlr_surface_get_matrix,
                  wlr_surface_has_buffer, wlr_surface_send_enter, wlr_surface_send_frame_done,
                  wlr_surface_send_leave, wlr_surface_state};

use Output;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use render::Texture;
use utils::c_to_rust_string;

/// The state stored in the wlr_surface user data.
struct InternalSurfaceState {
    /// Used to reconstruct a SurfaceHandle from just an *mut wlr_surface.
    handle: Weak<AtomicBool>
}

// TODO Move
pub struct Subsurface;
pub struct SubsurfaceHandle;

/// Surface state as reported by wlroots.
pub struct SurfaceState<'surface> {
    state: *mut wlr_surface_state,
    phantom: PhantomData<&'surface Surface>
}

/// A Wayland object that represents the data that we display on the screen.
///
/// Most surfaces come from Wayland clients, though they can also be created
/// by the compositor directly.
#[derive(Debug)]
pub struct Surface {
    /// The structe that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `SurfaceHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `SurfaceHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

/// See `Surface` for more information on how to use this structure.
#[derive(Clone, Debug)]
pub struct SurfaceHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// The pointer to the wlroots object that wraps a wl_surface.
    surface: *mut wlr_surface
}

impl Surface {
    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_surface {
        self.surface
    }

    pub(crate) unsafe fn from_ptr(surface: *mut wlr_surface) -> Self {
        if !(*surface).data.is_null() {
            panic!("Tried to construct a Surface from an already initialized wlr_surface");
        }
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        (*surface).data = Box::into_raw(Box::new(InternalSurfaceState { handle })) as _;
        let liveliness = Some(liveliness);
        Surface { liveliness,
                  surface }
    }

    /// Get the surface state.
    pub fn current_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            SurfaceState { state: (*self.surface).current,
                           phantom: PhantomData }
        }
    }

    /// Get the pending surface state.
    pub fn pending_state<'surface>(&'surface mut self) -> SurfaceState<'surface> {
        unsafe {
            SurfaceState { state: (*self.surface).pending,
                           phantom: PhantomData }
        }
    }

    /// Get the subsurface.
    pub fn subsurface(&self) -> Subsurface {
        Subsurface
    }

    /// Get the texture of this surface.
    pub fn texture(&self) -> Texture {
        unsafe { Texture::from_ptr((*self.surface).texture) }
    }

    /// Get the lifetime bound role (if one exists) for this surface.
    pub fn role(&self) -> Option<String> {
        unsafe { c_to_rust_string((*self.surface).role) }
    }

    /// Gets a matrix you can pass into wlr_render_with_matrix to display this
    /// surface.
    ///
    /// `matrix` is the output matrix, `projection` is the wlr_output
    /// projection matrix, and `transform` is any additional transformations you want
    /// to perform on the surface (or None/the identity matrix if you don't).
    ///
    /// `transform` is used before the surface is scaled, so its geometry extends
    /// from 0 to 1 in both dimensions.
    pub fn get_matrix<'a, T>(&mut self,
                             matrix: &mut [f32; 16],
                             projection: &[f32; 16],
                             transform: T)
        where T: Into<Option<&'a [f32; 16]>>
    {
        let transform = transform.into()
                                 .map(|transform| transform as *const _)
                                 .unwrap_or_else(|| ptr::null());
        unsafe { wlr_surface_get_matrix(self.surface, matrix, projection, transform) }
    }

    /// Whether or not this surface currently has an attached buffer.
    ///
    /// A surface has an attached buffer when it commits with a non-null buffer in its pending
    /// state.
    ///
    /// A surface will not have a buffer if it has never committed one, has
    /// committed a null buffer, or something went wrong with uploading the buffer.
    pub fn has_buffer(&self) -> bool {
        unsafe { wlr_surface_has_buffer(self.surface) }
    }

    /// Find a subsurface within this surface at the surface-local coordinates.
    ///
    /// Returns the surface and coordinates in the topmost surface coordinate system
    /// or None if no subsurface is found at that location.
    pub fn subsurface_at(&mut self,
                         sx: f32,
                         sy: f32,
                         sub_x: &mut f32,
                         sub_y: &mut f32)
                         -> Option<SubsurfaceHandle> {
        None
    }

    /// Get the top of the subsurface tree for this surface.
    pub fn get_main_surface(&self) -> Option<SurfaceHandle> {
        unsafe {
            let surface = wlr_surface_get_main_surface(self.surface);
            if surface.is_null() {
                None
            } else {
                Some(SurfaceHandle::from_ptr(surface))
            }
        }
    }

    pub fn send_enter(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_enter(self.surface, output.as_ptr()) }
    }

    pub fn send_leave(&mut self, output: &mut Output) {
        unsafe { wlr_surface_send_leave(self.surface, output.as_ptr()) }
    }

    /// Send the frame done event.
    pub fn send_frame_done(&mut self, duration: Duration) {
        unsafe {
            // FIXME
            // This is converting from a u64 -> i64
            // Something bad could happen!
            let when = timespec { tv_sec: duration.as_secs() as i64,
                                  tv_nsec: duration.subsec_nanos() as i64 };
            wlr_surface_send_frame_done(self.surface, &when);
        }
    }

    /// Get the matrix used to convert the internal byte buffer to use in the
    /// surface.
    pub fn buffer_to_surface_matrix(&self) -> [f32; 16] {
        unsafe { (*self.surface).buffer_to_surface_matrix }
    }

    /// Get the matrix used to convert the surface back to the internal byte
    /// buffer.
    pub fn surface_to_buffer_matrix(&self) -> [f32; 16] {
        unsafe { (*self.surface).surface_to_buffer_matrix }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Surface")
            .store(val, Ordering::Release);
    }

    unsafe fn from_handle(handle: &SurfaceHandle) -> Self {
        Surface { liveliness: None,
                  surface: handle.surface }
    }
}

impl SurfaceHandle {
    /// Creates an SurfaceHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(surface: *mut wlr_surface) -> Self {
        let data = (*surface).data as *mut InternalSurfaceState;
        let handle = (*data).handle.clone();
        SurfaceHandle { handle, surface }
    }

    /// Upgrades the surface handle to a reference to the backing `Surface`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Surface`
    /// which may live forever..
    /// But no surface lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Surface> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(Surface::from_handle(self))
            })
    }

    /// Run a function on the referenced Surface, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the surface
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Surface does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Surface`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Surface) -> R
    {
        let mut surface = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut surface)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running surface callback, mutable lock \
                                                    was false for: {:?}",
                                                   surface);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }
}

impl<'surface> SurfaceState<'surface> {
    pub fn width(&self) -> libc::c_int {
        unsafe { (*self.state).width }
    }

    pub fn height(&self) -> libc::c_int {
        unsafe { (*self.state).height }
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use super::context::Context;
use super::vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use super::buffer::{Buffer, BufferBinding, ArrayBufferBinding};

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    pub buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind(&self, gl: &super::Context) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl);
                Ok(())
            },
            None => { Err(()) }
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;
            let gl : &mut _ = $gl;

            {
                vbo.bind(gl).unwrap();
            }

            let gl_buffer = bind_array_buffer!(gl, &mut vbo.buffer);
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}
<commit_msg>Replace pub `VertexBuffer.buffer` with getter methods<commit_after>use std::marker::PhantomData;
use super::context::Context;
use super::vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use super::buffer::{Buffer, BufferBinding, ArrayBufferBinding};

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind(&self, gl: &super::Context) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;
            let gl : &mut _ = $gl;

            {
                vbo.bind(gl).unwrap();
            }

            let gl_buffer = bind_array_buffer!(gl, vbo.buffer_mut());
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}
<|endoftext|>


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

//! Provides helper functionality.

use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, io};

use glob;

use libc::c_int;

use super::CXVersion;

//================================================
// Macros
//================================================

macro_rules! try_opt {
    ($option:expr) => {{
        match $option {
            Some(some) => some,
            None => return None,
        }
    }};
}

//================================================
// Structs
//================================================

/// A `clang` executable.
#[derive(Clone, Debug)]
pub struct Clang {
    /// The path to this `clang` executable.
    pub path: PathBuf,
    /// The version of this `clang` executable if it could be parsed.
    pub version: Option<CXVersion>,
    /// The directories searched by this `clang` executable for C headers if
    /// they could be parsed.
    pub c_search_paths: Option<Vec<PathBuf>>,
    /// The directories searched by this `clang` executable for C++ headers if
    /// they could be parsed.
    pub cpp_search_paths: Option<Vec<PathBuf>>,
}

impl Clang {
    fn new(path: impl AsRef<Path>, args: &[String]) -> Self {
        Self {
            path: path.as_ref().into(),
            version: parse_version(path.as_ref()),
            c_search_paths: parse_search_paths(path.as_ref(), "c", args),
            cpp_search_paths: parse_search_paths(path.as_ref(), "c++", args),
        }
    }

    /// Returns a `clang` executable if one can be found.
    ///
    /// If the `CLANG_PATH` environment variable is set, that is the instance of
    /// `clang` used. Otherwise, a series of directories are searched. First, if
    /// a path is supplied, that is the first directory searched. Then, the
    /// directory returned by `llvm-config --bindir` is searched. On macOS
    /// systems, `xcodebuild -find clang` will next be queried. Last, the
    /// directories in the system's `PATH` are searched.
    ///
    /// ## Cross-compilation
    ///
    /// If target arguments are provided (e.g., `-target` followed by a target
    /// like `x86_64-unknown-linux-gnu`) then this method will prefer a
    /// target-prefixed instance of `clang` (e.g.,
    /// `x86_64-unknown-linux-gnu-clang` for the above example).
    pub fn find(path: Option<&Path>, args: &[String]) -> Option<Clang> {
        if let Ok(path) = env::var("CLANG_PATH") {
            return Some(Clang::new(path, args));
        }

        // Determine the cross-compilation target, if any.

        let mut target = None;
        for i in 0..args.len() {
            if args[i] == "-target" && i + 1 < args.len() {
                target = Some(&args[i + 1]);
            }
        }

        // Collect the paths to search for a `clang` executable in.

        let mut paths = vec![];

        if let Some(path) = path {
            paths.push(path.into());
        }

        if let Ok(path) = run_llvm_config(&["--bindir"]) {
            if let Some(line) = path.lines().next() {
                paths.push(line.into());
            }
        }

        if cfg!(target_os = "macos") {
            if let Ok((path, _)) = run("xcodebuild", &["-find", "clang"]) {
                if let Some(line) = path.lines().next() {
                    paths.push(line.into());
                }
            }
        }

        paths.extend(env::split_paths(&env::var("PATH").unwrap()));

        // First, look for a target-prefixed `clang` executable.

        if let Some(target) = target {
            let default = format!("{}-clang{}", target, env::consts::EXE_SUFFIX);
            let versioned = format!("{}-clang-[0-9]*{}", target, env::consts::EXE_SUFFIX);
            let patterns = &[&default[..], &versioned[..]];
            for path in &paths {
                if let Some(path) = find(&path, patterns) {
                    return Some(Clang::new(path, args));
                }
            }
        }

        // Otherwise, look for any other `clang` executable.

        let default = format!("clang{}", env::consts::EXE_SUFFIX);
        let versioned = format!("clang-[0-9]*{}", env::consts::EXE_SUFFIX);
        let patterns = &[&default[..], &versioned[..]];
        for path in paths {
            if let Some(path) = find(&path, patterns) {
                return Some(Clang::new(path, args));
            }
        }

        None
    }
}

//================================================
// Functions
//================================================

/// Returns the first match to the supplied glob patterns in the supplied
/// directory if there are any matches.
fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> {
    for pattern in patterns {
        let pattern = directory.join(pattern).to_string_lossy().into_owned();
        if let Some(path) = try_opt!(glob::glob(&pattern).ok())
            .filter_map(|p| p.ok())
            .next()
        {
            if path.is_file() && is_executable(&path).unwrap_or(false) {
                return Some(path);
            }
        }
    }

    None
}

#[cfg(unix)]
fn is_executable(path: &Path) -> io::Result<bool> {
    use std::ffi::CString;
    use std::os::unix::ffi::OsStrExt;

    let path = CString::new(path.as_os_str().as_bytes())?;
    unsafe { Ok(libc::access(path.as_ptr(), libc::X_OK) == 0) }
}

#[cfg(not(unix))]
fn is_executable(_: &Path) -> io::Result<bool> {
    Ok(true)
}

/// Attempts to run an executable, returning the `stdout` and `stderr` output if
/// successful.
fn run(executable: &str, arguments: &[&str]) -> Result<(String, String), String> {
    Command::new(executable)
        .args(arguments)
        .output()
        .map(|o| {
            let stdout = String::from_utf8_lossy(&o.stdout).into_owned();
            let stderr = String::from_utf8_lossy(&o.stderr).into_owned();
            (stdout, stderr)
        })
        .map_err(|e| format!("could not run executable `{}`: {}", executable, e))
}

/// Runs `clang`, returning the `stdout` and `stderr` output.
fn run_clang(path: &Path, arguments: &[&str]) -> (String, String) {
    run(&path.to_string_lossy().into_owned(), arguments).unwrap()
}

/// Runs `llvm-config`, returning the `stdout` output if successful.
fn run_llvm_config(arguments: &[&str]) -> Result<String, String> {
    let config = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".to_string());
    run(&config, arguments).map(|(o, _)| o)
}

/// Parses a version number if possible, ignoring trailing non-digit characters.
fn parse_version_number(number: &str) -> Option<c_int> {
    number
        .chars()
        .take_while(|c| c.is_digit(10))
        .collect::<String>()
        .parse()
        .ok()
}

/// Parses the version from the output of a `clang` executable if possible.
fn parse_version(path: &Path) -> Option<CXVersion> {
    let output = run_clang(path, &["--version"]).0;
    let start = try_opt!(output.find("version ")) + 8;
    let mut numbers = try_opt!(output[start..].split_whitespace().next()).split('.');
    let major = try_opt!(numbers.next().and_then(parse_version_number));
    let minor = try_opt!(numbers.next().and_then(parse_version_number));
    let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
    Some(CXVersion {
        Major: major,
        Minor: minor,
        Subminor: subminor,
    })
}

/// Parses the search paths from the output of a `clang` executable if possible.
fn parse_search_paths(path: &Path, language: &str, args: &[String]) -> Option<Vec<PathBuf>> {
    let mut clang_args = vec!["-E", "-x", language, "-", "-v"];
    clang_args.extend(args.iter().map(|s| &**s));
    let output = run_clang(path, &clang_args).1;
    let start = try_opt!(output.find("#include <...> search starts here:")) + 34;
    let end = try_opt!(output.find("End of search list."));
    let paths = output[start..end].replace("(framework directory)", "");
    Some(
        paths
            .lines()
            .filter(|l| !l.is_empty())
            .map(|l| Path::new(l.trim()).into())
            .collect(),
    )
}
<commit_msg>PATH env var might not be set<commit_after>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Provides helper functionality.

use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, io};

use glob;

use libc::c_int;

use super::CXVersion;

//================================================
// Macros
//================================================

macro_rules! try_opt {
    ($option:expr) => {{
        match $option {
            Some(some) => some,
            None => return None,
        }
    }};
}

//================================================
// Structs
//================================================

/// A `clang` executable.
#[derive(Clone, Debug)]
pub struct Clang {
    /// The path to this `clang` executable.
    pub path: PathBuf,
    /// The version of this `clang` executable if it could be parsed.
    pub version: Option<CXVersion>,
    /// The directories searched by this `clang` executable for C headers if
    /// they could be parsed.
    pub c_search_paths: Option<Vec<PathBuf>>,
    /// The directories searched by this `clang` executable for C++ headers if
    /// they could be parsed.
    pub cpp_search_paths: Option<Vec<PathBuf>>,
}

impl Clang {
    fn new(path: impl AsRef<Path>, args: &[String]) -> Self {
        Self {
            path: path.as_ref().into(),
            version: parse_version(path.as_ref()),
            c_search_paths: parse_search_paths(path.as_ref(), "c", args),
            cpp_search_paths: parse_search_paths(path.as_ref(), "c++", args),
        }
    }

    /// Returns a `clang` executable if one can be found.
    ///
    /// If the `CLANG_PATH` environment variable is set, that is the instance of
    /// `clang` used. Otherwise, a series of directories are searched. First, if
    /// a path is supplied, that is the first directory searched. Then, the
    /// directory returned by `llvm-config --bindir` is searched. On macOS
    /// systems, `xcodebuild -find clang` will next be queried. Last, the
    /// directories in the system's `PATH` are searched.
    ///
    /// ## Cross-compilation
    ///
    /// If target arguments are provided (e.g., `-target` followed by a target
    /// like `x86_64-unknown-linux-gnu`) then this method will prefer a
    /// target-prefixed instance of `clang` (e.g.,
    /// `x86_64-unknown-linux-gnu-clang` for the above example).
    pub fn find(path: Option<&Path>, args: &[String]) -> Option<Clang> {
        if let Ok(path) = env::var("CLANG_PATH") {
            return Some(Clang::new(path, args));
        }

        // Determine the cross-compilation target, if any.

        let mut target = None;
        for i in 0..args.len() {
            if args[i] == "-target" && i + 1 < args.len() {
                target = Some(&args[i + 1]);
            }
        }

        // Collect the paths to search for a `clang` executable in.

        let mut paths = vec![];

        if let Some(path) = path {
            paths.push(path.into());
        }

        if let Ok(path) = run_llvm_config(&["--bindir"]) {
            if let Some(line) = path.lines().next() {
                paths.push(line.into());
            }
        }

        if cfg!(target_os = "macos") {
            if let Ok((path, _)) = run("xcodebuild", &["-find", "clang"]) {
                if let Some(line) = path.lines().next() {
                    paths.push(line.into());
                }
            }
        }

        if let Ok(path) = env::var("PATH") {
            paths.extend(env::split_paths(&path));
        }

        // First, look for a target-prefixed `clang` executable.

        if let Some(target) = target {
            let default = format!("{}-clang{}", target, env::consts::EXE_SUFFIX);
            let versioned = format!("{}-clang-[0-9]*{}", target, env::consts::EXE_SUFFIX);
            let patterns = &[&default[..], &versioned[..]];
            for path in &paths {
                if let Some(path) = find(&path, patterns) {
                    return Some(Clang::new(path, args));
                }
            }
        }

        // Otherwise, look for any other `clang` executable.

        let default = format!("clang{}", env::consts::EXE_SUFFIX);
        let versioned = format!("clang-[0-9]*{}", env::consts::EXE_SUFFIX);
        let patterns = &[&default[..], &versioned[..]];
        for path in paths {
            if let Some(path) = find(&path, patterns) {
                return Some(Clang::new(path, args));
            }
        }

        None
    }
}

//================================================
// Functions
//================================================

/// Returns the first match to the supplied glob patterns in the supplied
/// directory if there are any matches.
fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> {
    for pattern in patterns {
        let pattern = directory.join(pattern).to_string_lossy().into_owned();
        if let Some(path) = try_opt!(glob::glob(&pattern).ok())
            .filter_map(|p| p.ok())
            .next()
        {
            if path.is_file() && is_executable(&path).unwrap_or(false) {
                return Some(path);
            }
        }
    }

    None
}

#[cfg(unix)]
fn is_executable(path: &Path) -> io::Result<bool> {
    use std::ffi::CString;
    use std::os::unix::ffi::OsStrExt;

    let path = CString::new(path.as_os_str().as_bytes())?;
    unsafe { Ok(libc::access(path.as_ptr(), libc::X_OK) == 0) }
}

#[cfg(not(unix))]
fn is_executable(_: &Path) -> io::Result<bool> {
    Ok(true)
}

/// Attempts to run an executable, returning the `stdout` and `stderr` output if
/// successful.
fn run(executable: &str, arguments: &[&str]) -> Result<(String, String), String> {
    Command::new(executable)
        .args(arguments)
        .output()
        .map(|o| {
            let stdout = String::from_utf8_lossy(&o.stdout).into_owned();
            let stderr = String::from_utf8_lossy(&o.stderr).into_owned();
            (stdout, stderr)
        })
        .map_err(|e| format!("could not run executable `{}`: {}", executable, e))
}

/// Runs `clang`, returning the `stdout` and `stderr` output.
fn run_clang(path: &Path, arguments: &[&str]) -> (String, String) {
    run(&path.to_string_lossy().into_owned(), arguments).unwrap()
}

/// Runs `llvm-config`, returning the `stdout` output if successful.
fn run_llvm_config(arguments: &[&str]) -> Result<String, String> {
    let config = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".to_string());
    run(&config, arguments).map(|(o, _)| o)
}

/// Parses a version number if possible, ignoring trailing non-digit characters.
fn parse_version_number(number: &str) -> Option<c_int> {
    number
        .chars()
        .take_while(|c| c.is_digit(10))
        .collect::<String>()
        .parse()
        .ok()
}

/// Parses the version from the output of a `clang` executable if possible.
fn parse_version(path: &Path) -> Option<CXVersion> {
    let output = run_clang(path, &["--version"]).0;
    let start = try_opt!(output.find("version ")) + 8;
    let mut numbers = try_opt!(output[start..].split_whitespace().next()).split('.');
    let major = try_opt!(numbers.next().and_then(parse_version_number));
    let minor = try_opt!(numbers.next().and_then(parse_version_number));
    let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
    Some(CXVersion {
        Major: major,
        Minor: minor,
        Subminor: subminor,
    })
}

/// Parses the search paths from the output of a `clang` executable if possible.
fn parse_search_paths(path: &Path, language: &str, args: &[String]) -> Option<Vec<PathBuf>> {
    let mut clang_args = vec!["-E", "-x", language, "-", "-v"];
    clang_args.extend(args.iter().map(|s| &**s));
    let output = run_clang(path, &clang_args).1;
    let start = try_opt!(output.find("#include <...> search starts here:")) + 34;
    let end = try_opt!(output.find("End of search list."));
    let paths = output[start..end].replace("(framework directory)", "");
    Some(
        paths
            .lines()
            .filter(|l| !l.is_empty())
            .map(|l| Path::new(l.trim()).into())
            .collect(),
    )
}
<|endoftext|>


<commit_before>mod epoll;
mod awakener;
pub mod io;

pub use self::epoll::{Epoll, Events};
pub use self::awakener::Awakener;

trait IsMinusOne {
    fn is_minus_one(&self) -> bool;
}

impl IsMinusOne for i32 {
    fn is_minus_one(&self) -> bool { *self == -1 }
}
impl IsMinusOne for isize {
    fn is_minus_one(&self) -> bool { *self == -1 }
}

fn cvt<T: IsMinusOne>(t: T) -> ::std::io::Result<T> {
    use std::io;

    if t.is_minus_one() {
        Err(io::Error::last_os_error())
    } else {
        Ok(t)
    }
}<commit_msg>add end line<commit_after>mod epoll;
mod awakener;
pub mod io;

pub use self::epoll::{Epoll, Events};
pub use self::awakener::Awakener;

trait IsMinusOne {
    fn is_minus_one(&self) -> bool;
}

impl IsMinusOne for i32 {
    fn is_minus_one(&self) -> bool { *self == -1 }
}
impl IsMinusOne for isize {
    fn is_minus_one(&self) -> bool { *self == -1 }
}

fn cvt<T: IsMinusOne>(t: T) -> ::std::io::Result<T> {
    use std::io;

    if t.is_minus_one() {
        Err(io::Error::last_os_error())
    } else {
        Ok(t)
    }
}
<|endoftext|>