<commit_before>use std::io::Read;

use hyper::Client;
use hyper::header::Connection;
use rustc_serialize::json::Json;
use url::percent_encoding;

use ::json;
use ::json::JsonPathElement::{Key, Only};

pub struct Wiki {
    hostname: String,
}

#[derive(Clone)]
pub struct Revision {
    pub revid: u64,
    pub parentid: u64,
    pub comment: String,
}

impl Wiki {
    /// Constructs a Wiki object representing the wiki at `hostname` (e.g. "en.wikipedia.org").
    pub fn new(hostname: &str) -> Wiki {
        Wiki { hostname: hostname.to_string() }
    }

    // TODO: return a Result
    /// Calls the MediaWiki API with the given parameters and format=json. Returns the raw JSON.
    fn call_mediawiki_api(&self, parameters: Vec<(&str, &str)>) -> String {
        let post_body =
            parameters.into_iter().map(|p| format!("{}={}", p.0, p.1))
            .collect::<Vec<_>>().join("&") + "&format=json";

        let client = Client::new();
        let mut response = client.post(&format!("https://{}/w/api.php", self.hostname))
            .body(&post_body)
            .header(Connection::close())
            .send().unwrap();

        let mut body = String::new();
        response.read_to_string(&mut body).unwrap();
        body
    }

    /// Returns the last `limit` revisions for the page `title`.
    pub fn get_revisions(&self, title: &str, limit: u64) -> Result<Vec<Revision>, String> {
        let json_str = self.call_mediawiki_api(
            vec![("action", "query"), ("prop", "revisions"), ("titles", title),
                 ("rvprop", "comment|ids"), ("rvlimit", &limit.to_string())]);
        let json = Json::from_str(&json_str).unwrap();
        let revisions = try!(
            json::get_json_array(&json, &[Key("query"), Key("pages"), Only, Key("revisions")]));

        // Check that  all revisions have revid and parentid (they all should).
        // TODO: what about making a Vec<Result<Revision>, String> and then rolling that up with a fold()? Would eliminate the repetition of the get_json_* calls.
        if revisions.into_iter().any(|revision| {
            json::get_json_number(revision, &[Key("revid")]).is_err() ||
            json::get_json_number(revision, &[Key("parentid")]).is_err() ||
            json::get_json_string(revision, &[Key("comment")]).is_err()
        }) {
            Err(format!(
                "One or more revisions of page \"{}\" have missing or invalid field", title))
        } else {
            Ok(revisions.into_iter().map(|revision| {
                Revision {
                    revid: json::get_json_number(revision, &[Key("revid")]).unwrap(),
                    parentid: json::get_json_number(revision, &[Key("parentid")]).unwrap(),
                    comment: json::get_json_string(revision, &[Key("comment")]).unwrap().to_string()
                }
            }).collect())
        }
    }

    /// Returns the latest revision ID for the page `title`.
    pub fn get_latest_revision(&self, title: &str) -> Result<Revision, String> {
        // TODO: Can this be a one-liner? Does try!() work properly like that?
        let revisions = try!(self.get_revisions(title, 1));
        Ok(revisions[0].clone())
    }

    /// Returns the contents of the page `title` as of (i.e., immediately after) revision `id`.
    pub fn get_revision_content(&self, title: &str, id: u64) -> Result<String, String> {
        let json_str = self.call_mediawiki_api(
            vec![("action", "query"), ("prop", "revisions"), ("titles", title), ("rvprop", "content"),
                 ("rvlimit", "1"), ("rvstartid", &id.to_string())]);
        let json = Json::from_str(&json_str).unwrap();
        match json::get_json_string(
            &json, &[Key("query"), Key("pages"), Only, Key("revisions"), Only, Key("*")]) {
            Ok(content) => Ok(content.to_string()),
            Err(msg) => Err(msg),
        }
    }

    /// Follows all redirects to find the canonical name of the page at `title`.
    pub fn get_canonical_title(&self, title: &str) -> Result<String, String> {
        let latest_revision_id = self.get_latest_revision(title).unwrap().revid;
        let page_contents = self.get_revision_content(title, latest_revision_id).unwrap();

        let regex = regex!(r"#REDIRECT \[\[([^]]+)\]\].*");
        match regex.captures(&page_contents) {
            Some(captures) => self.get_canonical_title(captures.at(1).unwrap()),
            None => {
                println!("Canonical page title is \"{}\"", title);
                Ok(title.to_string())
            },
        }
    }

    /// Parses the wikitext in `wikitext` as though it were the contents of the page `title`,
    /// returning the rendered HTML.
    pub fn parse_wikitext(&self, title: &str, wikitext: &str) -> Result<String, String> {
        let encoded_wikitext =
            percent_encoding::percent_encode(wikitext.as_bytes(), percent_encoding::QUERY_ENCODE_SET);
        let html = self.call_mediawiki_api(
            vec![("action", "parse"), ("prop", "text"), ("disablepp", ""), ("contentmodel", "wikitext"),
                 ("title", title), ("text", &encoded_wikitext)]);
        // TODO: check return value
        let json = Json::from_str(&html).unwrap();
        match json::get_json_string(&json, &[Key("parse"), Key("text"), Key("*")]) {
            Ok(contents) => Ok(contents.to_string()),
            Err(message) => Err(message),
        }
    }

    /// Gets the current, fully-rendered (**HTML**) contents of the page `title`.
    pub fn get_current_page_content(title: &str) -> String {
        // TODO: should this struct be keeping a Client instead of creating new ones for each method
        // call, here and in call_mediawiki_api?
        let client = Client::new();
        let mut res = client.get(
            &format!("https://en.wikipedia.org/wiki/{}", title))
            .header(Connection::close())
            .send().unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        body
    }
}
<commit_msg>Return a Result from call_mediawiki_api.<commit_after>use std::io::Read;

use hyper::Client;
use hyper::header::Connection;
use rustc_serialize::json::Json;
use url::percent_encoding;

use ::json;
use ::json::JsonPathElement::{Key, Only};

pub struct Wiki {
    hostname: String,
}

#[derive(Clone)]
pub struct Revision {
    pub revid: u64,
    pub parentid: u64,
    pub comment: String,
}

impl Wiki {
    /// Constructs a Wiki object representing the wiki at `hostname` (e.g. "en.wikipedia.org").
    pub fn new(hostname: &str) -> Wiki {
        Wiki { hostname: hostname.to_string() }
    }

    /// Calls the MediaWiki API with the given parameters and format=json. Returns the raw JSON.
    fn call_mediawiki_api(&self, parameters: Vec<(&str, &str)>) -> Result<String, String> {
        let post_body =
            parameters.into_iter().map(|p| format!("{}={}", p.0, p.1))
            .collect::<Vec<_>>().join("&") + "&format=json";

        let client = Client::new();
        let mut response = client.post(&format!("https://{}/w/api.php", self.hostname))
            .body(&post_body)
            .header(Connection::close())
            .send().unwrap();

        let mut body = String::new();
        response.read_to_string(&mut body).unwrap();
        Ok(body)
    }

    /// Returns the last `limit` revisions for the page `title`.
    pub fn get_revisions(&self, title: &str, limit: u64) -> Result<Vec<Revision>, String> {
        let json_str = self.call_mediawiki_api(
            vec![("action", "query"), ("prop", "revisions"), ("titles", title),
                 ("rvprop", "comment|ids"), ("rvlimit", &limit.to_string())]).unwrap();
        let json = Json::from_str(&json_str).unwrap();
        let revisions = try!(
            json::get_json_array(&json, &[Key("query"), Key("pages"), Only, Key("revisions")]));

        // Check that  all revisions have revid and parentid (they all should).
        // TODO: what about making a Vec<Result<Revision>, String> and then rolling that up with a fold()? Would eliminate the repetition of the get_json_* calls.
        if revisions.into_iter().any(|revision| {
            json::get_json_number(revision, &[Key("revid")]).is_err() ||
            json::get_json_number(revision, &[Key("parentid")]).is_err() ||
            json::get_json_string(revision, &[Key("comment")]).is_err()
        }) {
            Err(format!(
                "One or more revisions of page \"{}\" have missing or invalid field", title))
        } else {
            Ok(revisions.into_iter().map(|revision| {
                Revision {
                    revid: json::get_json_number(revision, &[Key("revid")]).unwrap(),
                    parentid: json::get_json_number(revision, &[Key("parentid")]).unwrap(),
                    comment: json::get_json_string(revision, &[Key("comment")]).unwrap().to_string()
                }
            }).collect())
        }
    }

    /// Returns the latest revision ID for the page `title`.
    pub fn get_latest_revision(&self, title: &str) -> Result<Revision, String> {
        // TODO: Can this be a one-liner? Does try!() work properly like that?
        let revisions = try!(self.get_revisions(title, 1));
        Ok(revisions[0].clone())
    }

    /// Returns the contents of the page `title` as of (i.e., immediately after) revision `id`.
    pub fn get_revision_content(&self, title: &str, id: u64) -> Result<String, String> {
        let json_str = self.call_mediawiki_api(
            vec![("action", "query"), ("prop", "revisions"), ("titles", title), ("rvprop", "content"),
                 ("rvlimit", "1"), ("rvstartid", &id.to_string())]).unwrap();
        let json = Json::from_str(&json_str).unwrap();
        match json::get_json_string(
            &json, &[Key("query"), Key("pages"), Only, Key("revisions"), Only, Key("*")]) {
            Ok(content) => Ok(content.to_string()),
            Err(msg) => Err(msg),
        }
    }

    /// Follows all redirects to find the canonical name of the page at `title`.
    pub fn get_canonical_title(&self, title: &str) -> Result<String, String> {
        let latest_revision_id = self.get_latest_revision(title).unwrap().revid;
        let page_contents = self.get_revision_content(title, latest_revision_id).unwrap();

        let regex = regex!(r"#REDIRECT \[\[([^]]+)\]\].*");
        match regex.captures(&page_contents) {
            Some(captures) => self.get_canonical_title(captures.at(1).unwrap()),
            None => {
                println!("Canonical page title is \"{}\"", title);
                Ok(title.to_string())
            },
        }
    }

    /// Parses the wikitext in `wikitext` as though it were the contents of the page `title`,
    /// returning the rendered HTML.
    pub fn parse_wikitext(&self, title: &str, wikitext: &str) -> Result<String, String> {
        let encoded_wikitext =
            percent_encoding::percent_encode(wikitext.as_bytes(), percent_encoding::QUERY_ENCODE_SET);
        let html = self.call_mediawiki_api(
            vec![("action", "parse"), ("prop", "text"), ("disablepp", ""), ("contentmodel", "wikitext"),
                 ("title", title), ("text", &encoded_wikitext)]).unwrap();
        // TODO: check return value
        let json = Json::from_str(&html).unwrap();
        match json::get_json_string(&json, &[Key("parse"), Key("text"), Key("*")]) {
            Ok(contents) => Ok(contents.to_string()),
            Err(message) => Err(message),
        }
    }

