<commit_before>use actix_web::client::ClientResponse;
use failure::{format_err, Error};
use serde_json::value::Value;
use serde_json::Map;
use docker_wrapper::*;
#[macro_use]
extern crate slog;
#[macro_use]
extern crate slog_scope;

pub struct ElasticSearchWrapper<'a> {
    docker_wrapper: &'a DockerWrapper,
    pub rubber: mimir::rubber::Rubber,
}

impl<'a> ElasticSearchWrapper<'a> {
    pub fn host(&self) -> String {
        self.docker_wrapper.host()
    }

    pub fn init(&mut self) {
        self.rubber.delete_index(&"_all".to_string()).unwrap();
    }

    //    A way to watch if indexes are built might be curl http://localhost:9200/_stats
    //    then _all/total/segments/index_writer_memory_in_bytes( or version_map_memory_in_bytes)
    //    should be == 0 if indexes are ok (no refresh needed)
    pub fn refresh(&self) {
        info!("Refreshing ES indexes");

        let res = reqwest::Client::new()
            .get(&format!("{}/_refresh", self.host()))
            .send()
            .unwrap();
        assert!(
            res.status() == reqwest::StatusCode::OK,
            "Error ES refresh: {:?}",
            res
        );
    }

    pub fn new(docker_wrapper: &DockerWrapper) -> ElasticSearchWrapper<'_> {
        let mut es_wrapper = ElasticSearchWrapper {
            docker_wrapper: docker_wrapper,
            rubber: mimir::rubber::Rubber::new(&docker_wrapper.host()),
        };
        es_wrapper.init();
        es_wrapper
    }

    /// simple search on an index
    /// assert that the result is OK and transform it to a json Value
    pub fn search(&self, word: &str) -> serde_json::Value {
        let mut res = self
            .rubber
            .get(&format!("munin/_search?q={}", word))
            .unwrap();
        assert!(res.status() == reqwest::StatusCode::OK);
        res.json().unwrap()
    }

    pub fn search_on_global_stop_index(&self, word: &str) -> serde_json::Value {
        let mut res = self
            .rubber
            .get(&format!("munin_global_stops/_search?q={}", word))
            .unwrap();
        assert!(res.status() == reqwest::StatusCode::OK);
        res.json().unwrap()
    }

    pub fn search_and_filter<'b, F>(
        &self,
        word: &str,
        predicate: F,
    ) -> impl Iterator<Item = mimir::Place> + 'b
    where
        F: 'b + FnMut(&mimir::Place) -> bool,
    {
        self.search_and_filter_on_index(word, predicate, false)
    }

    pub fn search_and_filter_on_global_stop_index<'b, F>(
        &self,
        word: &str,
        predicate: F,
    ) -> impl Iterator<Item = mimir::Place> + 'b
    where
        F: 'b + FnMut(&mimir::Place) -> bool,
    {
        self.search_and_filter_on_index(word, predicate, true)
    }

    fn search_and_filter_on_index<'b, F>(
        &self,
        word: &str,
        predicate: F,
        search_on_global_stops: bool,
    ) -> impl Iterator<Item = mimir::Place> + 'b
    where
        F: 'b + FnMut(&mimir::Place) -> bool,
    {
        use serde_json::map::Entry;

        fn into_object(json: Value) -> Option<Map<String, Value>> {
            match json {
                Value::Object(o) => Some(o),
                _ => None,
            }
        }
        fn get(json: Value, key: &str) -> Option<Value> {
            into_object(json).and_then(|mut json| match json.entry(key.to_string()) {
                Entry::Occupied(o) => Some(o.remove()),
                _ => None,
            })
        }
        let json = if search_on_global_stops {
            self.search_on_global_stop_index(word)
        } else {
            self.search(word)
        };
        get(json, "hits")
            .and_then(|json| get(json, "hits"))
            .and_then(|hits| match hits {
                Value::Array(v) => Some(v),
                _ => None,
            })
            .unwrap_or_else(Vec::default)
            .into_iter()
            .filter_map(|json| {
                into_object(json).and_then(|obj| {
                    let doc_type = obj
                        .get("_type")
                        .and_then(|doc_type| doc_type.as_str())
                        .map(|doc_type| doc_type.into());

                    doc_type.and_then(|doc_type| {
                        // The real object is contained in the _source section.
                        obj.get("_source").and_then(|src| {
                            bragi::query::make_place(doc_type, Some(Box::new(src.clone())))
                        })
                    })
                })
            })
            .filter(predicate)
    }
}

pub struct BragiHandler {
    app: actix_web::test::TestServer,
}

impl BragiHandler {
    pub fn new(url: String) -> BragiHandler {
        let make_server = move || {
            bragi::server::create_server(bragi::Context::from(&bragi::Args {
                connection_string: url.clone(),
                ..Default::default()
            }))
        };

        BragiHandler {
            app: actix_web::test::TestServer::with_factory(make_server),
        }
    }

    pub fn raw_get(&mut self, q: &str) -> Result<ClientResponse, Error> {
        self.app
            .execute(
                self.app
                    .client(actix_web::http::Method::GET, q)
                    .finish()
                    .map_err(|e| format_err!("invalid query: {}", e))?
                    .send(),
            )
            .map_err(|e| format_err!("impossible to query bragi: {}", e))
    }

    pub fn get(&mut self, q: &str) -> Vec<Map<String, Value>> {
        let r = self.raw_get(q).unwrap();
        assert!(r.status().is_success(), "invalid status: {}", r.status());
        self.get_results(r, Some("/properties/geocoding".to_string()))
    }

    pub fn get_json(&mut self, q: &str) -> Value {
        let r = self.raw_get(q).unwrap();
        assert!(r.status().is_success(), "invalid status: {}", r.status());
        self.to_json(r)
    }

    pub fn get_unchecked_json(&mut self, q: &str) -> (actix_web::http::StatusCode, Value) {
        let r = self.raw_get(q).unwrap();
        (r.status(), self.to_json(r))
    }

    pub fn raw_post_shape(
        &mut self,
        q: &str,
        shape: &'static str,
    ) -> Result<ClientResponse, Error> {
        self.app
            .execute(
                self.app
                    .client(actix_web::http::Method::POST, q)
                    .header(actix_web::http::header::CONTENT_TYPE, "application/json")
                    .body(shape)
                    .map_err(|e| format_err!("invalid query: {}", e))?
                    .send(),
            )
            .map_err(|e| format_err!("impossible to query bragi: {}", e))
    }

    pub fn post_shape(&mut self, q: &str, shape: &'static str) -> Vec<Map<String, Value>> {
        let r = self.raw_post_shape(q, shape).unwrap();
        self.get_results(r, Some("/properties/geocoding".to_string()))
    }

    pub fn to_json(&mut self, r: ClientResponse) -> Value {
        use actix_web::HttpMessage;
        let bytes = self.app.execute(r.body()).unwrap();
        let body = std::str::from_utf8(&bytes).unwrap();
        serde_json::from_str(body).unwrap()
    }

    pub fn get_results(
        &mut self,
        r: ClientResponse,
        pointer: Option<String>,
    ) -> Vec<Map<String, Value>> {
        self.to_json(r)
            .pointer("/features")
            .expect("wrongly formated bragi response")
            .as_array()
            .expect("features must be array")
            .iter()
            .map(|f| {
                if let Some(p) = &pointer {
                    f.pointer(&p)
                        .expect("no field in bragi response")
                        .as_object()
                        .unwrap()
                        .clone()
                } else {
                    f.as_object().unwrap().clone()
                }
            })
            .collect()
    }
}
<commit_msg>fix rebases<commit_after>use actix_web::client::ClientResponse;
use failure::{format_err, Error};
use serde_json::value::Value;
use serde_json::Map;
use docker_wrapper::*;
#[macro_use]
extern crate slog;
#[macro_use]
extern crate slog_scope;

pub struct ElasticSearchWrapper<'a> {
    pub docker_wrapper: &'a DockerWrapper,
    pub rubber: mimir::rubber::Rubber,
}

impl<'a> ElasticSearchWrapper<'a> {
    pub fn host(&self) -> String {
        self.docker_wrapper.host()
    }

    pub fn init(&mut self) {
        self.rubber.delete_index(&"_all".to_string()).unwrap();
    }

    //    A way to watch if indexes are built might be curl http://localhost:9200/_stats
    //    then _all/total/segments/index_writer_memory_in_bytes( or version_map_memory_in_bytes)
    //    should be == 0 if indexes are ok (no refresh needed)
    pub fn refresh(&self) {
        info!("Refreshing ES indexes");

        let res = reqwest::Client::new()
            .get(&format!("{}/_refresh", self.host()))
            .send()
            .unwrap();
        assert!(
            res.status() == reqwest::StatusCode::OK,
            "Error ES refresh: {:?}",
            res
        );
    }