    /// Gets the current, fully-rendered (**HTML**) contents of the page `title`.
    pub fn get_current_page_content(title: &str) -> String {
        // TODO: should this struct be keeping a Client instead of creating new ones for each method
        // call, here and in call_mediawiki_api?
        let client = Client::new();
        let mut res = client.get(
            &format!("https://en.wikipedia.org/wiki/{}", title))
            .header(Connection::close())
            .send().unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        body
    }
}
<|endoftext|>


<commit_before>//! `core_arch`

#[macro_use]
mod macros;

#[cfg(any(target_arch = "arm", target_arch = "aarch64", dox))]
mod acle;

mod simd;

#[cfg_attr(
    not(core_arch_docs),
    doc(include = "../stdsimd/crates/core_arch/src/core_arch_docs.md")
)]
#[cfg_attr(core_arch_docs, doc(include = "core_arch_docs.md"))]
#[stable(feature = "simd_arch", since = "1.27.0")]
pub mod arch {
    /// Platform-specific intrinsics for the `x86` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "x86", dox))]
    #[doc(cfg(target_arch = "x86"))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub mod x86 {
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86::*;
    }

    /// Platform-specific intrinsics for the `x86_64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "x86_64", dox))]
    #[doc(cfg(target_arch = "x86_64"))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub mod x86_64 {
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86::*;
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86_64::*;
    }

    /// Platform-specific intrinsics for the `arm` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "arm", dox))]
    #[doc(cfg(target_arch = "arm"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod arm {
        pub use crate::core_arch::arm::*;
    }

    /// Platform-specific intrinsics for the `aarch64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "aarch64", dox))]
    #[doc(cfg(target_arch = "aarch64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod aarch64 {
        pub use crate::core_arch::{aarch64::*, arm::*};
    }

    /// Platform-specific intrinsics for the `wasm32` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "wasm32", dox))]
    #[doc(cfg(target_arch = "wasm32"))]
    #[stable(feature = "simd_wasm32", since = "1.33.0")]
    pub mod wasm32 {
        #[stable(feature = "simd_wasm32", since = "1.33.0")]
        pub use crate::core_arch::wasm32::*;
    }

    /// Platform-specific intrinsics for the `mips` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "mips", dox))]
    #[doc(cfg(target_arch = "mips"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod mips {
        pub use crate::core_arch::mips::*;
    }

    /// Platform-specific intrinsics for the `mips64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "mips64", dox))]
    #[doc(cfg(target_arch = "mips64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod mips64 {
        pub use crate::core_arch::mips::*;
    }

    /// Platform-specific intrinsics for the `PowerPC` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "powerpc", dox))]
    #[doc(cfg(target_arch = "powerpc"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod powerpc {
        pub use crate::core_arch::powerpc::*;
    }

    /// Platform-specific intrinsics for the `PowerPC64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "powerpc64", dox))]
    #[doc(cfg(target_arch = "powerpc64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod powerpc64 {
        pub use crate::core_arch::powerpc64::*;
    }

    /// Platform-specific intrinsics for the `NVPTX` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64", dox))]
    #[doc(cfg(any(target_arch = "nvptx", target_arch = "nvptx64")))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod nvptx {
        pub use crate::core_arch::nvptx::*;
    }
}

mod simd_llvm;

#[cfg(any(target_arch = "x86", target_arch = "x86_64", dox))]
#[doc(cfg(any(target_arch = "x86", target_arch = "x86_64")))]
mod x86;
#[cfg(any(target_arch = "x86_64", dox))]
#[doc(cfg(target_arch = "x86_64"))]
mod x86_64;

#[cfg(any(target_arch = "aarch64", dox))]
#[doc(cfg(target_arch = "aarch64"))]
mod aarch64;
#[cfg(any(target_arch = "arm", target_arch = "aarch64", dox))]
#[doc(cfg(any(target_arch = "arm", target_arch = "aarch64")))]
mod arm;

#[cfg(any(target_arch = "wasm32", dox))]
#[doc(cfg(target_arch = "wasm32"))]
mod wasm32;

#[cfg(any(target_arch = "mips", target_arch = "mips64", dox))]
#[doc(cfg(any(target_arch = "mips", target_arch = "mips64")))]
mod mips;

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64", dox))]
#[doc(cfg(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod powerpc;

#[cfg(any(target_arch = "powerpc64", dox))]
#[doc(cfg(target_arch = "powerpc64"))]
mod powerpc64;

#[cfg(any(target_arch = "nvptx", target_arch = "nvptx64", dox))]
#[doc(cfg(any(target_arch = "nvptx", target_arch = "nvptx64")))]
mod nvptx;
<commit_msg>Adjust #[doc(include)] paths for rustdoc change<commit_after>//! `core_arch`

#[macro_use]
mod macros;

#[cfg(any(target_arch = "arm", target_arch = "aarch64", dox))]
mod acle;

mod simd;

#[cfg_attr(
    bootstrap,
    doc(include = "../stdsimd/crates/core_arch/src/core_arch_docs.md")
)]
#[cfg_attr(not(bootstrap), doc(include = "core_arch_docs.md"))]
#[stable(feature = "simd_arch", since = "1.27.0")]
pub mod arch {
    /// Platform-specific intrinsics for the `x86` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "x86", dox))]
    #[doc(cfg(target_arch = "x86"))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub mod x86 {
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86::*;
    }

    /// Platform-specific intrinsics for the `x86_64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "x86_64", dox))]
    #[doc(cfg(target_arch = "x86_64"))]
    #[stable(feature = "simd_x86", since = "1.27.0")]
    pub mod x86_64 {
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86::*;
        #[stable(feature = "simd_x86", since = "1.27.0")]
        pub use crate::core_arch::x86_64::*;
    }

    /// Platform-specific intrinsics for the `arm` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "arm", dox))]
    #[doc(cfg(target_arch = "arm"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod arm {
        pub use crate::core_arch::arm::*;
    }

    /// Platform-specific intrinsics for the `aarch64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "aarch64", dox))]
    #[doc(cfg(target_arch = "aarch64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod aarch64 {
        pub use crate::core_arch::{aarch64::*, arm::*};
    }

    /// Platform-specific intrinsics for the `wasm32` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "wasm32", dox))]
    #[doc(cfg(target_arch = "wasm32"))]
    #[stable(feature = "simd_wasm32", since = "1.33.0")]
    pub mod wasm32 {
        #[stable(feature = "simd_wasm32", since = "1.33.0")]
        pub use crate::core_arch::wasm32::*;
    }

    /// Platform-specific intrinsics for the `mips` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "mips", dox))]
    #[doc(cfg(target_arch = "mips"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod mips {
        pub use crate::core_arch::mips::*;
    }

    /// Platform-specific intrinsics for the `mips64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "mips64", dox))]
    #[doc(cfg(target_arch = "mips64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod mips64 {
        pub use crate::core_arch::mips::*;
    }

    /// Platform-specific intrinsics for the `PowerPC` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "powerpc", dox))]
    #[doc(cfg(target_arch = "powerpc"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod powerpc {
        pub use crate::core_arch::powerpc::*;
    }

    /// Platform-specific intrinsics for the `PowerPC64` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "powerpc64", dox))]
    #[doc(cfg(target_arch = "powerpc64"))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod powerpc64 {
        pub use crate::core_arch::powerpc64::*;
    }

    /// Platform-specific intrinsics for the `NVPTX` platform.
    ///
    /// See the [module documentation](../index.html) for more details.
    #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64", dox))]
    #[doc(cfg(any(target_arch = "nvptx", target_arch = "nvptx64")))]
    #[unstable(feature = "stdsimd", issue = "27731")]
    pub mod nvptx {
        pub use crate::core_arch::nvptx::*;
    }
}

mod simd_llvm;

#[cfg(any(target_arch = "x86", target_arch = "x86_64", dox))]
#[doc(cfg(any(target_arch = "x86", target_arch = "x86_64")))]
mod x86;
#[cfg(any(target_arch = "x86_64", dox))]
#[doc(cfg(target_arch = "x86_64"))]
mod x86_64;

#[cfg(any(target_arch = "aarch64", dox))]
#[doc(cfg(target_arch = "aarch64"))]
mod aarch64;
#[cfg(any(target_arch = "arm", target_arch = "aarch64", dox))]
#[doc(cfg(any(target_arch = "arm", target_arch = "aarch64")))]
mod arm;

#[cfg(any(target_arch = "wasm32", dox))]
#[doc(cfg(target_arch = "wasm32"))]
mod wasm32;

#[cfg(any(target_arch = "mips", target_arch = "mips64", dox))]
#[doc(cfg(any(target_arch = "mips", target_arch = "mips64")))]
mod mips;

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64", dox))]
#[doc(cfg(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod powerpc;

#[cfg(any(target_arch = "powerpc64", dox))]
#[doc(cfg(target_arch = "powerpc64"))]
mod powerpc64;

#[cfg(any(target_arch = "nvptx", target_arch = "nvptx64", dox))]
#[doc(cfg(any(target_arch = "nvptx", target_arch = "nvptx64")))]
mod nvptx;
<|endoftext|>


<commit_before>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::net::{ToSocketAddrs, SocketAddr};
#[cfg(feature = "ssl")]
use std::path::PathBuf;

pub use hyper::server::Listening;
use hyper::server::Server;
use hyper::net::Fresh;

use request::HttpRequest;
use response::HttpResponse;

use error::HttpResult;

use {Request, Handler};
use status;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// `Iron` contains the `Handler` which takes a `Request` and produces a
/// `Response`.
pub struct Iron<H> {
    /// Iron contains a `Handler`, which it uses to create responses for client
    /// requests.
    pub handler: H,

    /// Once listening, the local address that this server is bound to.
    pub addr: Option<SocketAddr>,

    /// Once listening, the protocol used to serve content.
    pub protocol: Option<Protocol>
}

/// Protocol used to serve content. Future versions of Iron may add new protocols
/// to this enum. Thus you should not exhaustively match on its variants.
#[derive(Clone)]
pub enum Protocol {
    /// Plaintext HTTP/1
    Http,
    /// HTTP/1 over SSL/TLS
    #[cfg(feature = "ssl")]
    Https {
        /// Path to SSL certificate file
        certificate: PathBuf,
        /// Path to SSL private key file
        key: PathBuf
    }
}

impl Protocol {
    /// Return the name used for this protocol in a URI's scheme part.
    pub fn name(&self) -> &'static str {
        match *self {
            Protocol::Http => "http",
            #[cfg(feature = "ssl")]
            Protocol::Https { .. } => "https"
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process using the HTTP protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// The thread returns a guard that will automatically join with the parent
    /// once it is dropped, blocking until this happens.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn http<A: ToSocketAddrs>(self, addr: A) -> HttpResult<Listening> {
        self.listen_with(addr, 2 * ::num_cpus::get(), Protocol::Http)
    }