    pub fn new(docker_wrapper: &DockerWrapper) -> ElasticSearchWrapper<'_> {
        let mut es_wrapper = ElasticSearchWrapper {
            docker_wrapper: docker_wrapper,
            rubber: mimir::rubber::Rubber::new(&docker_wrapper.host()),
        };
        es_wrapper.init();
        es_wrapper
    }

    /// simple search on an index
    /// assert that the result is OK and transform it to a json Value
    pub fn search(&self, word: &str) -> serde_json::Value {
        let mut res = self
            .rubber
            .get(&format!("munin/_search?q={}", word))
            .unwrap();
        assert!(res.status() == reqwest::StatusCode::OK);
        res.json().unwrap()
    }

    pub fn search_on_global_stop_index(&self, word: &str) -> serde_json::Value {
        let mut res = self
            .rubber
            .get(&format!("munin_global_stops/_search?q={}", word))
            .unwrap();
        assert!(res.status() == reqwest::StatusCode::OK);
        res.json().unwrap()
    }

    pub fn search_and_filter<'b, F>(
        &self,
        word: &str,
        predicate: F,
    ) -> impl Iterator<Item = mimir::Place> + 'b
    where
        F: 'b + FnMut(&mimir::Place) -> bool,
    {
        self.search_and_filter_on_index(word, predicate, false)
    }

    pub fn search_and_filter_on_global_stop_index<'b, F>(
        &self,
        word: &str,
        predicate: F,
    ) -> impl Iterator<Item = mimir::Place> + 'b
    where
        F: 'b + FnMut(&mimir::Place) -> bool,
    {
        self.search_and_filter_on_index(word, predicate, true)
    }

    fn search_and_filter_on_index<'b, F>(
        &self,
        word: &str,
        predicate: F,
        search_on_global_stops: bool,
    ) -> impl Iterator<Item = mimir::Place> + 'b
    where
        F: 'b + FnMut(&mimir::Place) -> bool,
    {
        use serde_json::map::Entry;

        fn into_object(json: Value) -> Option<Map<String, Value>> {
            match json {
                Value::Object(o) => Some(o),
                _ => None,
            }
        }
        fn get(json: Value, key: &str) -> Option<Value> {
            into_object(json).and_then(|mut json| match json.entry(key.to_string()) {
                Entry::Occupied(o) => Some(o.remove()),
                _ => None,
            })
        }
        let json = if search_on_global_stops {
            self.search_on_global_stop_index(word)
        } else {
            self.search(word)
        };
        get(json, "hits")
            .and_then(|json| get(json, "hits"))
            .and_then(|hits| match hits {
                Value::Array(v) => Some(v),
                _ => None,
            })
            .unwrap_or_else(Vec::default)
            .into_iter()
            .filter_map(|json| {
                into_object(json).and_then(|obj| {
                    let doc_type = obj
                        .get("_type")
                        .and_then(|doc_type| doc_type.as_str())
                        .map(|doc_type| doc_type.into());

                    doc_type.and_then(|doc_type| {
                        // The real object is contained in the _source section.
                        obj.get("_source").and_then(|src| {
                            bragi::query::make_place(doc_type, Some(Box::new(src.clone())))
                        })
                    })
                })
            })
            .filter(predicate)
    }
}

pub struct BragiHandler {
    pub app: actix_web::test::TestServer,
}

impl BragiHandler {
    pub fn new(url: String) -> BragiHandler {
        let make_server = move || {
            bragi::server::create_server(bragi::Context::from(&bragi::Args {
                connection_string: url.clone(),
                ..Default::default()
            }))
        };

        BragiHandler {
            app: actix_web::test::TestServer::with_factory(make_server),
        }
    }

    pub fn raw_get(&mut self, q: &str) -> Result<ClientResponse, Error> {
        self.app
            .execute(
                self.app
                    .client(actix_web::http::Method::GET, q)
                    .finish()
                    .map_err(|e| format_err!("invalid query: {}", e))?
                    .send(),
            )
            .map_err(|e| format_err!("impossible to query bragi: {}", e))
    }

    pub fn get(&mut self, q: &str) -> Vec<Map<String, Value>> {
        let r = self.raw_get(q).unwrap();
        assert!(r.status().is_success(), "invalid status: {}", r.status());
        self.get_results(r, Some("/properties/geocoding".to_string()))
    }

    pub fn get_json(&mut self, q: &str) -> Value {
        let r = self.raw_get(q).unwrap();
        assert!(r.status().is_success(), "invalid status: {}", r.status());
        self.to_json(r)
    }

    pub fn get_unchecked_json(&mut self, q: &str) -> (actix_web::http::StatusCode, Value) {
        let r = self.raw_get(q).unwrap();
        (r.status(), self.to_json(r))
    }

    pub fn raw_post_shape(
        &mut self,
        q: &str,
        shape: &'static str,
    ) -> Result<ClientResponse, Error> {
        self.app
            .execute(
                self.app
                    .client(actix_web::http::Method::POST, q)
                    .header(actix_web::http::header::CONTENT_TYPE, "application/json")
                    .body(shape)
                    .map_err(|e| format_err!("invalid query: {}", e))?
                    .send(),
            )
            .map_err(|e| format_err!("impossible to query bragi: {}", e))
    }

    pub fn post_shape(&mut self, q: &str, shape: &'static str) -> Vec<Map<String, Value>> {
        let r = self.raw_post_shape(q, shape).unwrap();
        self.get_results(r, Some("/properties/geocoding".to_string()))
    }

    pub fn to_json(&mut self, r: ClientResponse) -> Value {
        use actix_web::HttpMessage;
        let bytes = self.app.execute(r.body()).unwrap();
        let body = std::str::from_utf8(&bytes).unwrap();
        serde_json::from_str(body).unwrap()
    }

    pub fn get_results(
        &mut self,
        r: ClientResponse,
        pointer: Option<String>,
    ) -> Vec<Map<String, Value>> {
        self.to_json(r)
            .pointer("/features")
            .expect("wrongly formated bragi response")
            .as_array()
            .expect("features must be array")
            .iter()
            .map(|f| {
                if let Some(p) = &pointer {
                    f.pointer(&p)
                        .expect("no field in bragi response")
                        .as_object()
                        .unwrap()
                        .clone()
                } else {
                    f.as_object().unwrap().clone()
                }
            })
            .collect()
    }
}
<|endoftext|>


<commit_before>fn main() {
    // WHILE
    let mut x = 5; // mut x: i32
    let mut done = false; // mut done: bool

    println!("PRINT WHILE");
    while !done {
        x += x - 3;

        println!("{}", x);

        if x % 5 == 0 {
            done = true;
        }
    }

    println!("PRINT FOR");
    // FOR
    for x in 0..10 {
        println!("{}", x); // x: i32
    }
}
<commit_msg>actualizacion de loops<commit_after>fn main() {
    // WHILE
    let mut x = 5; // mut x: i32
    let mut done = false; // mut done: bool

    println!("PRINT WHILE");
    while !done {
        x += x - 3;

        println!("{}", x);

        if x % 5 == 0 {
            done = true;
        }
    }

    println!("PRINT FOR");
    // FOR
    for x in 0..10 {
        println!("{}", x); // x: i32
    }

    for (index, value) in (5..10).enumerate() {
        println!("index = {} and value = {}", index, value);
    }

}
<|endoftext|>


<commit_before>use std::fmt as StdFmt;

use comment::Comment;

#[derive(Debug, Eq, PartialEq)]
pub enum Language {
    C,
    Header,
    Hpp,
    Cpp,
    Css,
    Html,
    Java,
    JavaScript,
    Perl,
    Php,
    Python,
    Ruby,
    Rust,
    Xml,
    Toml,
    Go,
}

impl Language {
    pub fn from_ext(ext: &str) -> Option<Language> {
        match ext {
            "cpp" | "cp" | "cc" | "cxx" | "c++" | "C" => Some(Language::Cpp),
            "hpp" | "h++" => Some(Language::Hpp),
            "c" => Some(Language::C),
            "h" => Some(Language::Header),
            "css" => Some(Language::Css),
            "java" => Some(Language::Java),
            "js" => Some(Language::JavaScript),
            "rs" => Some(Language::Rust),
            "xml" => Some(Language::Xml),
            "html" | "htm" => Some(Language::Html),
            "py" => Some(Language::Python),
            "rb" => Some(Language::Ruby),
            "php" => Some(Language::Php),
            "toml" => Some(Language::Toml),
            "pl" => Some(Language::Perl),
            "go" => Some(Language::Go),
            _ => None,
        }
    }

    pub fn name(&self) -> &str {
        match *self {
            Language::Cpp => "C++",
            Language::Hpp => "C++ Header",
            Language::C => "C",
            Language::Header => "C Header",
            Language::Css => "CSS",
            Language::Java => "Java",
            Language::JavaScript => "JavaScript",
            Language::Rust => "Rust",
            Language::Xml => "XML",
            Language::Html => "HTML",
            Language::Python => "Python",
            Language::Ruby => "Ruby",
            Language::Php => "PHP",
            Language::Toml => "TOML",
            Language::Perl => "Perl",
            Language::Go => "Go",
        }
    }

    pub fn is_unsafe(&self) -> bool {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Rust => true,
            _ => false,
        }
    }

    pub fn unsafe_keyword(&self) -> Option<&str> {
        match *self {
            Language::Rust => Some("unsafe"),
            _ => None,
        }
    }
}

impl StdFmt::Display for Language {
    fn fmt(&self, f: &mut StdFmt::Formatter) -> StdFmt::Result {
        write!(f, "{}", self.name())
    }
}

impl Comment for Language {
	type Rep = &'static str;

    fn single(&self) -> Option<Vec<<Self as Comment>::Rep>> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::JavaScript |
            Language::Rust |
            Language::Go => Some(vec!["//"]),
            Language::Php => Some(vec!["//", "#"]),
            Language::Xml |
            Language::Html => Some(vec!["<!--"]),
            Language::Ruby |
            Language::Python |
            Language::Toml |
            Language::Perl => Some(vec!["#"]),

        }
    }

    fn multi_start(&self) -> Option<<Self as Comment>::Rep> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::JavaScript |
            Language::Go |
            Language::Rust |
            Language::Php => Some("/*"),
            Language::Xml |
            Language::Html => Some("<!--"),
            Language::Ruby => Some("=begin"),
            Language::Python => Some("'''"),
            Language::Toml |
            Language::Perl => None,
        }
    }

    fn multi_end(&self) -> Option<<Self as Comment>::Rep> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::Go |
            Language::JavaScript |
            Language::Rust |
            Language::Php => Some("*/"),
            Language::Xml |
            Language::Html => Some("-->"),
            Language::Ruby => Some("=end"),
            Language::Python => Some("'''"),
            Language::Toml |
            Language::Perl => None,
        }
    }
}
<commit_msg>Auto merge of #29 - nabijaczleweli:feature/languages/add-from-#4, r=kbknapp<commit_after>use std::fmt as StdFmt;

use comment::Comment;

#[derive(Debug, Eq, PartialEq)]
pub enum Language {
    C,
    Header,
    Hpp,
    Cpp,
    Css,
    Html,
    Java,
    JavaScript,
    Perl,
    Php,
    Python,
    Ruby,
    Rust,
    Xml,
    Toml,
    Go,
    Assembly,
    Shell,
    D,
    Nim,
}

impl Language {
    pub fn from_ext(ext: &str) -> Option<Language> {
        match ext {
            "cpp" | "cp" | "cc" | "cxx" | "c++" | "C" => Some(Language::Cpp),
            "hpp" | "h++" => Some(Language::Hpp),
            "c" => Some(Language::C),
            "h" => Some(Language::Header),
            "css" => Some(Language::Css),
            "java" => Some(Language::Java),
            "js" => Some(Language::JavaScript),
            "rs" => Some(Language::Rust),
            "xml" => Some(Language::Xml),
            "html" | "htm" => Some(Language::Html),
            "py" => Some(Language::Python),
            "rb" => Some(Language::Ruby),
            "php" => Some(Language::Php),
            "toml" => Some(Language::Toml),
            "pl" => Some(Language::Perl),
            "go" => Some(Language::Go),
            "agc" | "asm" | "a51" | "inc" | "nasm" | "s" | "ms" => Some(Language::Assembly),
            "ps1" | "psd1" | "psm1" | "sh" | "bash" | "bats" | "cgi" | "command" | "fcgi" |
            "ksh" | "sh.in" | "tmux" | "tool" | "zsh" | "tcsh" | "csh" | "fish" => {
                Some(Language::Shell)
            }
            "d" | "di" => Some(Language::D),
            "nim" | "nimrod" => Some(Language::Nim),
            _ => None,
        }
    }

    pub fn name(&self) -> &str {
        match *self {
            Language::Cpp => "C++",
            Language::Hpp => "C++ Header",
            Language::C => "C",
            Language::Header => "C Header",
            Language::Css => "CSS",
            Language::Java => "Java",
            Language::JavaScript => "JavaScript",
            Language::Rust => "Rust",
            Language::Xml => "XML",
            Language::Html => "HTML",
            Language::Python => "Python",
            Language::Ruby => "Ruby",
            Language::Php => "PHP",
            Language::Toml => "TOML",
            Language::Perl => "Perl",
            Language::Go => "Go",
            Language::Assembly => "Assembly",
            Language::Shell => "Shell",
            Language::D => "D",
            Language::Nim => "Nim",
        }
    }

    pub fn is_unsafe(&self) -> bool {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Rust |
            Language::Assembly |
            Language::Nim => true,
            _ => false,
        }
    }

    pub fn unsafe_keyword(&self) -> Option<&str> {
        match *self {
            Language::Rust => Some("unsafe"),
            _ => None,
        }
    }
}

impl StdFmt::Display for Language {
    fn fmt(&self, f: &mut StdFmt::Formatter) -> StdFmt::Result {
        write!(f, "{}", self.name())
    }
}

impl Comment for Language {
    type Rep = &'static str;

    fn single(&self) -> Option<Vec<<Self as Comment>::Rep>> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::JavaScript |
            Language::Rust |
            Language::Go |
            Language::D => Some(vec!["//"]),
            Language::Php => Some(vec!["//", "#"]),
            Language::Xml |
            Language::Html => Some(vec!["<!--"]),
            Language::Ruby |
            Language::Python |
            Language::Toml |
            Language::Perl |
            Language::Assembly |
            Language::Shell |
            Language::Nim => Some(vec!["#"]),
        }
    }

    fn multi_start(&self) -> Option<<Self as Comment>::Rep> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::JavaScript |
            Language::Go |
            Language::Rust |
            Language::Php |
            Language::D => Some("/*"),
            Language::Xml |
            Language::Html => Some("<!--"),
            Language::Ruby => Some("=begin"),
            Language::Python => Some("'''"),
            Language::Nim => Some("#["),
            Language::Toml |
            Language::Perl |
            Language::Assembly |
            Language::Shell => None,
        }
    }

    fn multi_end(&self) -> Option<<Self as Comment>::Rep> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::Go |
            Language::JavaScript |
            Language::Rust |
            Language::Php |
            Language::D => Some("*/"),
            Language::Xml |
            Language::Html => Some("-->"),
            Language::Ruby => Some("=end"),
            Language::Python => Some("'''"),
            Language::Nim => Some("]#"),
            Language::Toml |
            Language::Perl |
            Language::Assembly |
            Language::Shell => None,
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::path::{PathBuf, Path};
use std::fs::{read_dir, PathExt};
use std::borrow::ToOwned;
use std::iter::IteratorExt;
use std::vec::IntoIter;

pub struct FilesystemWalker {
    cur: Option<IntoIter<(u64, PathBuf)>>,
    stack: Vec<IntoIter<(u64, PathBuf)>>
}

// The idea here is that we serve the most recently changed files first
// because those are likely to be the most relevant. The current implementation
// does not guarantee this, though.
impl Iterator for FilesystemWalker {
    type Item = io::Result<(u64, PathBuf)>;

    fn next(&mut self) -> Option<io::Result<(u64, PathBuf)>> {
        loop {
            if let Some(ref mut cur) = self.cur {
                if let Some((modified, path)) = cur.next() {
                    if path.is_dir() {
                        match FilesystemWalker::read_dir_sorted(&path) {
                            Err(e) => return Some(Err(e)),
                            Ok(deeper) => self.stack.push(deeper)
                        }
                    }

                    return Some(Ok((modified, path)));
                }
            }

            self.cur = None;

            match self.stack.pop() {
                next @ Some(..) => self.cur = next,
                None => return None,
            }
        }
    }
}

impl FilesystemWalker {
    pub fn new(dir: &Path) -> io::Result<FilesystemWalker> {
        let start = try!(FilesystemWalker::read_dir_sorted(dir));

        Ok(FilesystemWalker {
            cur: Some(start),
            stack: Vec::new()
        })
    }

    fn read_dir_sorted(dir: &Path) -> io::Result<IntoIter<(u64, PathBuf)>> {
        let mut vec: Vec<(u64, PathBuf)> = try!(
            read_dir(dir)
            .and_then(|list| list
                .map(|possible_entry| {
                    possible_entry.and_then(|entry| {
                        let path = entry.path();

                        path.metadata()
                            .map(move |stats| {
                                (stats.modified(), path.to_owned())
                            })
                    })
                })
                .collect()
            )
        );

        vec.sort_by(|&(a, _), &(b, _)| a.cmp(&b).reverse());

        Ok(vec.into_iter())
    }
}

#[cfg(test)]
mod test {
    use std::old_io::Timer;
    use std::time::Duration;

    use super::super::super::tempdir::TempDir;
    use super::super::super::write_to_disk;

    #[test]
    fn read_dir() {
        let temp_dir = TempDir::new("readdir-test").unwrap();

        {
            let file_path = temp_dir.path().join("firstfile");
            write_to_disk(&file_path, b"test123").unwrap();
        }

        Timer::new().unwrap().sleep(Duration::milliseconds(50));

        {
            let file_path = temp_dir.path().join("second");
            write_to_disk(&file_path, b"hello").unwrap();
        }

        Timer::new().unwrap().sleep(Duration::milliseconds(50));

        {
            let file_path = temp_dir.path().join("third");
            write_to_disk(&file_path, b"waddaa").unwrap();
        }

        let list = super::FilesystemWalker::new(temp_dir.path()).unwrap();

        let filenames: Vec<String> = list
            .map(|x| {
                let (_, path) = x.unwrap();

                path.file_name().unwrap().to_string_lossy().into_owned()
            })
            .collect();

        assert_eq!(&["third", "second", "firstfile"], &filenames);
    }
}
<commit_msg>refactor FilesystemWalker; upgrade its test<commit_after>use std::io;
use std::path::{PathBuf, Path};
use std::fs::{read_dir, PathExt};
use std::borrow::ToOwned;
use std::iter::IteratorExt;

use super::super::iter_reduce::{Reduce, IteratorReduce};

pub struct FilesystemWalker {
    cur: Vec<(u64, PathBuf)>
}

// The idea here is that we serve the most recently changed files first
// because those are likely to be the most relevant.
impl Iterator for FilesystemWalker {
    type Item = io::Result<(u64, PathBuf)>;

    fn next(&mut self) -> Option<io::Result<(u64, PathBuf)>> {
        loop {
            match self.cur.pop() {
                Some((modified, path)) => {
                    if path.is_dir() {
                        if let Err(e) = self.read_dir_sorted(&path) {
                            return Some(Err(e));
                        }
                    }
                    else {
                        return Some(Ok((modified, path)));
                    }
                },
                None => return None
            }
        }
    }
}

impl FilesystemWalker {
    pub fn new(dir: &Path) -> io::Result<FilesystemWalker> {
        let mut walker = FilesystemWalker {
            cur: Vec::new()
        };

        try!(walker.read_dir_sorted(dir));

        Ok(walker)
    }

    fn read_dir_sorted(&mut self, dir: &Path) -> io::Result<()> {
        try!(
            read_dir(dir)
            .and_then(|list| list
                .map(|possible_entry| {
                    possible_entry.and_then(|entry| {
                        let path = entry.path();

                        path.metadata()
                            .map(|stats| {
                                let pair = (stats.modified(), path.to_owned());
                                self.cur.push(pair);
                            })
                    })
                })
                .reduce()
            )
        );

        self.cur.sort_by(|&(a, _), &(b, _)| a.cmp(&b));

        Ok(())
    }
}

#[cfg(test)]
mod test {
    use std::old_io::Timer;
    use std::time::Duration;
    use std::fs::create_dir_all;

    use super::super::super::tempdir::TempDir;
    use super::super::super::write_to_disk;