    /// Kick off the server process using the HTTPS protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// The thread returns a guard that will automatically join with the parent
    /// once it is dropped, blocking until this happens.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    #[cfg(feature = "ssl")]
    pub fn https<A: ToSocketAddrs>(self, addr: A, certificate: PathBuf, key: PathBuf)
                                   -> HttpResult<Listening> {
        self.listen_with(addr, 2 * ::num_cpus::get(),
                         Protocol::Https { certificate: certificate, key: key })
    }

    /// Kick off the server process with X threads.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn listen_with<A: ToSocketAddrs>(mut self, addr: A, threads: usize,
                                         protocol: Protocol) -> HttpResult<Listening> {
        let sock_addr = addr.to_socket_addrs()
            .ok().and_then(|mut addrs| addrs.next()).expect("Could not parse socket address.");

        self.addr = Some(sock_addr);

        self.protocol = Some(protocol.clone());

        match protocol {
            Protocol::Http => try!(Server::http(sock_addr)).handle_threads(self, threads),

            #[cfg(feature = "ssl")]
            Protocol::Https { ref certificate, ref key } => {
                use hyper::net::Openssl;

                try!(Server::https(sock_addr,
                                   try!(Openssl::with_cert_and_key(certificate, key))))
                    .handle_threads(self, threads)
            },
        }
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server, using the
    /// passed in `Handler`.
    pub fn new(handler: H) -> Iron<H> {
        Iron { handler: handler, addr: None, protocol: None }
    }

    fn bad_request(&self, mut http_res: HttpResponse<Fresh>) {
        *http_res.status_mut() = status::BadRequest;

        let http_res = match http_res.start() {
            Ok(res) => res,
            // Would like this to work, but if not *shrug*
            Err(_) => return,
        };

        // We would like this to work, but can't do anything if it doesn't.
        let _ = http_res.end();
    }
}

impl<H: Handler> ::hyper::server::Handler for Iron<H> {
    fn handle(&self, http_req: HttpRequest, http_res: HttpResponse<Fresh>) {
        // Create `Request` wrapper.
        let mut req = match Request::from_http(http_req, self.addr.clone().unwrap(),
                                               self.protocol.as_ref().unwrap()) {
            Ok(req) => req,
            Err(e) => {
                error!("Error creating request:\n    {}", e);
                return self.bad_request(http_res);
            }
        };

        // Dispatch the request
        let res = self.handler.handle(&mut req);

        match res {
            // Write the response back to http_res
            Ok(res) => res.write_back(http_res),
            Err(e) => {
                error!("Error handling:\n{:?}\nError was: {:?}", req, e.error);
                e.response.write_back(http_res);
            }
        }
    }
}

<commit_msg>(refactor) iron.rs<commit_after>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::net::{ToSocketAddrs, SocketAddr};
#[cfg(feature = "ssl")]
use std::path::PathBuf;

pub use hyper::server::Listening;
use hyper::server::Server;
use hyper::net::Fresh;

use request::HttpRequest;
use response::HttpResponse;

use error::HttpResult;

use {Request, Handler};
use status;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// `Iron` contains the `Handler` which takes a `Request` and produces a
/// `Response`.
pub struct Iron<H> {
    /// Iron contains a `Handler`, which it uses to create responses for client
    /// requests.
    pub handler: H,

    /// Once listening, the local address that this server is bound to.
    pub addr: Option<SocketAddr>,

    /// Once listening, the protocol used to serve content.
    pub protocol: Option<Protocol>
}

/// Protocol used to serve content. Future versions of Iron may add new protocols
/// to this enum. Thus you should not exhaustively match on its variants.
#[derive(Clone)]
pub enum Protocol {
    /// Plaintext HTTP/1
    Http,
    /// HTTP/1 over SSL/TLS
    #[cfg(feature = "ssl")]
    Https {
        /// Path to SSL certificate file
        certificate: PathBuf,
        /// Path to SSL private key file
        key: PathBuf
    }
}

impl Protocol {
    /// Return the name used for this protocol in a URI's scheme part.
    pub fn name(&self) -> &'static str {
        match *self {
            Protocol::Http => "http",
            #[cfg(feature = "ssl")]
            Protocol::Https { .. } => "https"
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process using the HTTP protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// The thread returns a guard that will automatically join with the parent
    /// once it is dropped, blocking until this happens.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn http<A: ToSocketAddrs>(self, addr: A) -> HttpResult<Listening> {
        self.listen_with(addr, 2 * ::num_cpus::get(), Protocol::Http)
    }

    /// Kick off the server process using the HTTPS protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// The thread returns a guard that will automatically join with the parent
    /// once it is dropped, blocking until this happens.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    #[cfg(feature = "ssl")]
    pub fn https<A: ToSocketAddrs>(self, addr: A, certificate: PathBuf, key: PathBuf)
                                   -> HttpResult<Listening> {
        self.listen_with(addr, 2 * ::num_cpus::get(),
                         Protocol::Https { certificate: certificate, key: key })
    }

    /// Kick off the server process with X threads.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn listen_with<A: ToSocketAddrs>(mut self, addr: A, threads: usize,
                                         protocol: Protocol) -> HttpResult<Listening> {
        let sock_addr = addr.to_socket_addrs()
            .ok().and_then(|mut addrs| addrs.next()).expect("Could not parse socket address.");

        self.addr = Some(sock_addr);

        self.protocol = Some(protocol.clone());

        match protocol {
            Protocol::Http => try!(Server::http(sock_addr)).handle_threads(self, threads),

            #[cfg(feature = "ssl")]
            Protocol::Https { ref certificate, ref key } => {
                use hyper::net::Openssl;

                try!(Server::https(sock_addr,
                                   try!(Openssl::with_cert_and_key(certificate, key))))
                    .handle_threads(self, threads)
            }
        }
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server, using the
    /// passed in `Handler`.
    pub fn new(handler: H) -> Iron<H> {
        Iron { handler: handler, addr: None, protocol: None }
    }

    fn bad_request(&self, mut http_res: HttpResponse<Fresh>) {
        *http_res.status_mut() = status::BadRequest;

        // Consume and flush the response.
        // We would like this to work, but can't do anything if it doesn't.
        if let Ok(res) = http_res.start()
        {
            let _ = res.end();
        }
    }
}

impl<H: Handler> ::hyper::server::Handler for Iron<H> {
    fn handle(&self, http_req: HttpRequest, http_res: HttpResponse<Fresh>) {
        // Create `Request` wrapper.
        match Request::from_http(http_req, self.addr.clone().unwrap(),
                                 self.protocol.as_ref().unwrap()) {
            Ok(mut req) => {
                // Dispatch the request, write the response back to http_res
                self.handler.handle(&mut req).unwrap_or_else(|e| {
                    error!("Error handling:\n{:?}\nError was: {:?}", req, e.error);
                    e.response
                }).write_back(http_res)
            },
            Err(e) => {
                error!("Error creating request:\n    {}", e);
                self.bad_request(http_res)
            }
        }
    }
}
<|endoftext|>


<commit_before>use libmodbus::{Modbus, ModbusRTU, RequestToSendMode, SerialMode};

#[test]
fn new_rtu_context() {
    assert!(Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).is_ok());
}

#[test]
#[ignore]
fn rtu_get_serial_mode() {
    #[cfg(target_os = "unix")]
    let modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();

    assert_eq!(modbus.rtu_get_serial_mode().unwrap(), SerialMode::RtuRS232);
}

#[test]
#[ignore]
// FIXME: Why is serial mode RS485 not possible?
fn rtu_set_serial_mode() {
    #[cfg(target_os = "unix")]
    let modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();

    assert_eq!(modbus.rtu_get_serial_mode().unwrap(), SerialMode::RtuRS232);
    // assert!(modbus.rtu_set_serial_mode(SerialMode::RtuRS485).is_ok());
    // assert_eq!(modbus.rtu_get_serial_mode().unwrap(), SerialMode::RtuRS485);
}

#[test]
#[ignore]
fn rtu_get_rts() {
    let modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    assert_eq!(modbus.rtu_get_rts().unwrap(), RequestToSendMode::RtuRtsNone);
}

#[test]
#[ignore]
fn rtu_set_rts() {
    #[cfg(target_os = "unix")]
    let mut modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let mut modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();

    // before
    assert_eq!(modbus.rtu_get_rts().unwrap(), RequestToSendMode::RtuRtsNone);
    // set rts mode
    assert!(modbus.rtu_set_rts(RequestToSendMode::RtuRtsUp).is_ok());
    // after set rts mode
    assert_eq!(modbus.rtu_get_rts().unwrap(), RequestToSendMode::RtuRtsUp);
}

#[test]
#[ignore]
fn rtu_set_custom_rts() {
    #[cfg(target_os = "unix")]
    let _modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let _modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();
    // function pointer via ffi ???
}

#[test]
#[ignore]
fn rtu_get_rts_delay() {
    #[cfg(target_os = "unix")]
    let modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();

    assert_eq!(modbus.rtu_get_rts_delay().unwrap(), 86);
}

#[test]
#[ignore]
fn rtu_set_rts_delay() {
    #[cfg(target_os = "unix")]
    let mut modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let mut modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();
    assert_eq!(modbus.rtu_get_rts_delay().unwrap(), 86);
    assert!(modbus.rtu_set_rts_delay(100).is_ok());
    assert_eq!(modbus.rtu_get_rts_delay().unwrap(), 100);
}
<commit_msg>Fix wrong cfg flag<commit_after>use libmodbus::{Modbus, ModbusRTU, RequestToSendMode, SerialMode};

#[test]
fn new_rtu_context() {
    assert!(Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).is_ok());
}

#[test]
#[ignore]
fn rtu_get_serial_mode() {
    #[cfg(target_os = "linux")]
    let modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();

    assert_eq!(modbus.rtu_get_serial_mode().unwrap(), SerialMode::RtuRS232);
}

#[test]
#[ignore]
// FIXME: Why is serial mode RS485 not possible?
fn rtu_set_serial_mode() {
    #[cfg(target_os = "linux")]
    let modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();

    assert_eq!(modbus.rtu_get_serial_mode().unwrap(), SerialMode::RtuRS232);
    // assert!(modbus.rtu_set_serial_mode(SerialMode::RtuRS485).is_ok());
    // assert_eq!(modbus.rtu_get_serial_mode().unwrap(), SerialMode::RtuRS485);
}

#[test]
#[ignore]
fn rtu_get_rts() {
    let modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    assert_eq!(modbus.rtu_get_rts().unwrap(), RequestToSendMode::RtuRtsNone);
}