    #[test]
    fn read_dir() {
        let temp_dir = TempDir::new("readdir-test").unwrap();
        let root_path = temp_dir.path();
        let sub_dir = root_path.join("sub");

        create_dir_all(&sub_dir).unwrap();

        {
            let file_path = root_path.join("filezero");
            write_to_disk(&file_path, b"test123").unwrap();
        }

        Timer::new().unwrap().sleep(Duration::milliseconds(50));

        {
            let file_path = sub_dir.join("firstfile");
            write_to_disk(&file_path, b"yolo").unwrap();
        }

        Timer::new().unwrap().sleep(Duration::milliseconds(50));

        {
            let file_path = root_path.join("second");
            write_to_disk(&file_path, b"hello").unwrap();
        }

        Timer::new().unwrap().sleep(Duration::milliseconds(50));

        {
            let file_path = root_path.join("third");
            write_to_disk(&file_path, b"waddaa").unwrap();
        }

        Timer::new().unwrap().sleep(Duration::milliseconds(50));

        {
            let file_path = sub_dir.join("deadlast");
            write_to_disk(&file_path, b"plswork").unwrap();
        }

        let list = super::FilesystemWalker::new(temp_dir.path()).unwrap();

        let filenames: Vec<String> = list
            .map(|x| {
                let (_, path) = x.unwrap();

                path.file_name().unwrap().to_string_lossy().into_owned()
            })
            .collect();

        assert_eq!(&["deadlast", "third", "second", "firstfile", "filezero"], &filenames);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

/*
Goals:
- コンパイルできるように、Point構造体にaddを実装してください
- コメントアウトされている[1], [2]を戻し、コンパイルできないことを確認してください
- 適切なライフタイムパラメータを追加して、コンパイルできるようにしてください
- コメントアウトされている[3], [4]を戻し、コンパイルエラーが発生することを確認してください
*/

fn main() {
    points();
    /* [1]
    area1();
    */
    /* [3]
    area2();
    */
}

fn points() {
    let from = Point::new(10.0, 10.0);
    let diff = Point::new(5.0, 10.0);
    let to = from.add(&diff);
    println!("({}, {})を({}, {})動かした場所は({}, {})です",
             from.x,
             from.y,
             diff.x,
             diff.y,
             to.x,
             to.y);
}

/* [2]
fn area1() {
    let top = Point::new(10.0, 10.0);
    let diff = Point::new(5.0, 10.0);
    let bottom = top.add(&diff);
    let rect = Rect::new(&top, &bottom);
    println!("area = {}", rect.area());
}
*/

/* [4]
fn area2() {
    let top = Point::new(10.0, 10.0);
    let rect;
    {
        let diff = Point::new(5.0, 10.0);
        let bottom = top.add(&diff);
        rect = Rect::new(&top, &bottom);
    }
    println!("area = {}", rect.area());
}
*/
struct Point {
    x: f32,
    y: f32,
}
impl Point {
    fn new(x: f32, y: f32) -> Point {
        Point { x: x, y: y }
    }
    fn add(&self, diff: &Point) -> Point {
        Point {
            x: self.x + diff.x,
            y: self.y + diff.y,
        }
    }
}

/* [2]
struct Rect {
    top_left: &'a Point,
    bottom_right: &'b Point,
}

impl Rect {
    fn new(top_left: &'a Point, bottom_right: &'b Point) -> Rect {
        Rect {
            top_left: top_left,
            bottom_right: bottom_right,
        }
    }
    fn area(&self) -> f32 {
        let dx = (self.top_left.x - self.bottom_right.x).abs();
        let dy = (self.top_left.y - self.bottom_right.y).abs();
        dx * dy
    }
}
*/<commit_msg>refactored<commit_after>#![allow(dead_code)]

/*
Goals:
- コンパイルできるように、Point構造体にaddを実装してください
- コメントアウトされている[1], [2]を戻し、コンパイルできないことを確認してください
- 適切なライフタイムパラメータを追加して、コンパイルできるようにしてください
- コメントアウトされている[3], [4]を戻し、コンパイルエラーが発生することを確認してください
*/

fn main() {
    points();
    /* [1]
    area1();
    */
    /* [3]
    area2();
    */
}

fn points() {
    let from = Point::new(10.0, 10.0);
    let diff = Point::new(5.0, 10.0);
    let to = from.add(&diff);
    println!("({}, {})を({}, {})動かした場所は({}, {})です",
             from.x,
             from.y,
             diff.x,
             diff.y,
             to.x,
             to.y);
}

/* [2]
fn area1() {
    let top = Point::new(10.0, 10.0);
    let diff = Point::new(5.0, 10.0);
    let bottom = top.add(&diff);
    let rect = Rect::new(&top, &bottom);
    println!("area = {}", rect.area());
}
*/

/* [4]
fn area2() {
    let top = Point::new(10.0, 10.0);
    let rect;
    {
        let diff = Point::new(5.0, 10.0);
        let bottom = top.add(&diff);
        rect = Rect::new(&top, &bottom);
    }
    println!("area = {}", rect.area());
}
*/
struct Point {
    x: f32,
    y: f32,
}
impl Point {
    fn new(x: f32, y: f32) -> Point {
        Point { x: x, y: y }
    }
    fn add(&self, offset: &Point) -> Point {
        Point {
            x: self.x + offset.x,
            y: self.y + offset.y,
        }
    }
}

/* [2]
struct Rect {
    top_left: &'a Point,
    bottom_right: &'b Point,
}

impl Rect {
    fn new(top_left: &'a Point, bottom_right: &'b Point) -> Rect {
        Rect {
            top_left: top_left,
            bottom_right: bottom_right,
        }
    }
    fn area(&self) -> f32 {
        let dx = (self.top_left.x - self.bottom_right.x).abs();
        let dy = (self.top_left.y - self.bottom_right.y).abs();
        dx * dy
    }
}
*/<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A cache that holds a limited number of key-value pairs. When the
//! capacity of the cache is exceeded, the least-recently-used
//! (where "used" means a look-up or putting the pair into the cache)
//! pair is automatically removed.
//!
//! # Example
//!
//! ```rust
//! use collections::LruCache;
//!
//! let mut cache: LruCache<int, int> = LruCache::new(2);
//! cache.put(1, 10);
//! cache.put(2, 20);
//! cache.put(3, 30);
//! assert!(cache.get(&1).is_none());
//! assert_eq!(*cache.get(&2).unwrap(), 20);
//! assert_eq!(*cache.get(&3).unwrap(), 30);
//!
//! cache.put(2, 22);
//! assert_eq!(*cache.get(&2).unwrap(), 22);
//!
//! cache.put(6, 60);
//! assert!(cache.get(&3).is_none());
//!
//! cache.change_capacity(1);
//! assert!(cache.get(&2).is_none());
//! ```

use std::cast;
use std::container::Container;
use std::hash::Hash;
use std::fmt;
use std::ptr;

use HashMap;

struct KeyRef<K> { k: *K }

struct LruEntry<K, V> {
    key: Option<K>,
    value: Option<V>,
    next: *mut LruEntry<K, V>,
    prev: *mut LruEntry<K, V>,
}

/// An LRU Cache.
pub struct LruCache<K, V> {
    map: HashMap<KeyRef<K>, ~LruEntry<K, V>>,
    max_size: uint,
    head: *mut LruEntry<K, V>,
    tail: *mut LruEntry<K, V>,
}

impl<S, K: Hash<S>> Hash<S> for KeyRef<K> {
    fn hash(&self, state: &mut S) {
        unsafe { (*self.k).hash(state) }
    }
}

impl<K: Eq> Eq for KeyRef<K> {
    fn eq(&self, other: &KeyRef<K>) -> bool {
        unsafe{ (*self.k).eq(&*other.k) }
    }
}

impl<K: TotalEq> TotalEq for KeyRef<K> {}

impl<K, V> LruEntry<K, V> {
    fn new() -> LruEntry<K, V> {
        LruEntry {
            key: None,
            value: None,
            next: ptr::mut_null(),
            prev: ptr::mut_null(),
        }
    }

    fn with_key_value(k: K, v: V) -> LruEntry<K, V> {
        LruEntry {
            key: Some(k),
            value: Some(v),
            next: ptr::mut_null(),
            prev: ptr::mut_null(),
        }
    }
}

impl<K: Hash + TotalEq, V> LruCache<K, V> {
    /// Create an LRU Cache that holds at most `capacity` items.
    pub fn new(capacity: uint) -> LruCache<K, V> {
        let cache = LruCache {
            map: HashMap::new(),
            max_size: capacity,
            head: unsafe{ cast::transmute(~LruEntry::<K, V>::new()) },
            tail: unsafe{ cast::transmute(~LruEntry::<K, V>::new()) },
        };
        unsafe {
            (*cache.head).next = cache.tail;
            (*cache.tail).prev = cache.head;
        }
        return cache;
    }

    /// Put a key-value pair into cache.
    pub fn put(&mut self, k: K, v: V) {
        let (node_ptr, node_opt) = match self.map.find_mut(&KeyRef{k: &k}) {
            Some(node) => {
                node.value = Some(v);
                let node_ptr: *mut LruEntry<K, V> = &mut **node;
                (node_ptr, None)
            }
            None => {
                let mut node = ~LruEntry::with_key_value(k, v);
                let node_ptr: *mut LruEntry<K, V> = &mut *node;
                (node_ptr, Some(node))
            }
        };
        match node_opt {
            None => {
                self.detach(node_ptr);
                self.attach(node_ptr);
            }
            Some(node) => {
                let keyref = unsafe { (*node_ptr).key.as_ref().unwrap() };
                self.map.swap(KeyRef{k: keyref}, node);
                self.attach(node_ptr);
                if self.len() > self.capacity() {
                    self.remove_lru();
                }
            }
        }
    }

    /// Return a value corresponding to the key in the cache.
    pub fn get<'a>(&'a mut self, k: &K) -> Option<&'a V> {
        let (value, node_ptr_opt) = match self.map.find_mut(&KeyRef{k: k}) {
            None => (None, None),
            Some(node) => {
                let node_ptr: *mut LruEntry<K, V> = &mut **node;
                unsafe {
                    match (*node_ptr).value {
                        None => (None, None),
                        Some(ref value) => (Some(value), Some(node_ptr))
                    }
                }
            }
        };
        match node_ptr_opt {
            None => (),
            Some(node_ptr) => {
                self.detach(node_ptr);
                self.attach(node_ptr);
            }
        }
        return value;
    }

    /// Remove and return a value corresponding to the key from the cache.
    pub fn pop(&mut self, k: &K) -> Option<V> {
        match self.map.pop(&KeyRef{k: k}) {
            None => None,
            Some(lru_entry) => lru_entry.value
        }
    }

    /// Return the maximum number of key-value pairs the cache can hold.
    pub fn capacity(&self) -> uint {
        self.max_size
    }

    /// Change the number of key-value pairs the cache can hold. Remove
    /// least-recently-used key-value pairs if necessary.
    pub fn change_capacity(&mut self, capacity: uint) {
        for _ in range(capacity, self.len()) {
            self.remove_lru();
        }
        self.max_size = capacity;
    }

    #[inline]
    fn remove_lru(&mut self) {
        if self.len() > 0 {
            let lru = unsafe { (*self.tail).prev };
            self.detach(lru);
            unsafe {
                match (*lru).key {
                    None => (),
                    Some(ref k) => { self.map.pop(&KeyRef{k: k}); }
                }
            }
        }
    }

    #[inline]
    fn detach(&mut self, node: *mut LruEntry<K, V>) {
        unsafe {
            (*(*node).prev).next = (*node).next;
            (*(*node).next).prev = (*node).prev;
        }
    }

    #[inline]
    fn attach(&mut self, node: *mut LruEntry<K, V>) {
        unsafe {
            (*node).next = (*self.head).next;
            (*node).prev = self.head;
            (*self.head).next = node;
            (*(*node).next).prev = node;
        }
    }
}

impl<A: fmt::Show + Hash + TotalEq, B: fmt::Show> fmt::Show for LruCache<A, B> {
    /// Return a string that lists the key-value pairs from most-recently
    /// used to least-recently used.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f.buf, r"\{"));
        let mut cur = self.head;
        for i in range(0, self.len()) {
            if i > 0 { try!(write!(f.buf, ", ")) }
            unsafe {
                cur = (*cur).next;
                match (*cur).key {
                    // should never print nil
                    None => try!(write!(f.buf, "nil")),
                    Some(ref k) => try!(write!(f.buf, "{}", *k)),
                }
            }
            try!(write!(f.buf, ": "));
            unsafe {
                match (*cur).value {
                    // should never print nil
                    None => try!(write!(f.buf, "nil")),
                    Some(ref value) => try!(write!(f.buf, "{}", *value)),
                }
            }
        }
        write!(f.buf, r"\}")
    }
}

impl<K: Hash + TotalEq, V> Container for LruCache<K, V> {
    /// Return the number of key-value pairs in the cache.
    fn len(&self) -> uint {
        self.map.len()
    }
}

impl<K: Hash + TotalEq, V> Mutable for LruCache<K, V> {
    /// Clear the cache of all key-value pairs.
    fn clear(&mut self) {
        self.map.clear();
    }
}

#[unsafe_destructor]
impl<K, V> Drop for LruCache<K, V> {
    fn drop(&mut self) {
        unsafe {
            let _: ~LruEntry<K, V> = cast::transmute(self.head);
            let _: ~LruEntry<K, V> = cast::transmute(self.tail);
        }
    }
}

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

    fn assert_opt_eq<V: Eq>(opt: Option<&V>, v: V) {
        assert!(opt.is_some());
        assert!(opt.unwrap() == &v);
    }

    #[test]
    fn test_put_and_get() {
        let mut cache: LruCache<int, int> = LruCache::new(2);
        cache.put(1, 10);
        cache.put(2, 20);
        assert_opt_eq(cache.get(&1), 10);
        assert_opt_eq(cache.get(&2), 20);
        assert_eq!(cache.len(), 2);
    }

    #[test]
    fn test_put_update() {
        let mut cache: LruCache<~str, Vec<u8>> = LruCache::new(1);
        cache.put(~"1", vec![10, 10]);
        cache.put(~"1", vec![10, 19]);
        assert_opt_eq(cache.get(&~"1"), vec![10, 19]);
        assert_eq!(cache.len(), 1);
    }

    #[test]
    fn test_expire_lru() {
        let mut cache: LruCache<~str, ~str> = LruCache::new(2);
        cache.put(~"foo1", ~"bar1");
        cache.put(~"foo2", ~"bar2");
        cache.put(~"foo3", ~"bar3");
        assert!(cache.get(&~"foo1").is_none());
        cache.put(~"foo2", ~"bar2update");
        cache.put(~"foo4", ~"bar4");
        assert!(cache.get(&~"foo3").is_none());
    }

    #[test]
    fn test_pop() {
        let mut cache: LruCache<int, int> = LruCache::new(2);
        cache.put(1, 10);
        cache.put(2, 20);
        assert_eq!(cache.len(), 2);
        let opt1 = cache.pop(&1);
        assert!(opt1.is_some());
        assert_eq!(opt1.unwrap(), 10);
        assert!(cache.get(&1).is_none());
        assert_eq!(cache.len(), 1);
    }

    #[test]
    fn test_change_capacity() {
        let mut cache: LruCache<int, int> = LruCache::new(2);
        assert_eq!(cache.capacity(), 2);
        cache.put(1, 10);
        cache.put(2, 20);
        cache.change_capacity(1);
        assert!(cache.get(&1).is_none());
        assert_eq!(cache.capacity(), 1);
    }

    #[test]
    fn test_to_str() {
        let mut cache: LruCache<int, int> = LruCache::new(3);
        cache.put(1, 10);
        cache.put(2, 20);
        cache.put(3, 30);
        assert_eq!(cache.to_str(), ~"{3: 30, 2: 20, 1: 10}");
        cache.put(2, 22);
        assert_eq!(cache.to_str(), ~"{2: 22, 3: 30, 1: 10}");
        cache.put(6, 60);
        assert_eq!(cache.to_str(), ~"{6: 60, 2: 22, 3: 30}");
        cache.get(&3);
        assert_eq!(cache.to_str(), ~"{3: 30, 6: 60, 2: 22}");
        cache.change_capacity(2);
        assert_eq!(cache.to_str(), ~"{3: 30, 6: 60}");
    }

    #[test]
    fn test_clear() {
        let mut cache: LruCache<int, int> = LruCache::new(2);
        cache.put(1, 10);
        cache.put(2, 20);
        cache.clear();
        assert!(cache.get(&1).is_none());
        assert!(cache.get(&2).is_none());
        assert_eq!(cache.to_str(), ~"{}");
    }
}
<commit_msg>Eliminate unecessary extra sigil node from LruCache.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A cache that holds a limited number of key-value pairs. When the
//! capacity of the cache is exceeded, the least-recently-used
//! (where "used" means a look-up or putting the pair into the cache)
//! pair is automatically removed.
//!
//! # Example
//!
//! ```rust
//! use collections::LruCache;
//!
//! let mut cache: LruCache<int, int> = LruCache::new(2);
//! cache.put(1, 10);
//! cache.put(2, 20);
//! cache.put(3, 30);
//! assert!(cache.get(&1).is_none());
//! assert_eq!(*cache.get(&2).unwrap(), 20);
//! assert_eq!(*cache.get(&3).unwrap(), 30);
//!
//! cache.put(2, 22);
//! assert_eq!(*cache.get(&2).unwrap(), 22);
//!
//! cache.put(6, 60);
//! assert!(cache.get(&3).is_none());
//!
//! cache.change_capacity(1);
//! assert!(cache.get(&2).is_none());
//! ```

use std::cast;
use std::container::Container;
use std::hash::Hash;
use std::fmt;
use std::ptr;

use HashMap;

struct KeyRef<K> { k: *K }

struct LruEntry<K, V> {
    key: Option<K>,
    value: Option<V>,
    next: *mut LruEntry<K, V>,
    prev: *mut LruEntry<K, V>,
}

/// An LRU Cache.
pub struct LruCache<K, V> {
    map: HashMap<KeyRef<K>, ~LruEntry<K, V>>,
    max_size: uint,
    head: *mut LruEntry<K, V>,
}

impl<S, K: Hash<S>> Hash<S> for KeyRef<K> {
    fn hash(&self, state: &mut S) {
        unsafe { (*self.k).hash(state) }
    }
}

impl<K: Eq> Eq for KeyRef<K> {
    fn eq(&self, other: &KeyRef<K>) -> bool {
        unsafe{ (*self.k).eq(&*other.k) }
    }
}

impl<K: TotalEq> TotalEq for KeyRef<K> {}

impl<K, V> LruEntry<K, V> {
    fn new() -> LruEntry<K, V> {
        LruEntry {
            key: None,
            value: None,
            next: ptr::mut_null(),
            prev: ptr::mut_null(),
        }
    }

    fn with_key_value(k: K, v: V) -> LruEntry<K, V> {
        LruEntry {
            key: Some(k),
            value: Some(v),
            next: ptr::mut_null(),
            prev: ptr::mut_null(),
        }
    }
}

impl<K: Hash + TotalEq, V> LruCache<K, V> {
    /// Create an LRU Cache that holds at most `capacity` items.
    pub fn new(capacity: uint) -> LruCache<K, V> {
        let cache = LruCache {
            map: HashMap::new(),
            max_size: capacity,
            head: unsafe{ cast::transmute(~LruEntry::<K, V>::new()) },
        };
        unsafe {
            (*cache.head).next = cache.head;
            (*cache.head).prev = cache.head;
        }
        return cache;
    }

    /// Put a key-value pair into cache.
    pub fn put(&mut self, k: K, v: V) {
        let (node_ptr, node_opt) = match self.map.find_mut(&KeyRef{k: &k}) {
            Some(node) => {
                node.value = Some(v);
                let node_ptr: *mut LruEntry<K, V> = &mut **node;
                (node_ptr, None)
            }
            None => {
                let mut node = ~LruEntry::with_key_value(k, v);
                let node_ptr: *mut LruEntry<K, V> = &mut *node;
                (node_ptr, Some(node))
            }
        };
        match node_opt {
            None => {
                self.detach(node_ptr);
                self.attach(node_ptr);
            }
            Some(node) => {
                let keyref = unsafe { (*node_ptr).key.as_ref().unwrap() };
                self.map.swap(KeyRef{k: keyref}, node);
                self.attach(node_ptr);
                if self.len() > self.capacity() {
                    self.remove_lru();
                }
            }
        }
    }