#[test]
#[ignore]
fn rtu_set_rts() {
    #[cfg(target_os = "linux")]
    let mut modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let mut modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();

    // before
    assert_eq!(modbus.rtu_get_rts().unwrap(), RequestToSendMode::RtuRtsNone);
    // set rts mode
    assert!(modbus.rtu_set_rts(RequestToSendMode::RtuRtsUp).is_ok());
    // after set rts mode
    assert_eq!(modbus.rtu_get_rts().unwrap(), RequestToSendMode::RtuRtsUp);
}

#[test]
#[ignore]
fn rtu_set_custom_rts() {
    #[cfg(target_os = "linux")]
    let _modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let _modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();
    // function pointer via ffi ???
}

#[test]
#[ignore]
fn rtu_get_rts_delay() {
    #[cfg(target_os = "linux")]
    let modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();

    assert_eq!(modbus.rtu_get_rts_delay().unwrap(), 86);
}

#[test]
#[ignore]
fn rtu_set_rts_delay() {
    #[cfg(target_os = "linux")]
    let mut modbus = Modbus::new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1).unwrap();
    #[cfg(target_os = "windows")]
    let mut modbus = Modbus::new_rtu("COM2", 115200, 'N', 8, 1).unwrap();
    assert_eq!(modbus.rtu_get_rts_delay().unwrap(), 86);
    assert!(modbus.rtu_set_rts_delay(100).is_ok());
    assert_eq!(modbus.rtu_get_rts_delay().unwrap(), 100);
}
<|endoftext|>


<commit_before>use std::ffi::CStr;
use std::marker::PhantomData;

use llvm_sys::prelude::*;
use llvm_sys::core::*;

use id::{Id, IdRef};

pub struct Context<'cid> {
    _id: Id<'cid>,
    llvm_context: LLVMContextRef
}

impl<'cid> Drop for Context<'cid> {
   fn drop(&mut self) {
       unsafe {
           LLVMContextDispose(self.llvm_context);
       }
   }
}

impl<'cid> Context<'cid> {
    pub fn new(id: Id<'cid>) -> Context<'cid> {
        Context {
            _id: id,
            llvm_context: unsafe { LLVMContextCreate() }
        }
    }
}

pub struct Module<'cid: 'context, 'context, 'mid> {
    _context: PhantomData<&'context Context<'cid>>,
    _id: Id<'mid>,
    llvm_module: LLVMModuleRef
}

impl<'cid, 'context, 'mid> Drop for Module<'cid, 'context, 'mid> {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeModule(self.llvm_module);
        }
    }
}

impl<'cid, 'context, 'mid> Module<'cid, 'context, 'mid> {
    pub fn new(id: Id<'mid>, name: &CStr, context: &'context Context<'cid>) -> Module<'cid, 'context, 'mid> {
        Module {
            _context: PhantomData,
            _id: id,
            llvm_module: unsafe { LLVMModuleCreateWithNameInContext(name.as_ptr(), context.llvm_context) }
        }
    }

    pub fn add_function<'module, 'fid>(&'module self, id: Id<'fid>, name: &CStr, ty: Type<'cid>) -> Function<'cid, 'mid, 'module, 'fid> {
        Function {
            _context_id: IdRef::new(),
            _module_id: IdRef::new(),
            _module: PhantomData,
            _id: id,
            llvm_function: unsafe { LLVMAddFunction(self.llvm_module, name.as_ptr(), ty.llvm_type) }
        }
    }
}

#[derive(Copy, Clone)]
pub struct Type<'cid> {
    _context_id: IdRef<'cid>,
    llvm_type: LLVMTypeRef
}

impl<'cid> Type<'cid> {
    pub fn f64(context: &Context<'cid>) -> Type<'cid> {
       Type {
           _context_id: IdRef::new(),
           llvm_type: unsafe { LLVMDoubleTypeInContext(context.llvm_context) }
       }
    }

    pub fn function(params: &[Type<'cid>], ret: Type<'cid>) -> Type<'cid> {
        Type {
            _context_id: IdRef::new(),
            // FIXME: actually enforce that Type and LLVMTypeRef are the same in memory
            llvm_type: unsafe { LLVMFunctionType(ret.llvm_type, params.as_ptr() as *mut LLVMTypeRef, params.len() as u32, 0) }
        }
    }
}

pub struct Builder<'cid> {
    _context_id: IdRef<'cid>,
    llvm_builder: LLVMBuilderRef
}

impl<'cid> Drop for Builder<'cid> {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeBuilder(self.llvm_builder);
        }
    }
}

impl<'cid> Builder<'cid> {
    pub fn new(context: &Context<'cid>) -> Builder<'cid> {
        Builder {
            _context_id: IdRef::new(),
            llvm_builder: unsafe { LLVMCreateBuilderInContext(context.llvm_context) }
        }
    }

    pub fn position_at_end<'fid, 'function, 'builder>(&'builder mut self, block: BasicBlock<'cid, 'fid, 'function>) -> PositionedBuilder<'cid, 'fid, 'function, 'builder> {
        unsafe {
            LLVMPositionBuilderAtEnd(self.llvm_builder, block.llvm_basic_block);
        }
        PositionedBuilder {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            _builder: PhantomData,
            llvm_builder: self.llvm_builder
        }
    }
}

pub struct PositionedBuilder<'cid: 'builder, 'fid, 'function, 'builder> {
    _context_id: IdRef<'cid>,
    _function_id: IdRef<'fid>,
    _function: PhantomData<&'function ()>,
    _builder: PhantomData<&'builder mut Builder<'cid>>,
    llvm_builder: LLVMBuilderRef
}

impl<'cid: 'builder, 'fid, 'function, 'builder> PositionedBuilder<'cid, 'fid, 'function, 'builder> {
    pub fn build_br(&self, target: BasicBlock<'cid, 'fid, 'function>) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildBr(self.llvm_builder, target.llvm_basic_block) }
        }
    }

    pub fn build_or(&self, lhs: Value<'cid, 'fid, 'function>, rhs: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildOr(self.llvm_builder, lhs.llvm_value, rhs.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_add(&self, lhs: Value<'cid, 'fid, 'function>, rhs: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildAdd(self.llvm_builder, lhs.llvm_value, rhs.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_and(&self, lhs: Value<'cid, 'fid, 'function>, rhs: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildAnd(self.llvm_builder, lhs.llvm_value, rhs.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_mul(&self, lhs: Value<'cid, 'fid, 'function>, rhs: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildMul(self.llvm_builder, lhs.llvm_value, rhs.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_neg(&self, value: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildNeg(self.llvm_builder, value.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_not(&self, value: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildNot(self.llvm_builder, value.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_ret(&self, value: Value<'cid, 'fid, 'function>) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildRet(self.llvm_builder, value.llvm_value) }
        }
    }
}

pub struct Function<'cid, 'mid: 'module, 'module, 'fid> {
    _context_id: IdRef<'cid>,
    _module_id: IdRef<'mid>,
    _module: PhantomData<&'module ()>,
    _id: Id<'fid>,
    llvm_function: LLVMValueRef
}

impl<'cid, 'mid: 'module, 'module, 'fid> Function<'cid, 'mid, 'module, 'fid> {
    pub fn append_basic_block<'function>(&'function self, name: &CStr, context: &Context<'cid>) -> BasicBlock<'cid, 'fid, 'function> {
        BasicBlock {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_basic_block: unsafe { LLVMAppendBasicBlockInContext(context.llvm_context, self.llvm_function, name.as_ptr()) }
        }
    }

    pub fn param<'function>(&'function self, index: u32) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMGetParam(self.llvm_function, index) }
        }
    }

    pub fn dump(&self) {
        unsafe {
            LLVMDumpValue(self.llvm_function);
        }
    }
}

#[derive(Copy, Clone)]
pub struct BasicBlock<'cid, 'fid, 'function> {
    _context_id: IdRef<'cid>,
    _function_id: IdRef<'fid>,
    _function: PhantomData<&'function ()>,
    llvm_basic_block: LLVMBasicBlockRef
}

#[derive(Copy, Clone)]
pub struct Value<'cid, 'fid, 'function> {
    _context_id: IdRef<'cid>,
    _function_id: IdRef<'fid>,
    _function: PhantomData<&'function ()>,
    llvm_value: LLVMValueRef
}
<commit_msg>Add some TODOs to the LLVM wrapper<commit_after>use std::ffi::CStr;
use std::marker::PhantomData;

use llvm_sys::prelude::*;
use llvm_sys::core::*;

use id::{Id, IdRef};

//
// TODO: Error Checking
//   This is currently a safety hole.
//
// TODO: Reduce the number of lifetimes.
//   It isn't completely clear that this is possible, but this is a first attempt.
//
// TODO: Docs
//
// TODO: See what safety guarentees LLVM actually needs.
//   The official LLVM docs aren't very clear on, e.g., when different contexts/modules/function/builders
//   can be mixed, or what things can outlive other things.
//
// TODO: Consider wrapping the C++ API in another way.
//   The official wrapper is useful, since it requires no effort and is maintained by LLVM. However,
//   it has a number of annoying issues. For example, given the similarity between LLVM's Twine and Rust's
//   &str, there should be no reason to use CStr.
//
// TODO: Missing functionality
//

pub struct Context<'cid> {
    _id: Id<'cid>,
    llvm_context: LLVMContextRef
}

impl<'cid> Drop for Context<'cid> {
   fn drop(&mut self) {
       unsafe {
           LLVMContextDispose(self.llvm_context);
       }
   }
}

impl<'cid> Context<'cid> {
    pub fn new(id: Id<'cid>) -> Context<'cid> {
        Context {
            _id: id,
            llvm_context: unsafe { LLVMContextCreate() }
        }
    }
}

pub struct Module<'cid: 'context, 'context, 'mid> {
    _context: PhantomData<&'context Context<'cid>>,
    _id: Id<'mid>,
    llvm_module: LLVMModuleRef
}

impl<'cid, 'context, 'mid> Drop for Module<'cid, 'context, 'mid> {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeModule(self.llvm_module);
        }
    }
}

impl<'cid, 'context, 'mid> Module<'cid, 'context, 'mid> {
    pub fn new(id: Id<'mid>, name: &CStr, context: &'context Context<'cid>) -> Module<'cid, 'context, 'mid> {
        Module {
            _context: PhantomData,
            _id: id,
            llvm_module: unsafe { LLVMModuleCreateWithNameInContext(name.as_ptr(), context.llvm_context) }
        }
    }

    pub fn add_function<'module, 'fid>(&'module self, id: Id<'fid>, name: &CStr, ty: Type<'cid>) -> Function<'cid, 'mid, 'module, 'fid> {
        Function {
            _context_id: IdRef::new(),
            _module_id: IdRef::new(),
            _module: PhantomData,
            _id: id,
            llvm_function: unsafe { LLVMAddFunction(self.llvm_module, name.as_ptr(), ty.llvm_type) }
        }
    }
}

#[derive(Copy, Clone)]
pub struct Type<'cid> {
    _context_id: IdRef<'cid>,
    llvm_type: LLVMTypeRef
}