    /// Return a value corresponding to the key in the cache.
    pub fn get<'a>(&'a mut self, k: &K) -> Option<&'a V> {
        let (value, node_ptr_opt) = match self.map.find_mut(&KeyRef{k: k}) {
            None => (None, None),
            Some(node) => {
                let node_ptr: *mut LruEntry<K, V> = &mut **node;
                unsafe {
                    match (*node_ptr).value {
                        None => (None, None),
                        Some(ref value) => (Some(value), Some(node_ptr))
                    }
                }
            }
        };
        match node_ptr_opt {
            None => (),
            Some(node_ptr) => {
                self.detach(node_ptr);
                self.attach(node_ptr);
            }
        }
        return value;
    }

    /// Remove and return a value corresponding to the key from the cache.
    pub fn pop(&mut self, k: &K) -> Option<V> {
        match self.map.pop(&KeyRef{k: k}) {
            None => None,
            Some(lru_entry) => lru_entry.value
        }
    }

    /// Return the maximum number of key-value pairs the cache can hold.
    pub fn capacity(&self) -> uint {
        self.max_size
    }

    /// Change the number of key-value pairs the cache can hold. Remove
    /// least-recently-used key-value pairs if necessary.
    pub fn change_capacity(&mut self, capacity: uint) {
        for _ in range(capacity, self.len()) {
            self.remove_lru();
        }
        self.max_size = capacity;
    }

    #[inline]
    fn remove_lru(&mut self) {
        if self.len() > 0 {
            let lru = unsafe { (*self.head).prev };
            self.detach(lru);
            unsafe {
                match (*lru).key {
                    None => (),
                    Some(ref k) => { self.map.pop(&KeyRef{k: k}); }
                }
            }
        }
    }

    #[inline]
    fn detach(&mut self, node: *mut LruEntry<K, V>) {
        unsafe {
            (*(*node).prev).next = (*node).next;
            (*(*node).next).prev = (*node).prev;
        }
    }

    #[inline]
    fn attach(&mut self, node: *mut LruEntry<K, V>) {
        unsafe {
            (*node).next = (*self.head).next;
            (*node).prev = self.head;
            (*self.head).next = node;
            (*(*node).next).prev = node;
        }
    }
}

impl<A: fmt::Show + Hash + TotalEq, B: fmt::Show> fmt::Show for LruCache<A, B> {
    /// Return a string that lists the key-value pairs from most-recently
    /// used to least-recently used.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f.buf, r"\{"));
        let mut cur = self.head;
        for i in range(0, self.len()) {
            if i > 0 { try!(write!(f.buf, ", ")) }
            unsafe {
                cur = (*cur).next;
                match (*cur).key {
                    // should never print nil
                    None => try!(write!(f.buf, "nil")),
                    Some(ref k) => try!(write!(f.buf, "{}", *k)),
                }
            }
            try!(write!(f.buf, ": "));
            unsafe {
                match (*cur).value {
                    // should never print nil
                    None => try!(write!(f.buf, "nil")),
                    Some(ref value) => try!(write!(f.buf, "{}", *value)),
                }
            }
        }
        write!(f.buf, r"\}")
    }
}

impl<K: Hash + TotalEq, V> Container for LruCache<K, V> {
    /// Return the number of key-value pairs in the cache.
    fn len(&self) -> uint {
        self.map.len()
    }
}

impl<K: Hash + TotalEq, V> Mutable for LruCache<K, V> {
    /// Clear the cache of all key-value pairs.
    fn clear(&mut self) {
        self.map.clear();
    }
}

#[unsafe_destructor]
impl<K, V> Drop for LruCache<K, V> {
    fn drop(&mut self) {
        unsafe {
            let _: ~LruEntry<K, V> = cast::transmute(self.head);
        }
    }
}

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

    fn assert_opt_eq<V: Eq>(opt: Option<&V>, v: V) {
        assert!(opt.is_some());
        assert!(opt.unwrap() == &v);
    }

    #[test]
    fn test_put_and_get() {
        let mut cache: LruCache<int, int> = LruCache::new(2);
        cache.put(1, 10);
        cache.put(2, 20);
        assert_opt_eq(cache.get(&1), 10);
        assert_opt_eq(cache.get(&2), 20);
        assert_eq!(cache.len(), 2);
    }

    #[test]
    fn test_put_update() {
        let mut cache: LruCache<~str, Vec<u8>> = LruCache::new(1);
        cache.put(~"1", vec![10, 10]);
        cache.put(~"1", vec![10, 19]);
        assert_opt_eq(cache.get(&~"1"), vec![10, 19]);
        assert_eq!(cache.len(), 1);
    }

    #[test]
    fn test_expire_lru() {
        let mut cache: LruCache<~str, ~str> = LruCache::new(2);
        cache.put(~"foo1", ~"bar1");
        cache.put(~"foo2", ~"bar2");
        cache.put(~"foo3", ~"bar3");
        assert!(cache.get(&~"foo1").is_none());
        cache.put(~"foo2", ~"bar2update");
        cache.put(~"foo4", ~"bar4");
        assert!(cache.get(&~"foo3").is_none());
    }

    #[test]
    fn test_pop() {
        let mut cache: LruCache<int, int> = LruCache::new(2);
        cache.put(1, 10);
        cache.put(2, 20);
        assert_eq!(cache.len(), 2);
        let opt1 = cache.pop(&1);
        assert!(opt1.is_some());
        assert_eq!(opt1.unwrap(), 10);
        assert!(cache.get(&1).is_none());
        assert_eq!(cache.len(), 1);
    }

    #[test]
    fn test_change_capacity() {
        let mut cache: LruCache<int, int> = LruCache::new(2);
        assert_eq!(cache.capacity(), 2);
        cache.put(1, 10);
        cache.put(2, 20);
        cache.change_capacity(1);
        assert!(cache.get(&1).is_none());
        assert_eq!(cache.capacity(), 1);
    }

    #[test]
    fn test_to_str() {
        let mut cache: LruCache<int, int> = LruCache::new(3);
        cache.put(1, 10);
        cache.put(2, 20);
        cache.put(3, 30);
        assert_eq!(cache.to_str(), ~"{3: 30, 2: 20, 1: 10}");
        cache.put(2, 22);
        assert_eq!(cache.to_str(), ~"{2: 22, 3: 30, 1: 10}");
        cache.put(6, 60);
        assert_eq!(cache.to_str(), ~"{6: 60, 2: 22, 3: 30}");
        cache.get(&3);
        assert_eq!(cache.to_str(), ~"{3: 30, 6: 60, 2: 22}");
        cache.change_capacity(2);
        assert_eq!(cache.to_str(), ~"{3: 30, 6: 60}");
    }

    #[test]
    fn test_clear() {
        let mut cache: LruCache<int, int> = LruCache::new(2);
        cache.put(1, 10);
        cache.put(2, 20);
        cache.clear();
        assert!(cache.get(&1).is_none());
        assert!(cache.get(&2).is_none());
        assert_eq!(cache.to_str(), ~"{}");
    }
}
<|endoftext|>


<commit_before>//! Serialization for client-server communication.

use std::any::Any;
use std::char;
use std::io::Write;
use std::num::NonZeroU32;
use std::ops::Bound;
use std::str;

pub(super) type Writer = super::buffer::Buffer<u8>;

pub(super) trait Encode<S>: Sized {
    fn encode(self, w: &mut Writer, s: &mut S);
}

pub(super) type Reader<'a> = &'a [u8];

pub(super) trait Decode<'a, 's, S>: Sized {
    fn decode(r: &mut Reader<'a>, s: &'s S) -> Self;
}

pub(super) trait DecodeMut<'a, 's, S>: Sized {
    fn decode(r: &mut Reader<'a>, s: &'s mut S) -> Self;
}

macro_rules! rpc_encode_decode {
    (uleb128 $ty:ty) => {
        impl<S> Encode<S> for $ty {
            fn encode(mut self, w: &mut Writer, s: &mut S) {
                let mut byte = 0x80;
                while byte & 0x80 != 0 {
                    byte = (self & 0x7f) as u8;
                    self >>= 7;
                    if self != 0 {
                        byte |= 0x80;
                    }
                    byte.encode(w, s);
                }
            }
        }

        impl<S> DecodeMut<'_, '_, S> for $ty {
            fn decode(r: &mut Reader, s: &mut S) -> Self {
                let mut byte = 0x80;
                let mut v = 0;
                let mut shift = 0;
                while byte & 0x80 != 0 {
                    byte = u8::decode(r, s);
                    v |= ((byte & 0x7f) as Self) << shift;
                    shift += 7;
                }
                v
            }
        }
    };
    (struct $name:ident { $($field:ident),* $(,)* }) => {
        impl<S> Encode<S> for $name {
            fn encode(self, w: &mut Writer, s: &mut S) {
                $(self.$field.encode(w, s);)*
            }
        }

        impl<S> DecodeMut<'_, '_, S> for $name {
            fn decode(r: &mut Reader, s: &mut S) -> Self {
                $name {
                    $($field: DecodeMut::decode(r, s)),*
                }
            }
        }
    };
    (enum $name:ident $(<$($T:ident),+>)* { $($variant:ident $(($field:ident))*),* $(,)* }) => {
        impl<S, $($($T: Encode<S>),+)*> Encode<S> for $name $(<$($T),+>)* {
            fn encode(self, w: &mut Writer, s: &mut S) {
                // HACK(eddyb) `Tag` enum duplicated between the
                // two impls as there's no other place to stash it.
                #[repr(u8)] enum Tag { $($variant),* }
                #[allow(non_upper_case_globals)]
                impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* }

                match self {
                    $($name::$variant $(($field))* => {
                        <Tag>::$variant.encode(w, s);
                        $($field.encode(w, s);)*
                    })*
                }
            }
        }

        impl<S, $($($T: for<'s> DecodeMut<'a, 's, S>),+)*> DecodeMut<'a, '_, S>
            for $name $(<$($T),+>)*
        {
            fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
                // HACK(eddyb) `Tag` enum duplicated between the
                // two impls as there's no other place to stash it.
                #[repr(u8)] enum Tag { $($variant),* }
                #[allow(non_upper_case_globals)]
                impl Tag { $(const $variant: u8 = Tag::$variant as u8;)* }

                match u8::decode(r, s) {
                    $(<Tag>::$variant => {
                        $(let $field = DecodeMut::decode(r, s);)*
                        $name::$variant $(($field))*
                    })*
                    _ => unreachable!(),
                }
            }
        }
    }
}