impl<'cid> Type<'cid> {
    pub fn f64(context: &Context<'cid>) -> Type<'cid> {
       Type {
           _context_id: IdRef::new(),
           llvm_type: unsafe { LLVMDoubleTypeInContext(context.llvm_context) }
       }
    }

    pub fn function(params: &[Type<'cid>], ret: Type<'cid>) -> Type<'cid> {
        Type {
            _context_id: IdRef::new(),
            // FIXME: actually enforce that Type and LLVMTypeRef are the same in memory
            llvm_type: unsafe { LLVMFunctionType(ret.llvm_type, params.as_ptr() as *mut LLVMTypeRef, params.len() as u32, 0) }
        }
    }
}

pub struct Builder<'cid> {
    _context_id: IdRef<'cid>,
    llvm_builder: LLVMBuilderRef
}

impl<'cid> Drop for Builder<'cid> {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeBuilder(self.llvm_builder);
        }
    }
}

impl<'cid> Builder<'cid> {
    pub fn new(context: &Context<'cid>) -> Builder<'cid> {
        Builder {
            _context_id: IdRef::new(),
            llvm_builder: unsafe { LLVMCreateBuilderInContext(context.llvm_context) }
        }
    }

    pub fn position_at_end<'fid, 'function, 'builder>(&'builder mut self, block: BasicBlock<'cid, 'fid, 'function>) -> PositionedBuilder<'cid, 'fid, 'function, 'builder> {
        unsafe {
            LLVMPositionBuilderAtEnd(self.llvm_builder, block.llvm_basic_block);
        }
        PositionedBuilder {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            _builder: PhantomData,
            llvm_builder: self.llvm_builder
        }
    }
}

pub struct PositionedBuilder<'cid: 'builder, 'fid, 'function, 'builder> {
    _context_id: IdRef<'cid>,
    _function_id: IdRef<'fid>,
    _function: PhantomData<&'function ()>,
    _builder: PhantomData<&'builder mut Builder<'cid>>,
    llvm_builder: LLVMBuilderRef
}

impl<'cid: 'builder, 'fid, 'function, 'builder> PositionedBuilder<'cid, 'fid, 'function, 'builder> {
    pub fn build_br(&self, target: BasicBlock<'cid, 'fid, 'function>) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildBr(self.llvm_builder, target.llvm_basic_block) }
        }
    }

    pub fn build_or(&self, lhs: Value<'cid, 'fid, 'function>, rhs: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildOr(self.llvm_builder, lhs.llvm_value, rhs.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_add(&self, lhs: Value<'cid, 'fid, 'function>, rhs: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildAdd(self.llvm_builder, lhs.llvm_value, rhs.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_and(&self, lhs: Value<'cid, 'fid, 'function>, rhs: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildAnd(self.llvm_builder, lhs.llvm_value, rhs.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_mul(&self, lhs: Value<'cid, 'fid, 'function>, rhs: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildMul(self.llvm_builder, lhs.llvm_value, rhs.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_neg(&self, value: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildNeg(self.llvm_builder, value.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_not(&self, value: Value<'cid, 'fid, 'function>, name: &CStr) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildNot(self.llvm_builder, value.llvm_value, name.as_ptr()) }
        }
    }

    pub fn build_ret(&self, value: Value<'cid, 'fid, 'function>) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMBuildRet(self.llvm_builder, value.llvm_value) }
        }
    }
}

pub struct Function<'cid, 'mid: 'module, 'module, 'fid> {
    _context_id: IdRef<'cid>,
    _module_id: IdRef<'mid>,
    _module: PhantomData<&'module ()>,
    _id: Id<'fid>,
    llvm_function: LLVMValueRef
}

impl<'cid, 'mid: 'module, 'module, 'fid> Function<'cid, 'mid, 'module, 'fid> {
    pub fn append_basic_block<'function>(&'function self, name: &CStr, context: &Context<'cid>) -> BasicBlock<'cid, 'fid, 'function> {
        BasicBlock {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_basic_block: unsafe { LLVMAppendBasicBlockInContext(context.llvm_context, self.llvm_function, name.as_ptr()) }
        }
    }

    pub fn param<'function>(&'function self, index: u32) -> Value<'cid, 'fid, 'function> {
        Value {
            _context_id: IdRef::new(),
            _function_id: IdRef::new(),
            _function: PhantomData,
            llvm_value: unsafe { LLVMGetParam(self.llvm_function, index) }
        }
    }

    pub fn dump(&self) {
        unsafe {
            LLVMDumpValue(self.llvm_function);
        }
    }
}

#[derive(Copy, Clone)]
pub struct BasicBlock<'cid, 'fid, 'function> {
    _context_id: IdRef<'cid>,
    _function_id: IdRef<'fid>,
    _function: PhantomData<&'function ()>,
    llvm_basic_block: LLVMBasicBlockRef
}

#[derive(Copy, Clone)]
pub struct Value<'cid, 'fid, 'function> {
    _context_id: IdRef<'cid>,
    _function_id: IdRef<'fid>,
    _function: PhantomData<&'function ()>,
    llvm_value: LLVMValueRef
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;

fn main() {
    print!("scalyc>");
    io::stdout().flush().unwrap();
    let mut card = String::new();
    io::stdin().read_line(&mut card).expect("failed to read line");
    println!("The card is {}", card);
}
<commit_msg>echo loop<commit_after>use std::io;
use std::io::Write;

fn main() {
    loop {
        print!("scalyc>");
        io::stdout().flush().unwrap();
        let mut card = String::new();
        io::stdin() .read_line(&mut card).expect("failed to read line");
        print!("{}", card);
    }
}
<|endoftext|>


<commit_before>struct Point {
	x: float,
	y: float
}

fn getSquareDistance(p1: Point, p2: Point) -> float {
	let dx : float = p1.x - p2.x;
	let dy : float = p1.y - p2.y;
	return dx * dx + dy * dy;
	}

fn getSquareSegmentDistance(p: Point, p1: Point, p2: Point) -> float {
	let mut dxy = Point { x: p2.x - p1.x, y: p2.y-p1.x};
	let mut xy : Point = Point { x: p1.x, y: p1.y};
	 if dxy.x != 0.0 && dxy.y != 0.0 {
		let t : float =((p.x - p1.x) * dxy.x + (p.y - p1.y) * dxy.y) / (dxy.y * dxy.y + dxy.y * dxy.y);
		if t>1.0 {
			 xy = p2;
		}else if t>0.0 {
			 xy = Point { x: dxy.x * t + p1.x,y: dxy.y * t + p1.y};
		}else{
			 xy  = Point { x: p1.x,y:  p1.y};
		}
	}
	dxy = Point {x: (p.x - xy.x), y: (p.y - xy.y)};
	return dxy.x * dxy.x + dxy.x * dxy.y;
}

fn main() {
	io::println(fmt!("%f",getSquareDistance(Point { x : 1.0, y: 1.0}, Point { x : 3.0, y : 3.0})));
}
<commit_msg>did simplifyRadialDistance<commit_after>struct Point {
	x: float,
	y: float
}

fn getSquareDistance(p1: Point, p2: Point) -> float {
	let dx : float = p1.x - p2.x;
	let dy : float = p1.y - p2.y;
	return dx * dx + dy * dy;
}

fn getSquareSegmentDistance(p: Point, p1: Point, p2: Point) -> float {
	let mut dxy = Point { x: p2.x - p1.x, y: p2.y-p1.x};
	let mut xy : Point = Point { x: p1.x, y: p1.y};
	 if dxy.x != 0.0 && dxy.y != 0.0 {
		let t : float =((p.x - p1.x) * dxy.x + (p.y - p1.y) * dxy.y) / (dxy.y * dxy.y + dxy.y * dxy.y);
		if t>1.0 {
			 xy = p2;
		}else if t>0.0 {
			 xy = Point { x: dxy.x * t + p1.x,y: dxy.y * t + p1.y};
		}else{
			 xy  = Point { x: p1.x,y:  p1.y};
		}
	}
	dxy = Point {x: (p.x - xy.x), y: (p.y - xy.y)};
	return dxy.x * dxy.x + dxy.x * dxy.y;
}
fn simplifyRadialDistance(points:~[Point], sqTolerance:float) -> ~[Point]{
	let mut i : uint = 1u;
	let len : uint = points.len();
	let mut prevPoint : Point = points[0u];
	let mut newPoints : ~[Point] = ~[prevPoint];
	let mut point : Point = points[i];
	loop {
		if (getSquareDistance(point, prevPoint) > sqTolerance) {
			newPoints.push(point);
			prevPoint = point;
		}
		i+=1;
		if (i < len) {
			point = points[i];
		}else{
			break;
		}
	}
	if (prevPoint.x != point.x && prevPoint.y != point.y) {
		newPoints.push(point);
	}
	return newPoints;
}

fn main() {
	io::println(fmt!("%f",getSquareDistance(Point { x : 1.0, y: 1.0}, Point { x : 3.0, y : 3.0})));
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate dotenv;
extern crate libc;

use std::{env, ptr, process};
use std::ffi::CString;
use libc::c_char;
use dotenv::{dotenv, DotenvError};

/// Literally taken from the libstd
/// (sys/unix/process.rs that is)
fn make_argv(prog: &CString, args: &[CString])
             -> *const *const libc::c_char
{
    let mut ptrs: Vec<*const libc::c_char> = Vec::with_capacity(args.len()+1);

    // Convert the CStrings into an array of pointers. Also return the
    // vector that owns the raw pointers, to ensure they live long
    // enough.
    ptrs.push(prog.as_ptr());
    ptrs.extend(args.iter().map(|tmp| {
        tmp.as_ptr()
    }));

    // Add a terminating null pointer (required by libc).
    ptrs.push(ptr::null());

    ptrs.as_ptr()
}

fn exec(prog: &str, args: &[String]) -> ! {
    let prog = CString::new(prog).expect("Convertable to CString");
    let args = args.iter()
        .map(|tmp| CString::new(&tmp[..]).expect("Convertable to CString"))
        .collect::<Vec<_>>();

    let argv = make_argv(&prog, &args);

    unsafe {
        let exit_code = libc::execv(*argv, argv);
        process::exit(exit_code);
    }
}

fn main() {
    env_logger::init().expect("Setup env_logger failed");

    info!("Loading dotenv");
    match dotenv() {
        Ok(()) => {},
        Err(DotenvError::Io) => {
            warn!("No dotenv file found. Skipping.");
        },
        Err(e) => {
            error!("Can't initialize dotenv.");
            error!("Error: {:?}", e);
            process::exit(1);
        }
    }

    let shell = env::var("SHELL").unwrap_or("/bin/sh".into());

    let args = env::args().skip(1).collect::<Vec<String>>();
    info!("args: {:?}", args);

    match args.len() {
        0 =>  {
            info!("Starting '{}' as shell", shell);
            exec(&shell, &[]);
        },
        _ => {
            let program = &args[0];
            info!("Starting '{}' with arguments: {:?}", program, &args[1..]);
            exec(program, &args[1..]);
        }
    }
}
<commit_msg>Let execvp handle the PATH-search for us<commit_after>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate dotenv;
extern crate libc;

use std::{env, ptr, process};
use std::ffi::CString;
use libc::c_char;
use dotenv::{dotenv, DotenvError};

/// Literally taken from the libstd
/// (sys/unix/process.rs that is)
fn make_argv(prog: &CString, args: &[CString])
             -> *const *const libc::c_char
{
    let mut ptrs: Vec<*const libc::c_char> = Vec::with_capacity(args.len()+1);

    // Convert the CStrings into an array of pointers. Also return the
    // vector that owns the raw pointers, to ensure they live long
    // enough.
    ptrs.push(prog.as_ptr());
    ptrs.extend(args.iter().map(|tmp| {
        tmp.as_ptr()
    }));

    // Add a terminating null pointer (required by libc).
    ptrs.push(ptr::null());

    ptrs.as_ptr()
}

fn exec(prog: &str, args: &[String]) -> ! {
    let prog = CString::new(prog).expect("Convertable to CString");
    let args = args.iter()
        .map(|tmp| CString::new(&tmp[..]).expect("Convertable to CString"))
        .collect::<Vec<_>>();

    let argv = make_argv(&prog, &args);

    unsafe {
        let exit_code = libc::execvp(*argv, argv);
        process::exit(exit_code);
    }
}

fn main() {
    env_logger::init().expect("Setup env_logger failed");

    info!("Loading dotenv");
    match dotenv() {
        Ok(()) => {},
        Err(DotenvError::Io) => {
            warn!("No dotenv file found. Skipping.");
        },
        Err(e) => {
            error!("Can't initialize dotenv.");
            error!("Error: {:?}", e);
            process::exit(1);
        }
    }

    let shell = env::var("SHELL").unwrap_or("/bin/sh".into());

    let args = env::args().skip(1).collect::<Vec<String>>();
    info!("args: {:?}", args);

    match args.len() {
        0 =>  {
            info!("Starting '{}' as shell", shell);
            exec(&shell, &[]);
        },
        _ => {
            let program = &args[0];
            info!("Starting '{}' with arguments: {:?}", program, &args[1..]);
            exec(program, &args[1..]);
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::clone::Clone;
use std::str::Lines;
use std::io::prelude::*;
use std::io::BufReader;
use std::fmt;

// Device Tree stucture
/*
struct DeviceTree<'a> {
	version: u32,
	boot_cpuid: u32,
	reserved_mem: Vec<(u64, u64)>,
	root: Node<'a, 'a>,
}

struct DeviceNode<'a, 'b> {
	name: String,
	props: Vec<(String, Property<'a>)>,
	children: Vec<DeviceNode<'b, 'b>>,
}

enum Property<'a> {
	Empty,
	Cells(Vec<u32>),
	String(String),
	ByteString(Vec<u8>),
	Combo(Vec<&'a Property<'a>>),
}
*/

// File tracking
#[derive(Debug)]
struct ParsedFile<'a> {
	path: &'a Path,
	file: File,
	method: IncludeMethod,
	included_files: Vec<ParsedFile<'a>>,
}

#[derive(Debug)]
enum IncludeMethod {
	DTS,
	CPP(File, Vec<FileMapping>),
}

#[derive(Debug, Clone, Copy)]
struct FileMapping {
	parent_start: usize,
	child_start: usize,
	len: usize,
}

#[derive(Debug)]
enum LinemarkerFlag {
	Start,
	Return,
	System,
	Extern,
}

// Change tracking
/*
struct Change<'a> {
	file: File,
	line: usize,
	// maybe point to node?
	name: String,
	value: Property<'a>,
}
*/

impl<'a> ParsedFile<'a> {
	fn new(path: &'a Path, method: IncludeMethod) -> ParsedFile<'a> {
		ParsedFile {
			path: path,
			file: File::open(path).unwrap(),
			method: method,
			included_files: vec![],
		}
	}

	fn assign_mapping(&mut self, path: &Path, mapping: FileMapping) -> Result<(), String> { //TODO: error propogation
		if self.path == path {
			match self.method {
				IncludeMethod::CPP(_, ref mut mappings) => mappings.push(mapping),
				IncludeMethod::DTS => unreachable!(),
			};
			Ok(())
		} else {
			for file in self.included_files.iter_mut() {
				if file.assign_mapping(path, mapping).is_ok() {
					return Ok(());
				}
			}
			Err(format!("Did not find file: {:?}", path))
		}
	}

	fn write(&self, f: &mut fmt::Formatter, prefix: &str) -> fmt::Result {
		let mut next_prefix = prefix.to_string();
		next_prefix.push_str(" |-");
		writeln!(f, "{} {:?}: {}", prefix, self.path, self.method)
			.and(self.included_files.iter().fold(Ok(()), |res, x| res.and(x.write(f, &next_prefix))))
	}
}

impl<'a> fmt::Display for ParsedFile<'a> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.write(f, "")
	}
}

impl fmt::Display for IncludeMethod {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			IncludeMethod::DTS => write!(f, "DTS"),
			IncludeMethod::CPP(_, _) => write!(f, "CPP"),
		}
	}
}

const CPP_OUTPUT_NAME: &'static str = "dts_viewer_tmp.dts";

fn main() {
	let file_name = match env::args().nth(1) {
		None => {
			println!("You forgot the dts file, you dummy");
			return;
		}
		Some(x) => x,
	};

	let arch = "arm";

	let dts_folder = PathBuf::from("arch").join(arch).join("boot/dts/");
	let file_path = dts_folder.join(file_name);

	let include_output = Command::new("arm-linux-gnueabi-gcc")
		.args(&["-H", "-E", "-nostdinc"])
		.args(&["-I", dts_folder.to_str().unwrap()])
		.args(&["-I", dts_folder.join("include/").to_str().unwrap()])
		.args(&["-undef", "-D__DTS__", "-x", "assembler-with-cpp"])
		.args(&["-o", CPP_OUTPUT_NAME])
		.arg(&file_path)
		.output()
		.expect("failed to execute process"); //TODO: properly handle errors

	let cpp_output = String::from_utf8_lossy(&include_output.stderr);
	println!("{}", cpp_output);

	let mut root_file = ParsedFile::new(&Path::new(&file_path),
										IncludeMethod::CPP(File::open(CPP_OUTPUT_NAME).unwrap(), vec![]));

	parse_cpp_output(&mut cpp_output.lines(), &mut root_file, 0);

	let global_buffer = BufReader::new(File::open(CPP_OUTPUT_NAME).unwrap());
	let mut parsed_lines = global_buffer.lines()
		.enumerate()
		.filter(|&(_, ref line)| match *line {
			Ok(ref l) => l.starts_with('#'),
			Err(_) => false,
		})
		.map(|(line_num, line)| {
			let line = line.unwrap();
			let tokens: Vec<&str> = line.split('"').map(|s| s.trim_matches('#').trim()).collect();
			let child_num: usize = tokens[0].parse().unwrap();
			let flag = match tokens[2].parse().unwrap_or(0) { //TODO: make conversion function
				1 => Some(LinemarkerFlag::Start),
				2 => Some(LinemarkerFlag::Return),
				3 => Some(LinemarkerFlag::System),
				4 => Some(LinemarkerFlag::Extern),
				_ => None,
			};
			(line_num + 1, child_num, PathBuf::from(tokens[1]), flag)
		})
		.peekable();

	while let Some((path, mapping)) =
		parse_cpp_linemarkers(&parsed_lines.next(), &parsed_lines.peek()) {
		if mapping.len > 1 {
			root_file.assign_mapping(path, mapping).unwrap();
		}
	}

	println!("{}", root_file);
}

fn count_begining_chars(s: &str, c: char) -> usize {
	let mut count: usize = 0;
	for sc in s.chars() {
		if sc == c {
			count += 1;
		} else {
			break;
		}
	}

	count
}

fn parse_cpp_output<'a>(lines: &mut Lines<'a>,
						parrent_file: &mut ParsedFile<'a>,
						depth: usize) {
	while let Some(line) = lines.clone().next() { //TODO: try to use Peekable again. Had problems with recursion before
		let count = count_begining_chars(line, '.');

		if count == 0 {
			return;
		} else if count < depth {
			return;
		} else if count == depth {
			return;
		} else if count > depth && (count - depth) == 1 {
			parrent_file.included_files.push(
					ParsedFile::new(
							&Path::new(lines.next()
								.unwrap()
								.trim_left_matches('.')
								.trim_left()),
							IncludeMethod::CPP(File::open(CPP_OUTPUT_NAME).unwrap(), Vec::new())
			));
			parse_cpp_output(lines,
							 parrent_file.included_files.last_mut().unwrap(),
							 depth + 1);
		} else {
			unreachable!();
		}
	}
}

fn parse_cpp_linemarkers<'a>(current: &'a Option<(usize, usize, PathBuf, Option<LinemarkerFlag>)>,
						next: &Option<&(usize, usize, PathBuf, Option<LinemarkerFlag>)>)
						-> Option<(&'a Path, FileMapping)> {
	if let Some((c_line_num, c_child_num, ref c_path, _)) = *current {
		if let Some(&(n_line_num, _, _, _)) = *next {
			Some((c_path,
				FileMapping {
					parent_start: c_line_num + 1,
					child_start: c_child_num,
					len: n_line_num - c_line_num,
			}))
		} else {
			let last_line = BufReader::new(File::open(CPP_OUTPUT_NAME).unwrap())
				.lines()
				.count(); //TODO: don't use lines() as that allocates new Strings on the heap
			Some((c_path,
				FileMapping {
					parent_start: c_line_num + 1,
					child_start: c_child_num,
					len: last_line - c_line_num,
			}))
		}
	} else {
		None
	}
}
<commit_msg>Use Peekable in parse_cpp_output to not clone an iterator every loop<commit_after>use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::str::Lines;
use std::io::prelude::*;
use std::io::BufReader;
use std::fmt;
use std::iter::Peekable;

// Device Tree stucture
/*
struct DeviceTree<'a> {
	version: u32,
	boot_cpuid: u32,
	reserved_mem: Vec<(u64, u64)>,
	root: Node<'a, 'a>,
}

struct DeviceNode<'a, 'b> {
	name: String,
	props: Vec<(String, Property<'a>)>,
	children: Vec<DeviceNode<'b, 'b>>,
}

enum Property<'a> {
	Empty,
	Cells(Vec<u32>),
	String(String),
	ByteString(Vec<u8>),
	Combo(Vec<&'a Property<'a>>),
}
*/

// File tracking
#[derive(Debug)]
struct ParsedFile<'a> {
	path: &'a Path,
	file: File,
	method: IncludeMethod,
	included_files: Vec<ParsedFile<'a>>,
}