impl<S> Encode<S> for () {
    fn encode(self, _: &mut Writer, _: &mut S) {}
}

impl<S> DecodeMut<'_, '_, S> for () {
    fn decode(_: &mut Reader, _: &mut S) -> Self {}
}

impl<S> Encode<S> for u8 {
    fn encode(self, w: &mut Writer, _: &mut S) {
        w.write_all(&[self]).unwrap();
    }
}

impl<S> DecodeMut<'_, '_, S> for u8 {
    fn decode(r: &mut Reader, _: &mut S) -> Self {
        let x = r[0];
        *r = &r[1..];
        x
    }
}

rpc_encode_decode!(uleb128 u32);
rpc_encode_decode!(uleb128 usize);

impl<S> Encode<S> for bool {
    fn encode(self, w: &mut Writer, s: &mut S) {
        (self as u8).encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for bool {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        match u8::decode(r, s) {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }
}

impl<S> Encode<S> for char {
    fn encode(self, w: &mut Writer, s: &mut S) {
        (self as u32).encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for char {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        char::from_u32(u32::decode(r, s)).unwrap()
    }
}

impl<S> Encode<S> for NonZeroU32 {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.get().encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for NonZeroU32 {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        Self::new(u32::decode(r, s)).unwrap()
    }
}

impl<S, A: Encode<S>, B: Encode<S>> Encode<S> for (A, B) {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.0.encode(w, s);
        self.1.encode(w, s);
    }
}

impl<S, A: for<'s> DecodeMut<'a, 's, S>, B: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S>
    for (A, B)
{
    fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
        (DecodeMut::decode(r, s), DecodeMut::decode(r, s))
    }
}

rpc_encode_decode!(
    enum Bound<T> {
        Included(x),
        Excluded(x),
        Unbounded,
    }
);

rpc_encode_decode!(
    enum Option<T> {
        None,
        Some(x),
    }
);

rpc_encode_decode!(
    enum Result<T, E> {
        Ok(x),
        Err(e),
    }
);

impl<S> Encode<S> for &[u8] {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.len().encode(w, s);
        w.write_all(self).unwrap();
    }
}

impl<S> DecodeMut<'a, '_, S> for &'a [u8] {
    fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
        let len = usize::decode(r, s);
        let xs = &r[..len];
        *r = &r[len..];
        xs
    }
}

impl<S> Encode<S> for &str {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.as_bytes().encode(w, s);
    }
}

impl<S> DecodeMut<'a, '_, S> for &'a str {
    fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
        str::from_utf8(<&[u8]>::decode(r, s)).unwrap()
    }
}

impl<S> Encode<S> for String {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self[..].encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for String {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        <&str>::decode(r, s).to_string()
    }
}

/// Simplied version of panic payloads, ignoring
/// types other than `&'static str` and `String`.
pub enum PanicMessage {
    StaticStr(&'static str),
    String(String),
    Unknown,
}

impl From<Box<dyn Any + Send>> for PanicMessage {
    fn from(payload: Box<dyn Any + Send + 'static>) -> Self {
        if let Some(s) = payload.downcast_ref::<&'static str>() {
            return PanicMessage::StaticStr(s);
        }
        if let Ok(s) = payload.downcast::<String>() {
            return PanicMessage::String(*s);
        }
        PanicMessage::Unknown
    }
}

impl Into<Box<dyn Any + Send>> for PanicMessage {
    fn into(self) -> Box<dyn Any + Send> {
        match self {
            PanicMessage::StaticStr(s) => Box::new(s),
            PanicMessage::String(s) => Box::new(s),
            PanicMessage::Unknown => {
                struct UnknownPanicMessage;
                Box::new(UnknownPanicMessage)
            }
        }
    }
}

impl PanicMessage {
    pub fn as_str(&self) -> Option<&str> {
        match self {
            PanicMessage::StaticStr(s) => Some(s),
            PanicMessage::String(s) => Some(s),
            PanicMessage::Unknown => None,
        }
    }
}

impl<S> Encode<S> for PanicMessage {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.as_str().encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for PanicMessage {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        match Option::<String>::decode(r, s) {
            Some(s) => PanicMessage::String(s),
            None => PanicMessage::Unknown,
        }
    }
}
<commit_msg>Work-around for shadowing of variant names with assoc const names in `libproc_macro/bridge/rpc.rs`.<commit_after>//! Serialization for client-server communication.

use std::any::Any;
use std::char;
use std::io::Write;
use std::num::NonZeroU32;
use std::ops::Bound;
use std::str;

pub(super) type Writer = super::buffer::Buffer<u8>;

pub(super) trait Encode<S>: Sized {
    fn encode(self, w: &mut Writer, s: &mut S);
}

pub(super) type Reader<'a> = &'a [u8];

pub(super) trait Decode<'a, 's, S>: Sized {
    fn decode(r: &mut Reader<'a>, s: &'s S) -> Self;
}

pub(super) trait DecodeMut<'a, 's, S>: Sized {
    fn decode(r: &mut Reader<'a>, s: &'s mut S) -> Self;
}

macro_rules! rpc_encode_decode {
    (uleb128 $ty:ty) => {
        impl<S> Encode<S> for $ty {
            fn encode(mut self, w: &mut Writer, s: &mut S) {
                let mut byte = 0x80;
                while byte & 0x80 != 0 {
                    byte = (self & 0x7f) as u8;
                    self >>= 7;
                    if self != 0 {
                        byte |= 0x80;
                    }
                    byte.encode(w, s);
                }
            }
        }

        impl<S> DecodeMut<'_, '_, S> for $ty {
            fn decode(r: &mut Reader, s: &mut S) -> Self {
                let mut byte = 0x80;
                let mut v = 0;
                let mut shift = 0;
                while byte & 0x80 != 0 {
                    byte = u8::decode(r, s);
                    v |= ((byte & 0x7f) as Self) << shift;
                    shift += 7;
                }
                v
            }
        }
    };
    (struct $name:ident { $($field:ident),* $(,)* }) => {
        impl<S> Encode<S> for $name {
            fn encode(self, w: &mut Writer, s: &mut S) {
                $(self.$field.encode(w, s);)*
            }
        }

        impl<S> DecodeMut<'_, '_, S> for $name {
            fn decode(r: &mut Reader, s: &mut S) -> Self {
                $name {
                    $($field: DecodeMut::decode(r, s)),*
                }
            }
        }
    };
    (enum $name:ident $(<$($T:ident),+>)* { $($variant:ident $(($field:ident))*),* $(,)* }) => {
        impl<S, $($($T: Encode<S>),+)*> Encode<S> for $name $(<$($T),+>)* {
            fn encode(self, w: &mut Writer, s: &mut S) {
                // HACK(eddyb): `Tag` enum duplicated between the
                // two impls as there's no other place to stash it.
                #[allow(non_upper_case_globals)]
                mod tag {
                    #[repr(u8)] enum Tag { $($variant),* }

                    $(pub const $variant: u8 = Tag::$variant as u8;)*
                }

                match self {
                    $($name::$variant $(($field))* => {
                        tag::$variant.encode(w, s);
                        $($field.encode(w, s);)*
                    })*
                }
            }
        }

        impl<S, $($($T: for<'s> DecodeMut<'a, 's, S>),+)*> DecodeMut<'a, '_, S>
            for $name $(<$($T),+>)*
        {
            fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
                // HACK(eddyb): `Tag` enum duplicated between the
                // two impls as there's no other place to stash it.
                #[allow(non_upper_case_globals)]
                mod tag {
                    #[repr(u8)] enum Tag { $($variant),* }

                    $(pub const $variant: u8 = Tag::$variant as u8;)*
                }

                match u8::decode(r, s) {
                    $(tag::$variant => {
                        $(let $field = DecodeMut::decode(r, s);)*
                        $name::$variant $(($field))*
                    })*
                    _ => unreachable!(),
                }
            }
        }
    }
}

impl<S> Encode<S> for () {
    fn encode(self, _: &mut Writer, _: &mut S) {}
}

impl<S> DecodeMut<'_, '_, S> for () {
    fn decode(_: &mut Reader, _: &mut S) -> Self {}
}

impl<S> Encode<S> for u8 {
    fn encode(self, w: &mut Writer, _: &mut S) {
        w.write_all(&[self]).unwrap();
    }
}

impl<S> DecodeMut<'_, '_, S> for u8 {
    fn decode(r: &mut Reader, _: &mut S) -> Self {
        let x = r[0];
        *r = &r[1..];
        x
    }
}

rpc_encode_decode!(uleb128 u32);
rpc_encode_decode!(uleb128 usize);

impl<S> Encode<S> for bool {
    fn encode(self, w: &mut Writer, s: &mut S) {
        (self as u8).encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for bool {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        match u8::decode(r, s) {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }
}

impl<S> Encode<S> for char {
    fn encode(self, w: &mut Writer, s: &mut S) {
        (self as u32).encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for char {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        char::from_u32(u32::decode(r, s)).unwrap()
    }
}

impl<S> Encode<S> for NonZeroU32 {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.get().encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for NonZeroU32 {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        Self::new(u32::decode(r, s)).unwrap()
    }
}

impl<S, A: Encode<S>, B: Encode<S>> Encode<S> for (A, B) {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.0.encode(w, s);
        self.1.encode(w, s);
    }
}

impl<S, A: for<'s> DecodeMut<'a, 's, S>, B: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S>
    for (A, B)
{
    fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
        (DecodeMut::decode(r, s), DecodeMut::decode(r, s))
    }
}

rpc_encode_decode!(
    enum Bound<T> {
        Included(x),
        Excluded(x),
        Unbounded,
    }
);

rpc_encode_decode!(
    enum Option<T> {
        None,
        Some(x),
    }
);

rpc_encode_decode!(
    enum Result<T, E> {
        Ok(x),
        Err(e),
    }
);

impl<S> Encode<S> for &[u8] {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.len().encode(w, s);
        w.write_all(self).unwrap();
    }
}

impl<S> DecodeMut<'a, '_, S> for &'a [u8] {
    fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
        let len = usize::decode(r, s);
        let xs = &r[..len];
        *r = &r[len..];
        xs
    }
}