#[derive(Debug)]
enum IncludeMethod {
	DTS,
	CPP(File, Vec<FileMapping>),
}

#[derive(Debug, Clone, Copy)]
struct FileMapping {
	parent_start: usize,
	child_start: usize,
	len: usize,
}

#[derive(Debug)]
enum LinemarkerFlag {
	Start,
	Return,
	System,
	Extern,
}

// Change tracking
/*
struct Change<'a> {
	file: File,
	line: usize,
	// maybe point to node?
	name: String,
	value: Property<'a>,
}
*/

impl<'a> ParsedFile<'a> {
	fn new(path: &'a Path, method: IncludeMethod) -> ParsedFile<'a> {
		ParsedFile {
			path: path,
			file: File::open(path).unwrap(),
			method: method,
			included_files: vec![],
		}
	}

	fn assign_mapping(&mut self, path: &Path, mapping: FileMapping) -> Result<(), String> { //TODO: error propogation
		if self.path == path {
			match self.method {
				IncludeMethod::CPP(_, ref mut mappings) => mappings.push(mapping),
				IncludeMethod::DTS => unreachable!(),
			};
			Ok(())
		} else {
			for file in self.included_files.iter_mut() {
				if file.assign_mapping(path, mapping).is_ok() {
					return Ok(());
				}
			}
			Err(format!("Did not find file: {:?}", path))
		}
	}

	fn write(&self, f: &mut fmt::Formatter, prefix: &str) -> fmt::Result {
		let mut next_prefix = prefix.to_string();
		next_prefix.push_str(" |-");
		writeln!(f, "{} {:?}: {}", prefix, self.path, self.method)
			.and(self.included_files.iter().fold(Ok(()), |res, x| res.and(x.write(f, &next_prefix))))
	}
}

impl<'a> fmt::Display for ParsedFile<'a> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		self.write(f, "")
	}
}

impl fmt::Display for IncludeMethod {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			IncludeMethod::DTS => write!(f, "DTS"),
			IncludeMethod::CPP(_, _) => write!(f, "CPP"),
		}
	}
}

const CPP_OUTPUT_NAME: &'static str = "dts_viewer_tmp.dts";

fn main() {
	let file_name = match env::args().nth(1) {
		None => {
			println!("You forgot the dts file, you dummy");
			return;
		}
		Some(x) => x,
	};

	let arch = "arm";

	let dts_folder = PathBuf::from("arch").join(arch).join("boot/dts/");
	let file_path = dts_folder.join(file_name);

	let include_output = Command::new("arm-linux-gnueabi-gcc")
		.args(&["-H", "-E", "-nostdinc"])
		.args(&["-I", dts_folder.to_str().unwrap()])
		.args(&["-I", dts_folder.join("include/").to_str().unwrap()])
		.args(&["-undef", "-D__DTS__", "-x", "assembler-with-cpp"])
		.args(&["-o", CPP_OUTPUT_NAME])
		.arg(&file_path)
		.output()
		.expect("failed to execute process"); //TODO: properly handle errors

	let cpp_output = String::from_utf8_lossy(&include_output.stderr);
	println!("{}", cpp_output);

	let mut root_file = ParsedFile::new(&Path::new(&file_path),
										IncludeMethod::CPP(File::open(CPP_OUTPUT_NAME).unwrap(), vec![]));

	parse_cpp_output(&mut cpp_output.lines().peekable(), &mut root_file, 0);

	let global_buffer = BufReader::new(File::open(CPP_OUTPUT_NAME).unwrap());
	let mut parsed_lines = global_buffer.lines()
		.enumerate()
		.filter(|&(_, ref line)| match *line {
			Ok(ref l) => l.starts_with('#'),
			Err(_) => false,
		})
		.map(|(line_num, line)| {
			let line = line.unwrap();
			let tokens: Vec<&str> = line.split('"').map(|s| s.trim_matches('#').trim()).collect();
			let child_num: usize = tokens[0].parse().unwrap();
			let flag = match tokens[2].parse().unwrap_or(0) { //TODO: make conversion function
				1 => Some(LinemarkerFlag::Start),
				2 => Some(LinemarkerFlag::Return),
				3 => Some(LinemarkerFlag::System),
				4 => Some(LinemarkerFlag::Extern),
				_ => None,
			};
			(line_num + 1, child_num, PathBuf::from(tokens[1]), flag)
		})
		.peekable();

	while let Some((path, mapping)) =
		parse_cpp_linemarkers(&parsed_lines.next(), &parsed_lines.peek()) {
		if mapping.len > 1 {
			root_file.assign_mapping(path, mapping).unwrap();
		}
	}

	println!("{}", root_file);
}

fn count_begining_chars(s: &str, c: char) -> usize {
	let mut count: usize = 0;
	for sc in s.chars() {
		if sc == c {
			count += 1;
		} else {
			break;
		}
	}

	count
}

fn parse_cpp_output<'a>(lines: &mut Peekable<Lines<'a>>,
						parrent_file: &mut ParsedFile<'a>,
						depth: usize) {
	while let Some(line) = lines.peek().cloned() {
		let count = count_begining_chars(line, '.');

		if count == 0 {
			return;
		} else if count < depth {
			return;
		} else if count == depth {
			return;
		} else if count > depth && (count - depth) == 1 {
			parrent_file.included_files.push(
					ParsedFile::new(
							&Path::new(lines.next()
								.unwrap()
								.trim_left_matches('.')
								.trim_left()),
							IncludeMethod::CPP(File::open(CPP_OUTPUT_NAME).unwrap(), Vec::new())
			));
			parse_cpp_output(lines,
							 parrent_file.included_files.last_mut().unwrap(),
							 depth + 1);
		} else {
			unreachable!();
		}
	}
}