impl<S> Encode<S> for &str {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.as_bytes().encode(w, s);
    }
}

impl<S> DecodeMut<'a, '_, S> for &'a str {
    fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
        str::from_utf8(<&[u8]>::decode(r, s)).unwrap()
    }
}

impl<S> Encode<S> for String {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self[..].encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for String {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        <&str>::decode(r, s).to_string()
    }
}

/// Simplied version of panic payloads, ignoring
/// types other than `&'static str` and `String`.
pub enum PanicMessage {
    StaticStr(&'static str),
    String(String),
    Unknown,
}

impl From<Box<dyn Any + Send>> for PanicMessage {
    fn from(payload: Box<dyn Any + Send + 'static>) -> Self {
        if let Some(s) = payload.downcast_ref::<&'static str>() {
            return PanicMessage::StaticStr(s);
        }
        if let Ok(s) = payload.downcast::<String>() {
            return PanicMessage::String(*s);
        }
        PanicMessage::Unknown
    }
}

impl Into<Box<dyn Any + Send>> for PanicMessage {
    fn into(self) -> Box<dyn Any + Send> {
        match self {
            PanicMessage::StaticStr(s) => Box::new(s),
            PanicMessage::String(s) => Box::new(s),
            PanicMessage::Unknown => {
                struct UnknownPanicMessage;
                Box::new(UnknownPanicMessage)
            }
        }
    }
}

impl PanicMessage {
    pub fn as_str(&self) -> Option<&str> {
        match self {
            PanicMessage::StaticStr(s) => Some(s),
            PanicMessage::String(s) => Some(s),
            PanicMessage::Unknown => None,
        }
    }
}

impl<S> Encode<S> for PanicMessage {
    fn encode(self, w: &mut Writer, s: &mut S) {
        self.as_str().encode(w, s);
    }
}

impl<S> DecodeMut<'_, '_, S> for PanicMessage {
    fn decode(r: &mut Reader, s: &mut S) -> Self {
        match Option::<String>::decode(r, s) {
            Some(s) => PanicMessage::String(s),
            None => PanicMessage::Unknown,
        }
    }
}
<|endoftext|>


<commit_before>pub mod parser;
pub mod token;
pub mod shunting_yard;

mod lexer;
mod rpn_calculator;
mod peekable_string_iterator;

// Exported types
pub use self::shunting_yard::ShuntingYard;
<commit_msg>Removed parser module declaration<commit_after>pub mod token;
pub mod shunting_yard;

mod lexer;
mod rpn_calculator;
mod peekable_string_iterator;

// Exported types
pub use self::shunting_yard::ShuntingYard;
<|endoftext|>


<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::hir::{self, ImplPolarity};
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::ty::{self, TyCtxt};
use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
use syntax::ast;
use rustc_data_structures::sync::Lrc;

trait Lower<T> {
    /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
    fn lower(&self) -> T;
}

impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
    fn lower(&self) -> Vec<U> {
        self.iter().map(|item| item.lower()).collect()
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::TraitPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::Implemented(*self)
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::ProjectionEq(*self)
    }
}

impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::Holds(self.lower())
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::RegionOutlives(*self)
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::TypeOutlives(*self)
    }
}

/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
/// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
/// example), we model them with quantified goals, e.g. as for the previous example:
/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
/// `Binder<Holds(Implemented(TraitPredicate))>`.
///
/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
/// can directly lower to a leaf goal instead of a quantified goal.
impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
{
    fn lower(&self) -> Goal<'tcx> {
        match self.no_late_bound_regions() {
            Some(p) => p.lower().into(),
            None => Goal::Quantified(
                QuantifierKind::Universal,
                Box::new(self.map_bound(|p| p.lower().into()))
            ),
        }
    }
}

impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
    fn lower(&self) -> Goal<'tcx> {
        use rustc::ty::Predicate::*;

        match self {
            Trait(predicate) => predicate.lower(),
            RegionOutlives(predicate) => predicate.lower(),
            TypeOutlives(predicate) => predicate.lower(),
            Projection(predicate) => predicate.lower(),
            WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
            ObjectSafe(..) |
            ClosureKind(..) |
            Subtype(..) |
            ConstEvaluatable(..) => unimplemented!(),
        }
    }
}

crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
    let item = tcx.hir.expect_item(node_id);
    match item.node {
        hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),

        // FIXME: other constructions e.g. traits, associated types...
        _ => Lrc::new(vec![]),
    }
}

fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
        return Lrc::new(vec![]);
    }

    // Rule Implemented-From-Impl
    //
    // (see rustc guide)

    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
    let trait_ref = ty::TraitPredicate { trait_ref }.lower();
    let where_clauses = tcx.predicates_of(def_id).predicates.lower();

    let clause = Clause::Implies(where_clauses, trait_ref);
    Lrc::new(vec![clause])
}

pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
    if !tcx.features().rustc_attrs {
        return;
    }

    let mut visitor = ClauseDumper { tcx };
    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
}

struct ClauseDumper<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
    fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
        let def_id = self.tcx.hir.local_def_id(node_id);
        for attr in attrs {
            if attr.check_name("rustc_dump_program_clauses") {
                let clauses = self.tcx.program_clauses_for(def_id);
                for clause in &*clauses {
                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
                }
            }
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_item(&mut self, item: &'tcx hir::Item) {
        self.process_attrs(item.id, &item.attrs);
        intravisit::walk_item(self, item);
    }

    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
        self.process_attrs(trait_item.id, &trait_item.attrs);
        intravisit::walk_trait_item(self, trait_item);
    }

    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
        self.process_attrs(impl_item.id, &impl_item.attrs);
        intravisit::walk_impl_item(self, impl_item);
    }

    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
        self.process_attrs(s.id, &s.attrs);
        intravisit::walk_struct_field(self, s);
    }
}
<commit_msg>Fix tidy<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::hir::{self, ImplPolarity};
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::ty::{self, TyCtxt};
use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
use syntax::ast;
use rustc_data_structures::sync::Lrc;

trait Lower<T> {
    /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
    fn lower(&self) -> T;
}

impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
    fn lower(&self) -> Vec<U> {
        self.iter().map(|item| item.lower()).collect()
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::TraitPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::Implemented(*self)
    }
}

impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
    fn lower(&self) -> WhereClauseAtom<'tcx> {
        WhereClauseAtom::ProjectionEq(*self)
    }
}

impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::Holds(self.lower())
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::RegionOutlives(*self)
    }
}

impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
    fn lower(&self) -> DomainGoal<'tcx> {
        DomainGoal::TypeOutlives(*self)
    }
}

/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
/// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
/// example), we model them with quantified goals, e.g. as for the previous example:
/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
/// `Binder<Holds(Implemented(TraitPredicate))>`.
///
/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
/// can directly lower to a leaf goal instead of a quantified goal.
impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
{
    fn lower(&self) -> Goal<'tcx> {
        match self.no_late_bound_regions() {
            Some(p) => p.lower().into(),
            None => Goal::Quantified(
                QuantifierKind::Universal,
                Box::new(self.map_bound(|p| p.lower().into()))
            ),
        }
    }
}

impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
    fn lower(&self) -> Goal<'tcx> {
        use rustc::ty::Predicate::*;

        match self {
            Trait(predicate) => predicate.lower(),
            RegionOutlives(predicate) => predicate.lower(),
            TypeOutlives(predicate) => predicate.lower(),
            Projection(predicate) => predicate.lower(),
            WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
            ObjectSafe(..) |
            ClosureKind(..) |
            Subtype(..) |
            ConstEvaluatable(..) => unimplemented!(),
        }
    }
}

crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
    let item = tcx.hir.expect_item(node_id);
    match item.node {
        hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),

        // FIXME: other constructions e.g. traits, associated types...
        _ => Lrc::new(vec![]),
    }
}

fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
    -> Lrc<Vec<Clause<'tcx>>>
{
    if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
        return Lrc::new(vec![]);
    }

    // Rule Implemented-From-Impl
    //
    // (see rustc guide)

    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
    let trait_ref = ty::TraitPredicate { trait_ref }.lower();
    let where_clauses = tcx.predicates_of(def_id).predicates.lower();

    let clause = Clause::Implies(where_clauses, trait_ref);
    Lrc::new(vec![clause])
}

pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
    if !tcx.features().rustc_attrs {
        return;
    }

    let mut visitor = ClauseDumper { tcx };
    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
}

struct ClauseDumper<'a, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
}

impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
    fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
        let def_id = self.tcx.hir.local_def_id(node_id);
        for attr in attrs {
            if attr.check_name("rustc_dump_program_clauses") {
                let clauses = self.tcx.program_clauses_for(def_id);
                for clause in &*clauses {
                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
                }
            }
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_item(&mut self, item: &'tcx hir::Item) {
        self.process_attrs(item.id, &item.attrs);
        intravisit::walk_item(self, item);
    }

    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
        self.process_attrs(trait_item.id, &trait_item.attrs);
        intravisit::walk_trait_item(self, trait_item);
    }

    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
        self.process_attrs(impl_item.id, &impl_item.attrs);
        intravisit::walk_impl_item(self, impl_item);
    }

    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
        self.process_attrs(s.id, &s.attrs);
        intravisit::walk_struct_field(self, s);
    }
}
<|endoftext|>