fn parse_cpp_linemarkers<'a>(current: &'a Option<(usize, usize, PathBuf, Option<LinemarkerFlag>)>,
						next: &Option<&(usize, usize, PathBuf, Option<LinemarkerFlag>)>)
						-> Option<(&'a Path, FileMapping)> {
	if let Some((c_line_num, c_child_num, ref c_path, _)) = *current {
		if let Some(&(n_line_num, _, _, _)) = *next {
			Some((c_path,
				FileMapping {
					parent_start: c_line_num + 1,
					child_start: c_child_num,
					len: n_line_num - c_line_num,
			}))
		} else {
			let last_line = BufReader::new(File::open(CPP_OUTPUT_NAME).unwrap())
				.lines()
				.count(); //TODO: don't use lines() as that allocates new Strings on the heap
			Some((c_path,
				FileMapping {
					parent_start: c_line_num + 1,
					child_start: c_child_num,
					len: last_line - c_line_num,
			}))
		}
	} else {
		None
	}
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{BufReader, BufRead, Write};
use std::collections::{HashMap};

use std::env;
use std::io;

const WHITESPACE_FACTOR: isize = 5;
const WHITESPACE_REDUCE: isize = 2;
const CLASS_FACTOR: isize = 5;
const CLASS_REDUCE: isize = 2;

#[derive(Debug)]
struct LineInfo {
    line: String,
    char_map: HashMap<char, Vec<usize>>,
    heatmap: Vec<isize>
}

#[derive(PartialEq)]
enum CharClass {
    Whitespace,
    Numeric,
    Alphabetic,
    Other
}

impl<T: Into<String>> From<T> for LineInfo {
    fn from(item: T) -> LineInfo {
        let mut map: HashMap<char, Vec<usize>> = HashMap::new();
        let mut heat = vec![];
        let line = item.into();

        let mut ws_score = 0;
        let mut cs_score = 0;
        let mut cur_class = CharClass::Whitespace;

        for (idx, c) in line.chars().enumerate() {
            // don't map whitespace
            if !c.is_whitespace() {
                // update the character class change score if needed
                if c.is_numeric() {
                    if cur_class != CharClass::Numeric {
                        cur_class = CharClass::Numeric;
                        cs_score += CLASS_FACTOR;
                    }
                } else if c.is_alphabetic() {
                    if cur_class != CharClass::Alphabetic {
                        cur_class = CharClass::Alphabetic;
                        cs_score += CLASS_FACTOR;
                    }
                } else {
                    if cur_class != CharClass::Other {
                        cur_class = CharClass::Other;
                        cs_score += CLASS_FACTOR;
                    }
                }

                // add an entry in the character map
                map.entry(c).or_insert(Vec::new()).push(idx);
                if c.is_uppercase() {
                    for lc in c.to_lowercase() {
                        // also insert all lowercase equivalents of this character
                        // but not the other way around, so that typing something
                        // uppercase specifies to match uppercase
                        map.entry(lc).or_insert(Vec::new()).push(idx);
                    }
                }
            } else {
                // whitespace is treated differently
                cur_class = CharClass::Whitespace;
                ws_score = WHITESPACE_FACTOR;
            }

            // push to the heatmap
            heat.push(ws_score + cs_score);

            // reduce things
            ws_score /= WHITESPACE_REDUCE;
            cs_score /= CLASS_REDUCE;
        }

        LineInfo {
            line: line,
            char_map: map,
            heatmap: heat
        }
    }
}

impl LineInfo {
    fn query_sequence<T: AsRef<str>>(&self, query_item: T) -> Option<Vec<Vec<usize>>> {
        let query = query_item.as_ref();
        let mut positions: Vec<Vec<usize>> = vec![];

        for c in query.chars() {
            match self.char_map.get(&c) {
                None => break,
                Some(list) => {
                    let to_push;
                    match positions.last() {
                        None => {
                            to_push = list.clone();
                        },
                        Some(item) => {
                            match list.binary_search(&item[0]) {
                                Ok(idx) => {
                                    if idx >= list.len() - 1 {
                                        // line is non-matching
                                        break;
                                    } else {
                                        to_push = list.split_at(idx + 1).1.into();
                                    }
                                },
                                Err(idx) => {
                                    if idx >= list.len() {
                                        // line is non-matching
                                        break;
                                    } else {
                                        to_push = list.split_at(idx).1.into();
                                    }
                                }
                            }
                        }
                    }
                    positions.push(to_push);
                }
            }
        }

        if positions.len() == query.len() {
            Some(positions)
        } else {
            None
        }
    }

    fn query_positions<T: AsRef<str>>(&self, query: T) -> Option<Vec<Vec<usize>>> {
        match self.query_sequence(query) {
            None => None,
            Some(positions) => {
                // matching line
                // create our idx vector
                let mut idx = vec![0; positions.len()];
                let mut result = vec![];
                loop {
                    // check that current configuration is strictly increasing
                    let mut ignore = false;
                    {
                        let mut last_pos = None;
                        for (i, pos) in idx.iter().enumerate() {
                            match last_pos {
                                None => last_pos = Some(positions[i][*pos]),
                                Some(other) => {
                                    if other >= positions[i][*pos] {
                                        ignore = true;
                                        break;
                                    } else {
                                        last_pos = Some(positions[i][*pos]);
                                    }
                                }
                            }
                        }
                    }

                    if !ignore {
                        // add the configuration to the list
                        result.push(idx.iter().enumerate().map(|(i, pos)| {positions[i][*pos]}).collect());
                    }

                    // update our position vector
                    let mut update_idx = idx.len() - 1;
                    let mut finished = false;
                    loop {
                        idx[update_idx] += 1;
                        if idx[update_idx] >= positions[update_idx].len() {
                            if update_idx == 0 {
                                // we're finished with all permutations
                                finished = true;
                                break;
                            } else {
                                idx[update_idx] = 0;
                                update_idx -= 1;
                            }
                        } else {
                            // finished updating for this permutation
                            break;
                        }
                    }
                    if finished {
                        // finished with everything
                        break;
                    }
                }

                // return result
                Some(result)
            }
        }
    }
}

fn main() {
    let history_path = match env::var("HISTFILE") {
        Ok(p) => p,
        Err(e) => panic!("Failed to get bash history file: {}", e)
    };

    let input_file = match File::open(&history_path) {
        Ok(f) => BufReader::new(f),
        Err(e) => panic!("Could not open history file: {}", e)
    };

    let mut query = String::new();

    print!("Match input: ");
    match io::stdout().flush() {
        Err(e) => panic!("Failed to flush stdout: {}", e),
        Ok(_) => {}
    }

    match io::stdin().read_line(&mut query) {
        Ok(_) => {},
        Err(e) => panic!("Failed to read input line: {}", e)
    }

    match query.pop() {
        Some('\n') => {/* pop off trailing newline */},
        Some(c) => query.push(c),
        None => {/* Do nothing with an empty query */}
    }

    for m_line in input_file.lines() {
        let line = match m_line {
            Ok(l) => l,
            Err(e) => panic!("Failed to read line: {}", e)
        };

        let info = LineInfo::from(line.clone());

        match info.query_positions(&query) {
            None => {
                // non-matching line
            },
            Some(positions) => {
                println!("Matching line {:?} with positions {:?}", line, positions);
            }
        }
    }
}
<commit_msg>Implement scoring<commit_after>#![feature(iter_arith)]
use std::fs::File;
use std::io::{BufReader, BufRead, Write};
use std::collections::{HashMap};

use std::env;
use std::io;

const WHITESPACE_FACTOR: isize = 5;
const WHITESPACE_REDUCE: isize = 2;
const CLASS_FACTOR: isize = 3;
const FIRST_FACTOR: isize = 3;
const CLASS_REDUCE: isize = 2;

const DIST_WEIGHT: isize = -10;
const HEAT_WEIGHT: isize = 5;
const LINE_REDUCE: isize = 50;

const MAX_LEN: usize = 80;

#[derive(Debug)]
struct LineInfo {
    line: String,
    char_map: HashMap<char, Vec<usize>>,
    heatmap: Vec<isize>
}

#[derive(PartialEq)]
enum CharClass {
    Whitespace,
    Numeric,
    Alphabetic,
    First,
    Other
}

impl<T: Into<String>> From<T> for LineInfo {
    fn from(item: T) -> LineInfo {
        let mut map: HashMap<char, Vec<usize>> = HashMap::new();
        let mut heat = vec![];
        let line = item.into();

        let mut ws_score = 0;
        let mut cs_score = 0;
        let mut cur_class = CharClass::First;
        // character class changes don't stack
        let mut cs_change = false;

        for (idx, c) in line.chars().enumerate() {
            // don't map whitespace
            if !c.is_whitespace() {
                // update the character class change score if needed
                if cur_class == CharClass::First {
                    // add the first character factor on top of class change
                    cs_score += FIRST_FACTOR;
                }
                if c.is_numeric() {
                    if cur_class != CharClass::Numeric {
                        cur_class = CharClass::Numeric;
                        if !cs_change {
                            cs_score += CLASS_FACTOR;
                            cs_change = true;
                        }
                    } else {
                        cs_change = false;
                    }
                } else if c.is_alphabetic() {
                    if cur_class != CharClass::Alphabetic {
                        cur_class = CharClass::Alphabetic;
                        if !cs_change {
                            cs_score += CLASS_FACTOR;
                            cs_change = true;
                        }
                    } else {
                        cs_change = false;
                    }
                } else {
                    if cur_class != CharClass::Other {
                        cur_class = CharClass::Other;
                        if !cs_change {
                            cs_score += CLASS_FACTOR;
                            cs_change = true;
                        }
                    } else {
                        cs_change = false;
                    }
                }

                // add an entry in the character map
                map.entry(c).or_insert(Vec::new()).push(idx);
                if c.is_uppercase() {
                    for lc in c.to_lowercase() {
                        // also insert all lowercase equivalents of this character
                        // but not the other way around, so that typing something
                        // uppercase specifies to match uppercase
                        map.entry(lc).or_insert(Vec::new()).push(idx);
                    }
                }
            } else {
                // whitespace is treated differently
                cur_class = CharClass::Whitespace;
                ws_score = WHITESPACE_FACTOR;
            }

            // push to the heatmap
            heat.push(ws_score + cs_score);

            // reduce things
            ws_score /= WHITESPACE_REDUCE;
            if !cs_change {
                cs_score /= CLASS_REDUCE;
            }
        }

        LineInfo {
            line: line,
            char_map: map,
            heatmap: heat
        }
    }
}

impl LineInfo {
    fn query_sequence<T: AsRef<str>>(&self, query_item: T) -> Option<Vec<Vec<usize>>> {
        let query = query_item.as_ref();
        let mut positions: Vec<Vec<usize>> = vec![];

        for c in query.chars() {
            match self.char_map.get(&c) {
                None => break,
                Some(list) => {
                    let to_push;
                    match positions.last() {
                        None => {
                            to_push = list.clone();
                        },
                        Some(item) => {
                            match list.binary_search(&item[0]) {
                                Ok(idx) => {
                                    if idx >= list.len() - 1 {
                                        // line is non-matching
                                        break;
                                    } else {
                                        to_push = list.split_at(idx + 1).1.into();
                                    }
                                },
                                Err(idx) => {
                                    if idx >= list.len() {
                                        // line is non-matching
                                        break;
                                    } else {
                                        to_push = list.split_at(idx).1.into();
                                    }
                                }
                            }
                        }
                    }
                    positions.push(to_push);
                }
            }
        }

        if positions.len() == query.len() {
            Some(positions)
        } else {
            None
        }
    }

    fn query_positions<T: AsRef<str>>(&self, query: T) -> Option<Vec<Vec<usize>>> {
        match self.query_sequence(query) {
            None => None,
            Some(positions) => {
                // matching line
                // create our idx vector
                let mut idx = vec![0; positions.len()];
                let mut result = vec![];
                loop {
                    // check that current configuration is strictly increasing
                    let mut ignore = false;
                    {
                        let mut last_pos = None;
                        for (i, pos) in idx.iter().enumerate() {
                            match last_pos {
                                None => last_pos = Some(positions[i][*pos]),
                                Some(other) => {
                                    if other >= positions[i][*pos] {
                                        ignore = true;
                                        break;
                                    } else {
                                        last_pos = Some(positions[i][*pos]);
                                    }
                                }
                            }
                        }
                    }

                    if !ignore {
                        // add the configuration to the list
                        result.push(idx.iter().enumerate().map(|(i, pos)| {positions[i][*pos]}).collect());
                    }

                    // update our position vector
                    let mut update_idx = idx.len() - 1;
                    let mut finished = false;
                    loop {
                        idx[update_idx] += 1;
                        if idx[update_idx] >= positions[update_idx].len() {
                            if update_idx == 0 {
                                // we're finished with all permutations
                                finished = true;
                                break;
                            } else {
                                idx[update_idx] = 0;
                                update_idx -= 1;
                            }
                        } else {
                            // finished updating for this permutation
                            break;
                        }
                    }
                    if finished {
                        // finished with everything
                        break;
                    }
                }

                // return result
                Some(result)
            }
        }
    }

    fn query_score<T: AsRef<str>>(&self, query: T) -> Option<isize> {
        match self.query_positions(&query) {
            None => None,
            Some(positions) => {
                let mut top_score = None;
                for pgroup in positions.iter() {
                    // find the average distance between the indexes
                    let mut dist_total = 0;
                    let mut dist_count = 0;
                    for i in 0..pgroup.len() - 1 {
                        dist_total += (pgroup[i + 1] - pgroup[i]) as isize;
                        dist_count += 1;
                    }
                    // sum the heatmap
                    let heat_sum: isize = pgroup.iter().map(|pos| {self.heatmap[*pos]}).sum();
                    let score = (dist_total / dist_count) * DIST_WEIGHT +
                        heat_sum * HEAT_WEIGHT;
                    match top_score {
                        None => top_score = Some(score),
                        Some(last) => {
                            if score > last {
                                top_score = Some(score);
                            }
                        }
                    }
                }

                // return the result
                top_score
            }
        }
    }
}

fn main() {
    let history_path = match env::var("HISTFILE") {
        Ok(p) => p,
        Err(e) => panic!("Failed to get bash history file: {}", e)
    };

    let input_file = match File::open(&history_path) {
        Ok(f) => BufReader::new(f),
        Err(e) => panic!("Could not open history file: {}", e)
    };

    let mut query = String::new();

    print!("Match input: ");
    match io::stdout().flush() {
        Err(e) => panic!("Failed to flush stdout: {}", e),
        Ok(_) => {}
    }

    match io::stdin().read_line(&mut query) {
        Ok(_) => {},
        Err(e) => panic!("Failed to read input line: {}", e)
    }

    match query.pop() {
        Some('\n') => {/* pop off trailing newline */},
        Some(c) => query.push(c),
        None => {/* Do nothing with an empty query */}
    }

    let mut line_number = -1;
    let mut best_match = None;
    let mut best_score = None;

    for m_line in input_file.lines() {
        let line = match m_line {
            Ok(l) => l,
            Err(e) => panic!("Failed to read line: {}", e)
        };

        if line.len() > MAX_LEN {
            // ignore this line
            continue;
        }

        let info = LineInfo::from(line.clone());

        line_number += 1;

        let line_score = match info.query_score(&query) {
            None => {
                // non-matching line
                continue;
            },
            Some(score) => {
                score + line_number / LINE_REDUCE
            }
        };

        println!("Line {:?} score {}", &line, line_score);

        match best_score {
            None => {
                best_score = Some(line_score);
                best_match = Some(line);
            },
            Some(last) => {
                if line_score >= last {
                    best_score = Some(line_score);
                    best_match = Some(line);
                }
            }
        }
    }

    match best_match {
        Some(line) => {
            println!("Best match: {:?}", line);
        },
        None => {
            println!("No best match found");
        }
    }
}
<|endoftext|>