<commit_before>use hyper::Url;
use hyper::header::{Headers, Header, HeaderFormat};
use hyper::method::Method;
use hyper;
use std::io::{Read, Write, BufReader, BufWriter};

use datatype::Error;

#[derive(Clone, Debug)]
pub struct HttpRequest<'a> {
    pub url: Url,
    pub method: Method,
    pub headers: Headers,
    pub body: Option<&'a str>
}

impl<'a> ToString for HttpRequest<'a> {
    fn to_string(&self) -> String {
        return format!("{} {}", self.method, self.url.serialize())
    }
}

impl<'a> HttpRequest<'a> {
    pub fn new(url: Url, method: Method) -> HttpRequest<'a> {
        HttpRequest { url: url, method: method, headers: Headers::new(), body: None }
    }

    pub fn get(url: Url) -> HttpRequest<'a> {
        HttpRequest::new(url, Method::Get)
    }

    pub fn post(url: Url) -> HttpRequest<'a> {
        HttpRequest::new(url, Method::Post)
    }

    pub fn with_body(&self, body: &'a str) -> HttpRequest<'a> {
        HttpRequest { body: Some(body), ..self.clone() }
    }

    pub fn with_header<H: Header + HeaderFormat>(&self, header: H) -> HttpRequest<'a> {
        let mut hs = self.headers.clone();
        hs.set(header);
        HttpRequest { headers: hs, ..self.clone() }
    }
}

pub trait HttpClient {
    fn new() -> Self;
    fn send_request(&self, req: &HttpRequest) -> Result<String, Error>;
    fn send_request_to<W: Write>(&self, req: &HttpRequest, to: W) -> Result<(), Error>;
}

impl HttpClient for hyper::Client {
    fn new() -> hyper::Client {
        let mut client = hyper::Client::new();
        client.set_redirect_policy(hyper::client::RedirectPolicy::FollowAll);
        client
    }

    fn send_request(&self, req: &HttpRequest) -> Result<String, Error> {
        self.request(req.method.clone(), req.url.clone())
            .headers(req.headers.clone())
            .body(if let Some(body) = req.body { body } else { "" })
            .send()
            .map_err(|e| {
                Error::ClientError(format!("{}", e))
            })
            .and_then(|mut resp| {
                let mut rbody = String::new();
                let status = resp.status;
                if status.is_server_error() || status.is_client_error() {
                    Err(Error::ClientError(format!("Request errored with status {}", status)))
                } else {
                    resp.read_to_string(&mut rbody)
                        .map_err(|e| Error::ParseError(format!("Cannot read response: {}", e)))
                        .map(|_| rbody)
                }
            })
    }

    fn send_request_to<W: Write>(&self, req: &HttpRequest, to: W) -> Result<(), Error> {
        self.request(req.method.clone(), req.url.clone())
            .headers(req.headers.clone())
            .body(if let Some(body) = req.body { body } else { "" })
            .send()
            .map_err(|e| {
                Error::ClientError(format!("Cannot send request: {}", e))
            })
            .and_then(|resp| {
                let status = resp.status;
                if status.is_server_error() || status.is_client_error() {
                    Err(Error::ClientError(format!("Request errored with status {}", status)))
                } else {
                    tee(resp, to)
                        .map_err(|e| Error::ParseError(format!("Cannot read response: {}", e)))
                        .map(|_| ())
                }
            })
    }
}

pub fn tee<R: Read, W: Write>(from: R, to: W) -> Result<(), Error> {
    let mb = 1024 * 1024;
    let rbuf = BufReader::with_capacity(5 * mb, from);
    let mut wbuf = BufWriter::with_capacity(5 * mb, to);
    for b in rbuf.bytes() {
        try!(wbuf.write(&[try!(b)]));
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::File;
    use std::io::{Read, repeat};

    #[test]
    fn test_tee() {
        let values = repeat(b'a').take(9000);
        let sink = File::create("/tmp/otaplus_tee_test").unwrap();

        assert!(tee(values, sink).is_ok());

        let mut values2 = repeat(b'a').take(9000);
        let mut expected = Vec::new();
        let _ = values2.read_to_end(&mut expected);

        let mut f = File::open("/tmp/otaplus_tee_test").unwrap();
        let mut result = Vec::new();
        let _ = f.read_to_end(&mut result);

        assert_eq!(result, expected);
    }

}
<commit_msg>A response is not successful unless it is<commit_after>use hyper::Url;
use hyper::header::{Headers, Header, HeaderFormat};
use hyper::method::Method;
use hyper;
use std::io::{Read, Write, BufReader, BufWriter};

use datatype::Error;

#[derive(Clone, Debug)]
pub struct HttpRequest<'a> {
    pub url: Url,
    pub method: Method,
    pub headers: Headers,
    pub body: Option<&'a str>
}

impl<'a> ToString for HttpRequest<'a> {
    fn to_string(&self) -> String {
        return format!("{} {}", self.method, self.url.serialize())
    }
}

impl<'a> HttpRequest<'a> {
    pub fn new(url: Url, method: Method) -> HttpRequest<'a> {
        HttpRequest { url: url, method: method, headers: Headers::new(), body: None }
    }

    pub fn get(url: Url) -> HttpRequest<'a> {
        HttpRequest::new(url, Method::Get)
    }

    pub fn post(url: Url) -> HttpRequest<'a> {
        HttpRequest::new(url, Method::Post)
    }

    pub fn with_body(&self, body: &'a str) -> HttpRequest<'a> {
        HttpRequest { body: Some(body), ..self.clone() }
    }

    pub fn with_header<H: Header + HeaderFormat>(&self, header: H) -> HttpRequest<'a> {
        let mut hs = self.headers.clone();
        hs.set(header);
        HttpRequest { headers: hs, ..self.clone() }
    }
}

pub trait HttpClient {
    fn new() -> Self;
    fn send_request(&self, req: &HttpRequest) -> Result<String, Error>;
    fn send_request_to<W: Write>(&self, req: &HttpRequest, to: W) -> Result<(), Error>;
}

impl HttpClient for hyper::Client {
    fn new() -> hyper::Client {
        let mut client = hyper::Client::new();
        client.set_redirect_policy(hyper::client::RedirectPolicy::FollowAll);
        client
    }

    fn send_request(&self, req: &HttpRequest) -> Result<String, Error> {
        self.request(req.method.clone(), req.url.clone())
            .headers(req.headers.clone())
            .body(if let Some(body) = req.body { body } else { "" })
            .send()
            .map_err(|e| {
                Error::ClientError(format!("{}", e))
            })
            .and_then(|mut resp| {
                let mut rbody = String::new();
                let status = resp.status;
                if status.is_success() {
                    resp.read_to_string(&mut rbody)
                        .map_err(|e| Error::ParseError(format!("Cannot read response: {}", e)))
                        .map(|_| rbody)
                } else {
                    Err(Error::ClientError(format!("Request failed with status {}", status)))
                }
            })
    }

    fn send_request_to<W: Write>(&self, req: &HttpRequest, to: W) -> Result<(), Error> {
        self.request(req.method.clone(), req.url.clone())
            .headers(req.headers.clone())
            .body(if let Some(body) = req.body { body } else { "" })
            .send()
            .map_err(|e| {
                Error::ClientError(format!("Cannot send request: {}", e))
            })
            .and_then(|resp| {
                let status = resp.status;
                if status.is_server_error() || status.is_client_error() {
                    Err(Error::ClientError(format!("Request errored with status {}", status)))
                } else {
                    tee(resp, to)
                        .map_err(|e| Error::ParseError(format!("Cannot read response: {}", e)))
                        .map(|_| ())
                }
            })
    }
}

pub fn tee<R: Read, W: Write>(from: R, to: W) -> Result<(), Error> {
    let mb = 1024 * 1024;
    let rbuf = BufReader::with_capacity(5 * mb, from);
    let mut wbuf = BufWriter::with_capacity(5 * mb, to);
    for b in rbuf.bytes() {
        try!(wbuf.write(&[try!(b)]));
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs::File;
    use std::io::{Read, repeat};

    #[test]
    fn test_tee() {
        let values = repeat(b'a').take(9000);
        let sink = File::create("/tmp/otaplus_tee_test").unwrap();

        assert!(tee(values, sink).is_ok());

        let mut values2 = repeat(b'a').take(9000);
        let mut expected = Vec::new();
        let _ = values2.read_to_end(&mut expected);

        let mut f = File::open("/tmp/otaplus_tee_test").unwrap();
        let mut result = Vec::new();
        let _ = f.read_to_end(&mut result);

        assert_eq!(result, expected);
    }

}
<|endoftext|>


<commit_before>use analysis::rust_type::Result;
use env::Env;
use gobjects::GStatus;
use library;
use library::*;
use nameutil::crate_name;

// FIXME: This module needs redundant allocations audit
// TODO: ffi_type computations should be cached

pub fn ffi_type(env: &Env, tid: library::TypeId, c_type: &str) -> Result {
    // Fast track plain fundamental types avoiding some checks
    if let Some(c_tid) = env.library.find_type(0, c_type) {
        if env.library.type_(c_tid).maybe_ref_as::<Fundamental>().is_some() {
            return ffi_inner(env, c_tid, c_type.into());
        }
    }

    let (ptr, inner) = rustify_pointers(c_type);
    let res = match (ptr.is_empty(), ffi_inner(env, tid, inner)) {
        (true, x) => x,
        (_, Ok(s)) => Ok(format!("{} {}", ptr, s)),
        (_, Err(s)) => Err(format!("{} {}", ptr, s)),
    };
    trace!("ffi_type({:?}, {}) -> {:?}", tid, c_type, res);
    res
}

fn ffi_inner(env: &Env, tid: library::TypeId, inner: String) -> Result {
    match *env.library.type_(tid) {
        Type::Fundamental(fund) => {
            use library::Fundamental::*;
            let inner = match fund {
                None => "c_void",
                Boolean => "gboolean",
                Int8 => "i8",
                UInt8 => "u8",
                Int16 => "i16",
                UInt16 => "u16",
                Int32 => "i32",
                UInt32 => "u32",
                Int64 => "i64",
                UInt64 => "u64",
                Char => "c_char",
                UChar => "c_char",
                Short => "c_short",
                UShort => "c_ushort",
                Int => "c_int",
                UInt => "c_uint",
                Long => "c_long",
                ULong => "c_ulong",
                Size => "size_t",
                SSize => "ssize_t",
                Float => "c_float",
                Double => "c_double",
                UniChar => "u32",
                Utf8 => "c_char",
                Filename => "c_char",
                Type => "GType",
                Pointer => return Ok(inner),
                Unsupported => return Err(format!("[Unsupported type {}]", inner)),
                VarArgs => panic!("Should not reach here"),
            };
            Ok(inner.into())
        }
        Type::Record(..) | Type::Alias(..) | Type::Function(..) => {
            fix_external_name(env, tid, &inner)
        }
        // TODO: need to recurse into it
        Type::Array(inner_tid) => {
            ffi_inner(env, inner_tid, inner)
        }
        Type::List(..) | Type::SList(..) => Ok(inner),
        _ => {
            if let Some(glib_name) = env.library.type_(tid).get_glib_name() {
                if inner != glib_name {
                    let msg = format!("[c:type mismatch {} != {} of {}]", inner, glib_name,
                      env.library.type_(tid).get_name());
                    warn!("{}", msg);
                    Err(msg)
                }
                else {
                    fix_external_name(env, tid, &inner)
                }
            }
            else {
                let msg = format!("[Missing glib_name of {}, can't match != {}]",
                                  env.library.type_(tid).get_name(), inner);
                warn!("{}", msg);
                Err(msg)
            }
        }
    }
}

fn fix_external_name(env: &Env, type_id: library::TypeId, name: &str) -> Result {
    if type_id.ns_id == library::MAIN_NAMESPACE || type_id.ns_id == library::INTERNAL_NAMESPACE {
        Ok(name.into())
    } else {
        let name_with_prefix = format!("{}_ffi::{}",
            fix_namespace(env, type_id), name);
        if env.type_status_sys(&type_id.full_name(&env.library)) == GStatus::Ignore {
            Err(name_with_prefix.into())
        } else {
            Ok(name_with_prefix)
        }
    }
}

//TODO: check if need to use in non sys codegen
fn fix_namespace(env: &Env, type_id: library::TypeId) -> String {
    let mut name: &str = &crate_name(&env.library.namespace(type_id.ns_id).name);
    name = match name {
        "gdkpixbuf" => "gdk",
        "gio" => "glib",
        "gobject" => "glib",
        _ => name,
    };
    name.into()
}

fn rustify_pointers(c_type: &str) -> (String, String) {
    let mut input = c_type.trim();
    let leading_const = input.starts_with("const ");
    if leading_const {
        input = &input[6..];
    }
    let end = [
        input.find(" const"),
        input.find("*const"),
        input.find("*"),
        Some(input.len()),
    ].iter().filter_map(|&x| x).min().unwrap();
    let inner = input[..end].trim().into();

    let mut ptrs: Vec<_> = input[end..].rsplit('*').skip(1)
        .map(|s| if s.contains("const") { "*const" } else { "*mut" }).collect();
    if let (true, Some(p)) = (leading_const, ptrs.last_mut()) {
        *p = "*const";
    }

    let res = (ptrs.connect(" "), inner);
    trace!("rustify `{}` -> `{}` `{}`", c_type, res.0, res.1);
    res
}

#[cfg(test)]
mod tests {
    use super::rustify_pointers as rustify_ptr;

    fn s(x: &str, y: &str) -> (String, String) {
        (x.into(), y.into())
    }

    #[test]
    fn rustify_pointers() {
        assert_eq!(rustify_ptr("char"), s("", "char"));
        assert_eq!(rustify_ptr("char*"), s("*mut", "char"));
        assert_eq!(rustify_ptr("const char*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const *"), s("*const", "char"));
        assert_eq!(rustify_ptr(" char * * "), s("*mut *mut", "char"));
        assert_eq!(rustify_ptr("const char**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("char const**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("const char* const*"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char const * const *"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char* const*"), s("*const *mut", "char"));
    }
}
<commit_msg>ffi_type: support fixed-size arrays<commit_after>use analysis::rust_type::Result;
use env::Env;
use gobjects::GStatus;
use library;
use library::*;
use nameutil::crate_name;

// FIXME: This module needs redundant allocations audit
// TODO: ffi_type computations should be cached

pub fn ffi_type(env: &Env, tid: library::TypeId, c_type: &str) -> Result {
    // Fast track plain fundamental types avoiding some checks
    if let Some(c_tid) = env.library.find_type(0, c_type) {
        let fundamental_c_type = env.library.type_(c_tid).maybe_ref_as::<Fundamental>().is_some();
        let array = match env.library.type_(tid) {
            &library::Type::ArraySized(..) => true,
            _ => false,
        };
        if fundamental_c_type && !array {
            return ffi_inner(env, c_tid, c_type.into());
        }
    }

    let (ptr, inner) = rustify_pointers(c_type);
    let res = match (ptr.is_empty(), ffi_inner(env, tid, inner)) {
        (true, x) => x,
        (_, Ok(s)) => Ok(format!("{} {}", ptr, s)),
        (_, Err(s)) => Err(format!("{} {}", ptr, s)),
    };
    trace!("ffi_type({:?}, {}) -> {:?}", tid, c_type, res);
    res
}

fn ffi_inner(env: &Env, tid: library::TypeId, inner: String) -> Result {
    match *env.library.type_(tid) {
        Type::Fundamental(fund) => {
            use library::Fundamental::*;
            let inner = match fund {
                None => "c_void",
                Boolean => "gboolean",
                Int8 => "i8",
                UInt8 => "u8",
                Int16 => "i16",
                UInt16 => "u16",
                Int32 => "i32",
                UInt32 => "u32",
                Int64 => "i64",
                UInt64 => "u64",
                Char => "c_char",
                UChar => "c_char",
                Short => "c_short",
                UShort => "c_ushort",
                Int => "c_int",
                UInt => "c_uint",
                Long => "c_long",
                ULong => "c_ulong",
                Size => "size_t",
                SSize => "ssize_t",
                Float => "c_float",
                Double => "c_double",
                UniChar => "u32",
                Utf8 => "c_char",
                Filename => "c_char",
                Type => "GType",
                Pointer => return Ok(inner),
                Unsupported => return Err(format!("[Unsupported type {}]", inner)),
                VarArgs => panic!("Should not reach here"),
            };
            Ok(inner.into())
        }
        Type::Record(..) | Type::Alias(..) | Type::Function(..) => {
            fix_external_name(env, tid, &inner)
        }
        Type::Array(inner_tid) => ffi_inner(env, inner_tid, inner),
        Type::ArraySized(inner_tid, size) => {
            match ffi_inner(env, inner_tid, inner) {
                Ok(s) => Ok(format!("[{}; {}]", s, size)),
                Err(s) => Err(format!("[{}; {}]", s, size)),
            }
        }
        Type::List(..) | Type::SList(..) => Ok(inner),
        _ => {
            if let Some(glib_name) = env.library.type_(tid).get_glib_name() {
                if inner != glib_name {
                    let msg = format!("[c:type mismatch {} != {} of {}]", inner, glib_name,
                      env.library.type_(tid).get_name());
                    warn!("{}", msg);
                    Err(msg)
                }
                else {
                    fix_external_name(env, tid, &inner)
                }
            }
            else {
                let msg = format!("[Missing glib_name of {}, can't match != {}]",
                                  env.library.type_(tid).get_name(), inner);
                warn!("{}", msg);
                Err(msg)
            }
        }
    }
}

fn fix_external_name(env: &Env, type_id: library::TypeId, name: &str) -> Result {
    if type_id.ns_id == library::MAIN_NAMESPACE || type_id.ns_id == library::INTERNAL_NAMESPACE {
        Ok(name.into())
    } else {
        let name_with_prefix = format!("{}_ffi::{}",
            fix_namespace(env, type_id), name);
        if env.type_status_sys(&type_id.full_name(&env.library)) == GStatus::Ignore {
            Err(name_with_prefix.into())
        } else {
            Ok(name_with_prefix)
        }
    }
}

//TODO: check if need to use in non sys codegen
fn fix_namespace(env: &Env, type_id: library::TypeId) -> String {
    let mut name: &str = &crate_name(&env.library.namespace(type_id.ns_id).name);
    name = match name {
        "gdkpixbuf" => "gdk",
        "gio" => "glib",
        "gobject" => "glib",
        _ => name,
    };
    name.into()
}

fn rustify_pointers(c_type: &str) -> (String, String) {
    let mut input = c_type.trim();
    let leading_const = input.starts_with("const ");
    if leading_const {
        input = &input[6..];
    }
    let end = [
        input.find(" const"),
        input.find("*const"),
        input.find("*"),
        Some(input.len()),
    ].iter().filter_map(|&x| x).min().unwrap();
    let inner = input[..end].trim().into();

    let mut ptrs: Vec<_> = input[end..].rsplit('*').skip(1)
        .map(|s| if s.contains("const") { "*const" } else { "*mut" }).collect();
    if let (true, Some(p)) = (leading_const, ptrs.last_mut()) {
        *p = "*const";
    }

    let res = (ptrs.connect(" "), inner);
    trace!("rustify `{}` -> `{}` `{}`", c_type, res.0, res.1);
    res
}

#[cfg(test)]
mod tests {
    use super::rustify_pointers as rustify_ptr;

    fn s(x: &str, y: &str) -> (String, String) {
        (x.into(), y.into())
    }

    #[test]
    fn rustify_pointers() {
        assert_eq!(rustify_ptr("char"), s("", "char"));
        assert_eq!(rustify_ptr("char*"), s("*mut", "char"));
        assert_eq!(rustify_ptr("const char*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const *"), s("*const", "char"));
        assert_eq!(rustify_ptr(" char * * "), s("*mut *mut", "char"));
        assert_eq!(rustify_ptr("const char**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("char const**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("const char* const*"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char const * const *"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char* const*"), s("*const *mut", "char"));
    }
}
<|endoftext|>


<commit_before>use clap::{crate_version, App, Arg};
use reqwest::blocking::Client;
use serde::Deserialize;
use serde_json::json;

mod settings;
use settings::Settings;

#[derive(Deserialize, Debug)]
struct PathShortened {
    path_shortened: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let settings = Settings::new().unwrap();

    // Subcommands function exactly like sub-Apps, because that's exactly what they are. Each
    // instance of a Subcommand can have its own version, author(s), Args, and even its own
    // subcommands.
    //
    // # Help and Version
    // Just like Apps, each subcommand will get its own "help" and "version" flags automatically
    // generated. Also, like Apps, you can override "-V" or "-h" safely and still get "--help" and
    // "--version" auto generated.
    //
    // NOTE: If you specify a subcommand for your App, clap will also autogenerate a "help"
    // subcommand along with "-h" and "--help" (applies to sub-subcommands as well).
    //
    // Just like arg() and args(), subcommands can be specified one at a time via subcommand() or
    // multiple ones at once with a Vec<App> provided to subcommands().
    let matches = App::new("lhc")
        .version(crate_version!())
        .subcommand(
            App::new("path-shorten").about("Shorten a path").arg(
                Arg::new("path_to_shorten")
                    .about("the path to shorten")
                    .index(1)
                    .required(true),
            ),
        )
        .subcommand(App::new("shutdown").about("Shut down lh server instance"))
        .get_matches();

    match matches.subcommand_name() {
        Some("path-shorten") => {
            if let Some(m) = matches.subcommand_matches("path-shorten") {
                // Safe to use unwrap() because of the required() option
                let path_to_shorten = m.value_of("path_to_shorten").unwrap();

                let request_url = format!(
                    "http://{}:{}/path-shorten/",
                    settings.server.domain, settings.server.port
                );

                let json_body = json!({
                "path": path_to_shorten,
                });

                let response = Client::new().post(request_url).json(&json_body).send()?;

                let path_shortened: PathShortened = response.json()?;

                print!("{}", path_shortened.path_shortened);
            }
        }
        Some("shutdown") => {
            let request_url = format!(
                "http://{}:{}/shutdown",
                settings.server.domain, settings.server.port
            );

            let response = Client::new().get(request_url).send()?;

            println!("{}", response.text()?);
        }
        None => println!("Nothing to do."),
        _ => println!("Nothing to do (unrecognized subcommand)."),
    }
    Ok(())
}
<commit_msg>lhc: path-shorten: simplify request url<commit_after>use clap::{crate_version, App, Arg};
use reqwest::blocking::Client;
use serde::Deserialize;
use serde_json::json;

mod settings;
use settings::Settings;

#[derive(Deserialize, Debug)]
struct PathShortened {
    path_shortened: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let settings = Settings::new().unwrap();

    // Subcommands function exactly like sub-Apps, because that's exactly what they are. Each
    // instance of a Subcommand can have its own version, author(s), Args, and even its own
    // subcommands.
    //
    // # Help and Version
    // Just like Apps, each subcommand will get its own "help" and "version" flags automatically
    // generated. Also, like Apps, you can override "-V" or "-h" safely and still get "--help" and
    // "--version" auto generated.
    //
    // NOTE: If you specify a subcommand for your App, clap will also autogenerate a "help"
    // subcommand along with "-h" and "--help" (applies to sub-subcommands as well).
    //
    // Just like arg() and args(), subcommands can be specified one at a time via subcommand() or
    // multiple ones at once with a Vec<App> provided to subcommands().
    let matches = App::new("lhc")
        .version(crate_version!())
        .subcommand(
            App::new("path-shorten").about("Shorten a path").arg(
                Arg::new("path_to_shorten")
                    .about("the path to shorten")
                    .index(1)
                    .required(true),
            ),
        )
        .subcommand(App::new("shutdown").about("Shut down lh server instance"))
        .get_matches();

    match matches.subcommand_name() {
        Some("path-shorten") => {
            if let Some(m) = matches.subcommand_matches("path-shorten") {
                // Safe to use unwrap() because of the required() option
                let path_to_shorten = m.value_of("path_to_shorten").unwrap();

                let request_url = format!(
                    "http://{}:{}/path-shorten",
                    settings.server.domain, settings.server.port
                );

                let json_body = json!({
                "path": path_to_shorten,
                });

                let response = Client::new().post(request_url).json(&json_body).send()?;

                let path_shortened: PathShortened = response.json()?;

                print!("{}", path_shortened.path_shortened);
            }
        }
        Some("shutdown") => {
            let request_url = format!(
                "http://{}:{}/shutdown",
                settings.server.domain, settings.server.port
            );

            let response = Client::new().get(request_url).send()?;

            println!("{}", response.text()?);
        }
        None => println!("Nothing to do."),
        _ => println!("Nothing to do (unrecognized subcommand)."),
    }
    Ok(())
}
<|endoftext|>


<commit_before>use crate::paging::{RmmA, RmmArch, TableKind};

#[cfg(not(target_arch = "x86_64"))]
pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
    println!("DEBUGGER TODO");
    println!();
}

// Super unsafe due to page table switching and raw pointers!
#[cfg(target_arch = "x86_64")]
pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
    println!("DEBUGGER START");
    println!();

    let old_table = RmmA::table(TableKind::User);

    for (id, context_lock) in crate::context::contexts().iter() {
        if target_id.map_or(false, |target_id| *id != target_id) { continue; }
        let context = context_lock.read();
        println!("{}: {}", (*id).into(), context.name.read());

        // Switch to context page table to ensure syscall debug and stack dump will work
        if let Some(ref space) = context.addr_space {
            RmmA::set_table(TableKind::User, space.read().table.utable.table().phys());
            check_consistency(&mut space.write());
        }

        println!("status: {:?}", context.status);
        if ! context.status_reason.is_empty() {
            println!("reason: {}", context.status_reason);
        }
        if let Some((a, b, c, d, e, f)) = context.syscall {
            println!("syscall: {}", crate::syscall::debug::format_call(a, b, c, d, e, f));
        }
        if let Some(ref addr_space) = context.addr_space {
            let addr_space = addr_space.read();
            if ! addr_space.grants.is_empty() {
                println!("grants:");
                for grant in addr_space.grants.iter() {
                    let region = grant.region();
                    println!(
                        "    virt 0x{:016x}:0x{:016x} size 0x{:08x} {}",
                        region.start_address().data(), region.final_address().data(), region.size(),
                        if grant.is_owned() { "owned" } else { "borrowed" },
                    );
                }
            }
        }
        if let Some(regs) = crate::ptrace::regs_for(&context) {
            println!("regs:");
            regs.dump();

            let mut rsp = regs.iret.rsp;
            println!("stack: {:>016x}", rsp);
            //Maximum 64 qwords
            for _ in 0..64 {
                if context.addr_space.as_ref().map_or(false, |space| space.read().table.utable.translate(crate::paging::VirtualAddress::new(rsp)).is_some()) {
                    let value = *(rsp as *const usize);
                    println!("    {:>016x}: {:>016x}", rsp, value);
                    if let Some(next_rsp) = rsp.checked_add(core::mem::size_of::<usize>()) {
                        rsp = next_rsp;
                    } else {
                        println!("    {:>016x}: OVERFLOW", rsp);
                        break;
                    }
                } else {
                    println!("    {:>016x}: GUARD PAGE", rsp);
                    break;
                }
            }
        }

        // Switch to original page table
        RmmA::set_table(TableKind::User, old_table);

        println!();
    }

    println!("DEBUGGER END");
}

pub unsafe fn check_consistency(addr_space: &mut crate::context::memory::AddrSpace) {
    use crate::paging::*;

    let p4 = addr_space.table.utable.table();

    for p4i in 0..256 {
        let p3 = match p4.next(p4i) {
            Some(p3) => p3,
            None => continue,
        };

        for p3i in 0..512 {
            let p2 = match p3.next(p3i) {
                Some(p2) => p2,
                None => continue,
            };

            for p2i in 0..512 {
                let p1 = match p2.next(p2i) {
                    Some(p1) => p1,
                    None => continue,
                };

                for p1i in 0..512 {
                    let (physaddr, flags) = match p1.entry(p1i) {
                        Some(e) => if let Ok(address) = e.address() {
                            (address, e.flags())
                        } else {
                            continue;
                        }
                        _ => continue,
                    };
                    let address = VirtualAddress::new((p1i << 12) | (p2i << 21) | (p3i << 30) | (p4i << 39));

                    let grant = match addr_space.grants.contains(address) {
                        Some(g) => g,
                        None => {
                            log::error!("ADDRESS {:p} LACKING GRANT BUT MAPPED TO {:#0x} FLAGS {:?}!", address.data() as *const u8, physaddr.data(), flags);
                            continue;
                        }
                    };
                    const STICKY: usize = (1 << 5) | (1 << 6); // accessed+dirty
                    if grant.flags().data() & !STICKY != flags.data() & !STICKY {
                        log::error!("FLAG MISMATCH: {:?} != {:?}, address {:p} in grant at {:?}", grant.flags(), flags, address.data() as *const u8, grant.region());
                    }
                }
            }
        }
    }

    for grant in addr_space.grants.iter() {
        for page in grant.pages() {
            let _entry = match addr_space.table.utable.translate(page.start_address()) {
                Some(e) => e,
                None => {
                    log::error!("GRANT AT {:?} LACKING MAPPING AT PAGE {:p}", grant.region(), page.start_address().data() as *const u8);
                    continue;
                }
            };
        }
    }
}
<commit_msg>Implement debugger for x86<commit_after>use crate::paging::{RmmA, RmmArch, TableKind};

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
    println!("DEBUGGER TODO");
    println!();
}

// Super unsafe due to page table switching and raw pointers!
#[cfg(target_arch = "x86")]
pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
    println!("DEBUGGER START");
    println!();

    let old_table = RmmA::table(TableKind::User);

    for (id, context_lock) in crate::context::contexts().iter() {
        if target_id.map_or(false, |target_id| *id != target_id) { continue; }
        let context = context_lock.read();
        println!("{}: {}", (*id).into(), context.name.read());

        // Switch to context page table to ensure syscall debug and stack dump will work
        if let Some(ref space) = context.addr_space {
            RmmA::set_table(TableKind::User, space.read().table.utable.table().phys());
            //TODO check_consistency(&mut space.write());
        }

        println!("status: {:?}", context.status);
        if ! context.status_reason.is_empty() {
            println!("reason: {}", context.status_reason);
        }
        if let Some((a, b, c, d, e, f)) = context.syscall {
            println!("syscall: {}", crate::syscall::debug::format_call(a, b, c, d, e, f));
        }
        if let Some(ref addr_space) = context.addr_space {
            let addr_space = addr_space.read();
            if ! addr_space.grants.is_empty() {
                println!("grants:");
                for grant in addr_space.grants.iter() {
                    let region = grant.region();
                    println!(
                        "    virt 0x{:08x}:0x{:08x} size 0x{:08x} {}",
                        region.start_address().data(), region.final_address().data(), region.size(),
                        if grant.is_owned() { "owned" } else { "borrowed" },
                    );
                }
            }
        }
        if let Some(regs) = crate::ptrace::regs_for(&context) {
            println!("regs:");
            regs.dump();

            let mut sp = regs.iret.esp;
            println!("stack: {:>08x}", sp);
            //Maximum 64 dwords
            for _ in 0..64 {
                if context.addr_space.as_ref().map_or(false, |space| space.read().table.utable.translate(crate::paging::VirtualAddress::new(sp)).is_some()) {
                    let value = *(sp as *const usize);
                    println!("    {:>08x}: {:>08x}", sp, value);
                    if let Some(next_sp) = sp.checked_add(core::mem::size_of::<usize>()) {
                        sp = next_sp;
                    } else {
                        println!("    {:>08x}: OVERFLOW", sp);
                        break;
                    }
                } else {
                    println!("    {:>08x}: GUARD PAGE", sp);
                    break;
                }
            }
        }

        // Switch to original page table
        RmmA::set_table(TableKind::User, old_table);

        println!();
    }

    println!("DEBUGGER END");
}

// Super unsafe due to page table switching and raw pointers!
#[cfg(target_arch = "x86_64")]
pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
    println!("DEBUGGER START");
    println!();

    let old_table = RmmA::table(TableKind::User);

    for (id, context_lock) in crate::context::contexts().iter() {
        if target_id.map_or(false, |target_id| *id != target_id) { continue; }
        let context = context_lock.read();
        println!("{}: {}", (*id).into(), context.name.read());

        // Switch to context page table to ensure syscall debug and stack dump will work
        if let Some(ref space) = context.addr_space {
            RmmA::set_table(TableKind::User, space.read().table.utable.table().phys());
            check_consistency(&mut space.write());
        }

        println!("status: {:?}", context.status);
        if ! context.status_reason.is_empty() {
            println!("reason: {}", context.status_reason);
        }
        if let Some((a, b, c, d, e, f)) = context.syscall {
            println!("syscall: {}", crate::syscall::debug::format_call(a, b, c, d, e, f));
        }
        if let Some(ref addr_space) = context.addr_space {
            let addr_space = addr_space.read();
            if ! addr_space.grants.is_empty() {
                println!("grants:");
                for grant in addr_space.grants.iter() {
                    let region = grant.region();
                    println!(
                        "    virt 0x{:016x}:0x{:016x} size 0x{:08x} {}",
                        region.start_address().data(), region.final_address().data(), region.size(),
                        if grant.is_owned() { "owned" } else { "borrowed" },
                    );
                }
            }
        }
        if let Some(regs) = crate::ptrace::regs_for(&context) {
            println!("regs:");
            regs.dump();

            let mut rsp = regs.iret.rsp;
            println!("stack: {:>016x}", rsp);
            //Maximum 64 qwords
            for _ in 0..64 {
                if context.addr_space.as_ref().map_or(false, |space| space.read().table.utable.translate(crate::paging::VirtualAddress::new(rsp)).is_some()) {
                    let value = *(rsp as *const usize);
                    println!("    {:>016x}: {:>016x}", rsp, value);
                    if let Some(next_rsp) = rsp.checked_add(core::mem::size_of::<usize>()) {
                        rsp = next_rsp;
                    } else {
                        println!("    {:>016x}: OVERFLOW", rsp);
                        break;
                    }
                } else {
                    println!("    {:>016x}: GUARD PAGE", rsp);
                    break;
                }
            }
        }

        // Switch to original page table
        RmmA::set_table(TableKind::User, old_table);

        println!();
    }

    println!("DEBUGGER END");
}

#[cfg(target_arch = "x86_64")]
pub unsafe fn check_consistency(addr_space: &mut crate::context::memory::AddrSpace) {
    use crate::paging::*;

    let p4 = addr_space.table.utable.table();

    for p4i in 0..256 {
        let p3 = match p4.next(p4i) {
            Some(p3) => p3,
            None => continue,
        };

        for p3i in 0..512 {
            let p2 = match p3.next(p3i) {
                Some(p2) => p2,
                None => continue,
            };

            for p2i in 0..512 {
                let p1 = match p2.next(p2i) {
                    Some(p1) => p1,
                    None => continue,
                };

                for p1i in 0..512 {
                    let (physaddr, flags) = match p1.entry(p1i) {
                        Some(e) => if let Ok(address) = e.address() {
                            (address, e.flags())
                        } else {
                            continue;
                        }
                        _ => continue,
                    };
                    let address = VirtualAddress::new((p1i << 12) | (p2i << 21) | (p3i << 30) | (p4i << 39));

                    let grant = match addr_space.grants.contains(address) {
                        Some(g) => g,
                        None => {
                            log::error!("ADDRESS {:p} LACKING GRANT BUT MAPPED TO {:#0x} FLAGS {:?}!", address.data() as *const u8, physaddr.data(), flags);
                            continue;
                        }
                    };
                    const STICKY: usize = (1 << 5) | (1 << 6); // accessed+dirty
                    if grant.flags().data() & !STICKY != flags.data() & !STICKY {
                        log::error!("FLAG MISMATCH: {:?} != {:?}, address {:p} in grant at {:?}", grant.flags(), flags, address.data() as *const u8, grant.region());
                    }
                }
            }
        }
    }

    for grant in addr_space.grants.iter() {
        for page in grant.pages() {
            let _entry = match addr_space.table.utable.translate(page.start_address()) {
                Some(e) => e,
                None => {
                    log::error!("GRANT AT {:?} LACKING MAPPING AT PAGE {:p}", grant.region(), page.start_address().data() as *const u8);
                    continue;
                }
            };
        }
    }
}
<|endoftext|>


<commit_before>
use std::io::{Read, SeekFrom};
use std::cmp;

use hyper;
use hyper::Error;
use hyper::client::Client;
use hyper::client::response::Response;
use hyper::header::ByteRangeSpec;
use hyper::header::ByteRangeSpec::FromTo;
use hyper::header::Range::Bytes;
use hyper::header::{ContentLength, ContentRange, ContentRangeSpec};

use reader::ReaderKind;
use reader::Reader;
use buffer::Buffer;

#[derive(Debug)]
pub struct HttpReader {
  position: u64,
  size: Option<u64>,
  buf: Buffer
}

impl HttpReader {
  fn create(content_length: Option<u64>) -> HttpReader {
    HttpReader{
      position: 0,
      size: content_length,
      buf: Buffer::create()
    }
  }
}

pub fn exists(filename: &String) -> bool {
  let client = Client::new();
  match client.head(filename).send() {
    Ok(resp) => resp.status == hyper::Ok,
    Err(_) => false
  }
}

fn get_head(filename: &String) -> Result<Response, Error> {
  let client = Client::new();
  client.head(filename).send()
}

fn get_content_length(response: &Response) -> Option<u64> {
  match response.headers.get::<ContentLength>() {
    Some(length) => Some(**length as u64),
    None => None
  }
}

fn get_content_range(response: &Response) -> Result<Option<u64>, String> {
  match response.headers.get::<ContentRange>() {
    Some(content_range) => {
      match content_range.clone() {
        ContentRange(ContentRangeSpec::Bytes{
            range: _range,
            instance_length: length
          }) => {
          Ok(length)
        },
        ContentRange(ContentRangeSpec::Unregistered{unit: _unit, resp: _resp}) => {
          Err("Unregistered, actually unsupported".to_string())
        }
      }
    },
    None =>
      Err("Missing content_range".to_string()),
  }
}

pub fn open(filename: &String) -> Result<Reader, String> {
  match get_head(filename) {
    Err(error) => Err(error.to_string()),
    Ok(response) => {

      let content_length = get_content_length(&response);
      let http_reader = HttpReader::create(content_length);

      let reader = Reader{
        filename: filename.to_string(),
        mode: ReaderKind::Http,
        file: None,
        cache_size: None,
        http_reader: Some(http_reader)
      };

      Ok(reader)
    }
  }
}

fn get_data_range(position: u64, size: usize) -> Vec<ByteRangeSpec> {
  let start = position;
  let end = position + (size - 1) as u64;

  vec![FromTo(start, end)]
}

fn load_data(reader: &mut Reader, size: usize) -> Result<Option<Vec<u8>>, String> {

  info!("make HTTP request with request {:?} bytes", size);
  match reader.http_reader {
    None => Err("missing HTTP reader".to_string()),
    Some(ref mut http_reader) => {

      match http_reader.size {
          Some(size) => {
            if http_reader.position >= size {
              return Ok(None)
            }
          },
          None => (),
      };

      let range = get_data_range(http_reader.position, size);

      let client = Client::new();
      let request =
        client
        .get(&reader.filename)
        .header(Bytes(range));

      let mut response = try!(request.send().map_err(|e| e.to_string()));

      let mut loaded_size : u64 = 0;
      {
        match get_content_length(&response) {
            Some(content_length) => loaded_size = content_length,
            None => return Err("Missing content_length".to_string()),
        }

        match get_content_range(&response) {
          Ok(length) => http_reader.size = length,
          Err(msg) => return Err(msg),
        }
      }

      match loaded_size {
        0 => Err("Bad request range".to_string()),
        _ => {
          let mut body = vec![0; loaded_size as usize];
          try!(Read::read_exact(&mut response, &mut body).map_err(|e| e.to_string()));

          http_reader.position = http_reader.position + loaded_size as u64;
          Ok(Some(body))
        }
      }
    }
  }
}

fn define_size_to_load(reader: &Reader, cache_size: usize, size: usize) -> Option<usize> {
  match reader.http_reader {
    Some(ref http_reader) => {
      match http_reader.buf.get_cached_size() < size {
        true => Some(cmp::max(cache_size, size)),
        _ => None
      }
    },
    None => panic!("Missing Http Reader"),
  }
}

pub fn read(mut reader: &mut Reader, size: usize) -> Result<Vec<u8>, String> {
  debug!("read {:?} bytes", size);
  match reader.cache_size {
    None => {
      match load_data(reader, size) {
        Ok(optional_data) => {
          match optional_data {
            Some(data) => Ok(data),
            None => Ok(Vec::new()),
          }
        },
        Err(msg) => return Err(msg)
      }
    },
    Some(cache_size) => {
      let mut buffer = Vec::new();
      match define_size_to_load(reader, cache_size, size) {
        Some(required_size) => {
          match load_data(&mut reader, required_size) {
            Ok(optional_data) => {
              match optional_data {
                Some(full_data) => {
                  match reader.http_reader {
                    Some(ref mut http_reader) => {
                      http_reader.buf.append_data(&full_data);
                      buffer = http_reader.buf.get_data(size);
                    },
                    None => panic!("Missing Http Reader"),
                  }
                },
                None => {
                  return Ok(Vec::new())
                },
              }
            },
            Err(msg) => {
              return Err(msg)
            }
          }
        },
        None => {
          match reader.http_reader {
            Some(ref mut http_reader) => {
              buffer = http_reader.buf.get_data(size);
            },
            None => return Err("Missing Http Reader".to_string()),
          };
        },
      }
      Ok(buffer)
    }
  }
}

pub fn get_position(reader: &Reader) -> Result<u64, String> {

  match reader.cache_size {
    None => {
      match reader.http_reader {
        Some(ref http_reader) => {
          Ok(http_reader.position)
        },
        None => Err("missing HTTP reader".to_string()),
      }
    },
    Some(_cache_size) => {
      match reader.http_reader {
        Some(ref http_reader) => {
          Ok(http_reader.position - http_reader.buf.get_cached_size() as u64)
        },
        None => Err("missing HTTP reader".to_string()),
      }
    }
  }
}

pub fn get_size(reader: &mut Reader) -> Result<u64, String> {

  let _data = read(reader, 1);

  match reader.http_reader {
      Some(ref mut http_reader) => {
        match http_reader.size {
            Some(length) => Ok(length),
            None => Err("missing HTTP header".to_string()),
        }
      },
      None => Err("missing HTTP reader".to_string()),
  }
}

pub fn seek(mut reader: &mut Reader, seek: SeekFrom) -> Result<u64, String> {
  // println!("Seek");

  let mut require_reset_buffer : bool = false;
  let mut position : u64 = 0;

  match reader.http_reader {
    Some(ref mut http_reader) => {
      match seek {
        SeekFrom::Start(value) => {
          require_reset_buffer = true;
          http_reader.position = value;
          position = http_reader.position
        },
        SeekFrom::End(value) => {
          require_reset_buffer = true;
          http_reader.position = value as u64;
          position = http_reader.position
        },
        SeekFrom::Current(value) => {
          // println!("position {:?}", http_reader.position);
          let mut new_position = http_reader.position;
          // new_position -= http_reader.buffer.len() as u64;
          new_position += value as u64;

          // println!("new {:?} > {:?} + {:?}", new_position, http_reader.position, http_reader.buf.get_cached_size());

          if new_position > http_reader.position + http_reader.buf.get_cached_size() as u64 {
            require_reset_buffer = true;
            http_reader.position = new_position - http_reader.buf.get_cached_size() as u64;
            // println!("new position == {:?}", http_reader.position);
            position = http_reader.position
          } else {
            // println!("split_off {:?} at {:?}", http_reader.buf.get_cached_size(), value as usize);
            let _seek_data = http_reader.buf.get_data(value as usize);
          }
        }
      }
    },
    None => return Err("missing HTTP reader".to_string()),
  }

  if require_reset_buffer == true {
    match reset_buffer(reader) {
      Ok(_) => {},
      Err(msg) => return Err(msg)
    }
  }

  Ok(position)
}

fn reset_buffer(reader: &mut Reader) -> Result<(), String> {
  match reader.http_reader {
    Some(ref mut http_reader) => {
      http_reader.buf.reset();
      Ok(())
    },
    None => Err("missing HTTP reader".to_string()),
  }
}
<commit_msg>rename buf to buffer in HTTP reader<commit_after>
use std::io::{Read, SeekFrom};
use std::cmp;

use hyper;
use hyper::Error;
use hyper::client::Client;
use hyper::client::response::Response;
use hyper::header::ByteRangeSpec;
use hyper::header::ByteRangeSpec::FromTo;
use hyper::header::Range::Bytes;
use hyper::header::{ContentLength, ContentRange, ContentRangeSpec};

use reader::ReaderKind;
use reader::Reader;
use buffer::Buffer;

#[derive(Debug)]
pub struct HttpReader {
  position: u64,
  size: Option<u64>,
  buffer: Buffer
}

impl HttpReader {
  fn create(content_length: Option<u64>) -> HttpReader {
    HttpReader{
      position: 0,
      size: content_length,
      buffer: Buffer::create()
    }
  }
}

pub fn exists(filename: &String) -> bool {
  let client = Client::new();
  match client.head(filename).send() {
    Ok(resp) => resp.status == hyper::Ok,
    Err(_) => false
  }
}

fn get_head(filename: &String) -> Result<Response, Error> {
  let client = Client::new();
  client.head(filename).send()
}

fn get_content_length(response: &Response) -> Option<u64> {
  match response.headers.get::<ContentLength>() {
    Some(length) => Some(**length as u64),
    None => None
  }
}

fn get_content_range(response: &Response) -> Result<Option<u64>, String> {
  match response.headers.get::<ContentRange>() {
    Some(content_range) => {
      match content_range.clone() {
        ContentRange(ContentRangeSpec::Bytes{
            range: _range,
            instance_length: length
          }) => {
          Ok(length)
        },
        ContentRange(ContentRangeSpec::Unregistered{unit: _unit, resp: _resp}) => {
          Err("Unregistered, actually unsupported".to_string())
        }
      }
    },
    None =>
      Err("Missing content_range".to_string()),
  }
}

pub fn open(filename: &String) -> Result<Reader, String> {
  match get_head(filename) {
    Err(error) => Err(error.to_string()),
    Ok(response) => {

      let content_length = get_content_length(&response);
      let http_reader = HttpReader::create(content_length);

      let reader = Reader{
        filename: filename.to_string(),
        mode: ReaderKind::Http,
        file: None,
        cache_size: None,
        http_reader: Some(http_reader)
      };

      Ok(reader)
    }
  }
}

fn get_data_range(position: u64, size: usize) -> Vec<ByteRangeSpec> {
  let start = position;
  let end = position + (size - 1) as u64;

  vec![FromTo(start, end)]
}

fn load_data(reader: &mut Reader, size: usize) -> Result<Option<Vec<u8>>, String> {

  info!("make HTTP request with request {:?} bytes", size);
  match reader.http_reader {
    None => Err("missing HTTP reader".to_string()),
    Some(ref mut http_reader) => {

      match http_reader.size {
          Some(size) => {
            if http_reader.position >= size {
              return Ok(None)
            }
          },
          None => (),
      };

      let range = get_data_range(http_reader.position, size);

      let client = Client::new();
      let request =
        client
        .get(&reader.filename)
        .header(Bytes(range));

      let mut response = try!(request.send().map_err(|e| e.to_string()));

      let mut loaded_size : u64 = 0;
      {
        match get_content_length(&response) {
            Some(content_length) => loaded_size = content_length,
            None => return Err("Missing content_length".to_string()),
        }

        match get_content_range(&response) {
          Ok(length) => http_reader.size = length,
          Err(msg) => return Err(msg),
        }
      }

      match loaded_size {
        0 => Err("Bad request range".to_string()),
        _ => {
          let mut body = vec![0; loaded_size as usize];
          try!(Read::read_exact(&mut response, &mut body).map_err(|e| e.to_string()));

          http_reader.position = http_reader.position + loaded_size as u64;
          Ok(Some(body))
        }
      }
    }
  }
}

fn define_size_to_load(reader: &Reader, cache_size: usize, size: usize) -> Option<usize> {
  match reader.http_reader {
    Some(ref http_reader) => {
      match http_reader.buffer.get_cached_size() < size {
        true => Some(cmp::max(cache_size, size)),
        _ => None
      }
    },
    None => panic!("Missing Http Reader"),
  }
}

pub fn read(mut reader: &mut Reader, size: usize) -> Result<Vec<u8>, String> {
  debug!("read {:?} bytes", size);
  match reader.cache_size {
    None => {
      match load_data(reader, size) {
        Ok(optional_data) => {
          match optional_data {
            Some(data) => Ok(data),
            None => Ok(Vec::new()),
          }
        },
        Err(msg) => return Err(msg)
      }
    },
    Some(cache_size) => {
      let mut buffer = Vec::new();
      match define_size_to_load(reader, cache_size, size) {
        Some(required_size) => {
          match load_data(&mut reader, required_size) {
            Ok(optional_data) => {
              match optional_data {
                Some(full_data) => {
                  match reader.http_reader {
                    Some(ref mut http_reader) => {
                      http_reader.buffer.append_data(&full_data);
                      buffer = http_reader.buffer.get_data(size);
                    },
                    None => panic!("Missing Http Reader"),
                  }
                },
                None => {
                  return Ok(Vec::new())
                },
              }
            },
            Err(msg) => {
              return Err(msg)
            }
          }
        },
        None => {
          match reader.http_reader {
            Some(ref mut http_reader) => {
              buffer = http_reader.buffer.get_data(size);
            },
            None => return Err("Missing Http Reader".to_string()),
          };
        },
      }
      Ok(buffer)
    }
  }
}

pub fn get_position(reader: &Reader) -> Result<u64, String> {

  match reader.cache_size {
    None => {
      match reader.http_reader {
        Some(ref http_reader) => {
          Ok(http_reader.position)
        },
        None => Err("missing HTTP reader".to_string()),
      }
    },
    Some(_cache_size) => {
      match reader.http_reader {
        Some(ref http_reader) => {
          Ok(http_reader.position - http_reader.buffer.get_cached_size() as u64)
        },
        None => Err("missing HTTP reader".to_string()),
      }
    }
  }
}

pub fn get_size(reader: &mut Reader) -> Result<u64, String> {

  let _data = read(reader, 1);

  match reader.http_reader {
      Some(ref mut http_reader) => {
        match http_reader.size {
            Some(length) => Ok(length),
            None => Err("missing HTTP header".to_string()),
        }
      },
      None => Err("missing HTTP reader".to_string()),
  }
}

pub fn seek(mut reader: &mut Reader, seek: SeekFrom) -> Result<u64, String> {
  // println!("Seek");

  let mut require_reset_buffer : bool = false;
  let mut position : u64 = 0;

  match reader.http_reader {
    Some(ref mut http_reader) => {
      match seek {
        SeekFrom::Start(value) => {
          require_reset_buffer = true;
          http_reader.position = value;
          position = http_reader.position
        },
        SeekFrom::End(value) => {
          require_reset_buffer = true;
          http_reader.position = value as u64;
          position = http_reader.position
        },
        SeekFrom::Current(value) => {
          // println!("position {:?}", http_reader.position);
          let mut new_position = http_reader.position;
          // new_position -= http_reader.buffer.len() as u64;
          new_position += value as u64;

          // println!("new {:?} > {:?} + {:?}", new_position, http_reader.position, http_reader.buffer.get_cached_size());

          if new_position > http_reader.position + http_reader.buffer.get_cached_size() as u64 {
            require_reset_buffer = true;
            http_reader.position = new_position - http_reader.buffer.get_cached_size() as u64;
            // println!("new position == {:?}", http_reader.position);
            position = http_reader.position
          } else {
            // println!("split_off {:?} at {:?}", http_reader.buffer.get_cached_size(), value as usize);
            let _seek_data = http_reader.buffer.get_data(value as usize);
          }
        }
      }
    },
    None => return Err("missing HTTP reader".to_string()),
  }

  if require_reset_buffer == true {
    match reset_buffer(reader) {
      Ok(_) => {},
      Err(msg) => return Err(msg)
    }
  }

  Ok(position)
}

fn reset_buffer(reader: &mut Reader) -> Result<(), String> {
  match reader.http_reader {
    Some(ref mut http_reader) => {
      http_reader.buffer.reset();
      Ok(())
    },
    None => Err("missing HTTP reader".to_string()),
  }
}
<|endoftext|>


<commit_before>#![feature(test)]
#[macro_use]
extern crate abomonation;
extern crate test;

use test::Bencher;
use abomonation::{Abomonation, encode, decode};

#[bench]
fn bench_populate(b: &mut Bencher) {
    b.iter(|| {
        Log::new()
    });
}

#[bench]
fn bench_serialize(b: &mut Bencher) {
    let log = Log::new();
    let mut bytes = vec![];
    unsafe { encode(&log, &mut bytes); }
    b.bytes = bytes.len() as u64;
    b.iter(|| {
        bytes.clear();
        unsafe { encode(&log, &mut bytes); }
        test::black_box(&bytes);
    });
}

#[bench]
fn bench_deserialize(b: &mut Bencher) {
    let log = Log::new();
    let mut bytes = vec![];
    unsafe { encode(&log, &mut bytes); }
    b.bytes = bytes.len() as u64;
    b.iter(|| {
        test::black_box(unsafe { decode::<Log>(&mut bytes) });
    });
}

#[bench]
fn bench_deserialize_assert(b: &mut Bencher) {
    let log = Log::new();
    let mut bytes = vec![];
    unsafe { encode(&log, &mut bytes); }
    b.bytes = bytes.len() as u64;
    b.iter(|| {
        assert!(unsafe { decode::<Log>(&mut bytes) }.unwrap().0 == &log);
    });
}

unsafe_abomonate!(Http : content_type, user_agent, referer, request_uri);
unsafe_abomonate!(Origin : ip, hostname);
unsafe_abomonate!(Log : http, origin, server_ip, server_name, remote_ip, ray_id);

#[derive(Eq, PartialEq)]
pub struct Http {
    protocol: HttpProtocol,
    status: u32,
    host_status: u32,
    up_status: u32,
    method: HttpMethod,
    content_type: String,
    user_agent: String,
    referer: String,
    request_uri: String,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum HttpProtocol {
    HTTP_PROTOCOL_UNKNOWN,
    HTTP10,
    HTTP11,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum HttpMethod {
    METHOD_UNKNOWN,
    GET,
    POST,
    DELETE,
    PUT,
    HEAD,
    PURGE,
    OPTIONS,
    PROPFIND,
    MKCOL,
    PATCH,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum CacheStatus {
    CACHESTATUS_UNKNOWN,
    Miss,
    Expired,
    Hit,
}

#[derive(Eq, PartialEq)]
pub struct Origin {
    ip: String,
    port: u32,
    hostname: String,
    protocol: OriginProtocol,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum OriginProtocol {
    ORIGIN_PROTOCOL_UNKNOWN,
    HTTP,
    HTTPS,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum ZonePlan {
    ZONEPLAN_UNKNOWN,
    FREE,
    PRO,
    BIZ,
    ENT,
}

#[derive(Eq, PartialEq)]
pub enum Country {
	UNKNOWN,
	A1,
	A2,
	O1,
	AD,
	AE,
	AF,
	AG,
	AI,
	AL,
	AM,
	AO,
	AP,
	AQ,
	AR,
	AS,
	AT,
	AU,
	AW,
	AX,
	AZ,
	BA,
	BB,
	BD,
	BE,
	BF,
	BG,
	BH,
	BI,
	BJ,
	BL,
	BM,
	BN,
	BO,
	BQ,
	BR,
	BS,
	BT,
	BV,
	BW,
	BY,
	BZ,
	CA,
	CC,
	CD,
	CF,
	CG,
	CH,
	CI,
	CK,
	CL,
	CM,
	CN,
	CO,
	CR,
	CU,
	CV,
	CW,
	CX,
	CY,
	CZ,
	DE,
	DJ,
	DK,
	DM,
	DO,
	DZ,
	EC,
	EE,
	EG,
	EH,
	ER,
	ES,
	ET,
	EU,
	FI,
	FJ,
	FK,
	FM,
	FO,
	FR,
	GA,
	GB,
	GD,
	GE,
	GF,
	GG,
	GH,
	GI,
	GL,
	GM,
	GN,
	GP,
	GQ,
	GR,
	GS,
	GT,
	GU,
	GW,
	GY,
	HK,
	HM,
	HN,
	HR,
	HT,
	HU,
	ID,
	IE,
	IL,
	IM,
	IN,
	IO,
	IQ,
	IR,
	IS,
	IT,
	JE,
	JM,
	JO,
	JP,
	KE,
	KG,
	KH,
	KI,
	KM,
	KN,
	KP,
	KR,
	KW,
	KY,
	KZ,
	LA,
	LB,
	LC,
	LI,
	LK,
	LR,
	LS,
	LT,
	LU,
	LV,
	LY,
	MA,
	MC,
	MD,
	ME,
	MF,
	MG,
	MH,
	MK,
	ML,
	MM,
	MN,
	MO,
	MP,
	MQ,
	MR,
	MS,
	MT,
	MU,
	MV,
	MW,
	MX,
	MY,
	MZ,
	NA,
	NC,
	NE,
	NF,
	NG,
	NI,
	NL,
	NO,
	NP,
	NR,
	NU,
	NZ,
	OM,
	PA,
	PE,
	PF,
	PG,
	PH,
	PK,
	PL,
	PM,
	PN,
	PR,
	PS,
	PT,
	PW,
	PY,
	QA,
	RE,
	RO,
	RS,
	RU,
	RW,
	SA,
	SB,
	SC,
	SD,
	SE,
	SG,
	SH,
	SI,
	SJ,
	SK,
	SL,
	SM,
	SN,
	SO,
	SR,
	SS,
	ST,
	SV,
	SX,
	SY,
	SZ,
	TC,
	TD,
	TF,
	TG,
	TH,
	TJ,
	TK,
	TL,
	TM,
	TN,
	TO,
	TR,
	TT,
	TV,
	TW,
	TZ,
	UA,
	UG,
	UM,
	US,
	UY,
	UZ,
	VA,
	VC,
	VE,
	VG,
	VI,
	VN,
	VU,
	WF,
	WS,
	XX,
	YE,
	YT,
	ZA,
	ZM,
	ZW,
}

#[derive(Eq, PartialEq)]
pub struct Log {
    timestamp: i64,
    zone_id: u32,
    zone_plan: ZonePlan,
    http: Http,
    origin: Origin,
    country: Country,
    cache_status: CacheStatus,
    server_ip: String,
    server_name: String,
    remote_ip: String,
    bytes_dlv: u64,
    ray_id: String,
}

impl Log {
    pub fn new() -> Log {
        Log {
            timestamp: 2837513946597,
            zone_id: 123456,
            zone_plan: ZonePlan::FREE,
            http: Http {
                protocol: HttpProtocol::HTTP11,
                status: 200,
                host_status: 503,
                up_status: 520,
                method: HttpMethod::GET,
                content_type: "text/html".to_owned(),
                user_agent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36".to_string(),
                referer: "https://www.cloudflare.com/".to_owned(),
                request_uri: "/cdn-cgi/trace".to_owned(),
            },
            origin: Origin {
                ip: "1.2.3.4".to_owned(),
                port: 8000,
                hostname: "www.example.com".to_owned(),
                protocol: OriginProtocol::HTTPS,
            },
            country: Country::US,
            cache_status: CacheStatus::Hit,
            server_ip: "192.168.1.1".to_owned(),
            server_name: "metal.cloudflare.com".to_owned(),
            remote_ip: "10.1.2.3".to_owned(),
            bytes_dlv: 123456,
            ray_id: "10c73629cce30078-LAX".to_owned(),
        }
    }
}
<commit_msg>forgot one to_string -> to_owned<commit_after>#![feature(test)]
#[macro_use]
extern crate abomonation;
extern crate test;

use test::Bencher;
use abomonation::{Abomonation, encode, decode};

#[bench]
fn bench_populate(b: &mut Bencher) {
    b.iter(|| {
        Log::new()
    });
}

#[bench]
fn bench_serialize(b: &mut Bencher) {
    let log = Log::new();
    let mut bytes = vec![];
    unsafe { encode(&log, &mut bytes); }
    b.bytes = bytes.len() as u64;
    b.iter(|| {
        bytes.clear();
        unsafe { encode(&log, &mut bytes); }
        test::black_box(&bytes);
    });
}

#[bench]
fn bench_deserialize(b: &mut Bencher) {
    let log = Log::new();
    let mut bytes = vec![];
    unsafe { encode(&log, &mut bytes); }
    b.bytes = bytes.len() as u64;
    b.iter(|| {
        test::black_box(unsafe { decode::<Log>(&mut bytes) });
    });
}

#[bench]
fn bench_deserialize_assert(b: &mut Bencher) {
    let log = Log::new();
    let mut bytes = vec![];
    unsafe { encode(&log, &mut bytes); }
    b.bytes = bytes.len() as u64;
    b.iter(|| {
        assert!(unsafe { decode::<Log>(&mut bytes) }.unwrap().0 == &log);
    });
}

unsafe_abomonate!(Http : content_type, user_agent, referer, request_uri);
unsafe_abomonate!(Origin : ip, hostname);
unsafe_abomonate!(Log : http, origin, server_ip, server_name, remote_ip, ray_id);

#[derive(Eq, PartialEq)]
pub struct Http {
    protocol: HttpProtocol,
    status: u32,
    host_status: u32,
    up_status: u32,
    method: HttpMethod,
    content_type: String,
    user_agent: String,
    referer: String,
    request_uri: String,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum HttpProtocol {
    HTTP_PROTOCOL_UNKNOWN,
    HTTP10,
    HTTP11,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum HttpMethod {
    METHOD_UNKNOWN,
    GET,
    POST,
    DELETE,
    PUT,
    HEAD,
    PURGE,
    OPTIONS,
    PROPFIND,
    MKCOL,
    PATCH,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum CacheStatus {
    CACHESTATUS_UNKNOWN,
    Miss,
    Expired,
    Hit,
}

#[derive(Eq, PartialEq)]
pub struct Origin {
    ip: String,
    port: u32,
    hostname: String,
    protocol: OriginProtocol,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum OriginProtocol {
    ORIGIN_PROTOCOL_UNKNOWN,
    HTTP,
    HTTPS,
}

#[allow(non_camel_case_types)]
#[derive(Eq, PartialEq)]
pub enum ZonePlan {
    ZONEPLAN_UNKNOWN,
    FREE,
    PRO,
    BIZ,
    ENT,
}

#[derive(Eq, PartialEq)]
pub enum Country {
	UNKNOWN,
	A1,
	A2,
	O1,
	AD,
	AE,
	AF,
	AG,
	AI,
	AL,
	AM,
	AO,
	AP,
	AQ,
	AR,
	AS,
	AT,
	AU,
	AW,
	AX,
	AZ,
	BA,
	BB,
	BD,
	BE,
	BF,
	BG,
	BH,
	BI,
	BJ,
	BL,
	BM,
	BN,
	BO,
	BQ,
	BR,
	BS,
	BT,
	BV,
	BW,
	BY,
	BZ,
	CA,
	CC,
	CD,
	CF,
	CG,
	CH,
	CI,
	CK,
	CL,
	CM,
	CN,
	CO,
	CR,
	CU,
	CV,
	CW,
	CX,
	CY,
	CZ,
	DE,
	DJ,
	DK,
	DM,
	DO,
	DZ,
	EC,
	EE,
	EG,
	EH,
	ER,
	ES,
	ET,
	EU,
	FI,
	FJ,
	FK,
	FM,
	FO,
	FR,
	GA,
	GB,
	GD,
	GE,
	GF,
	GG,
	GH,
	GI,
	GL,
	GM,
	GN,
	GP,
	GQ,
	GR,
	GS,
	GT,
	GU,
	GW,
	GY,
	HK,
	HM,
	HN,
	HR,
	HT,
	HU,
	ID,
	IE,
	IL,
	IM,
	IN,
	IO,
	IQ,
	IR,
	IS,
	IT,
	JE,
	JM,
	JO,
	JP,
	KE,
	KG,
	KH,
	KI,
	KM,
	KN,
	KP,
	KR,
	KW,
	KY,
	KZ,
	LA,
	LB,
	LC,
	LI,
	LK,
	LR,
	LS,
	LT,
	LU,
	LV,
	LY,
	MA,
	MC,
	MD,
	ME,
	MF,
	MG,
	MH,
	MK,
	ML,
	MM,
	MN,
	MO,
	MP,
	MQ,
	MR,
	MS,
	MT,
	MU,
	MV,
	MW,
	MX,
	MY,
	MZ,
	NA,
	NC,
	NE,
	NF,
	NG,
	NI,
	NL,
	NO,
	NP,
	NR,
	NU,
	NZ,
	OM,
	PA,
	PE,
	PF,
	PG,
	PH,
	PK,
	PL,
	PM,
	PN,
	PR,
	PS,
	PT,
	PW,
	PY,
	QA,
	RE,
	RO,
	RS,
	RU,
	RW,
	SA,
	SB,
	SC,
	SD,
	SE,
	SG,
	SH,
	SI,
	SJ,
	SK,
	SL,
	SM,
	SN,
	SO,
	SR,
	SS,
	ST,
	SV,
	SX,
	SY,
	SZ,
	TC,
	TD,
	TF,
	TG,
	TH,
	TJ,
	TK,
	TL,
	TM,
	TN,
	TO,
	TR,
	TT,
	TV,
	TW,
	TZ,
	UA,
	UG,
	UM,
	US,
	UY,
	UZ,
	VA,
	VC,
	VE,
	VG,
	VI,
	VN,
	VU,
	WF,
	WS,
	XX,
	YE,
	YT,
	ZA,
	ZM,
	ZW,
}

#[derive(Eq, PartialEq)]
pub struct Log {
    timestamp: i64,
    zone_id: u32,
    zone_plan: ZonePlan,
    http: Http,
    origin: Origin,
    country: Country,
    cache_status: CacheStatus,
    server_ip: String,
    server_name: String,
    remote_ip: String,
    bytes_dlv: u64,
    ray_id: String,
}

impl Log {
    pub fn new() -> Log {
        Log {
            timestamp: 2837513946597,
            zone_id: 123456,
            zone_plan: ZonePlan::FREE,
            http: Http {
                protocol: HttpProtocol::HTTP11,
                status: 200,
                host_status: 503,
                up_status: 520,
                method: HttpMethod::GET,
                content_type: "text/html".to_owned(),
                user_agent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36".to_owned(),
                referer: "https://www.cloudflare.com/".to_owned(),
                request_uri: "/cdn-cgi/trace".to_owned(),
            },
            origin: Origin {
                ip: "1.2.3.4".to_owned(),
                port: 8000,
                hostname: "www.example.com".to_owned(),
                protocol: OriginProtocol::HTTPS,
            },
            country: Country::US,
            cache_status: CacheStatus::Hit,
            server_ip: "192.168.1.1".to_owned(),
            server_name: "metal.cloudflare.com".to_owned(),
            remote_ip: "10.1.2.3".to_owned(),
            bytes_dlv: 123456,
            ray_id: "10c73629cce30078-LAX".to_owned(),
        }
    }
}
<|endoftext|>


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

use core::prelude::*;

#[deriving_eq]
pub enum mode {
    mode_compile_fail,
    mode_run_fail,
    mode_run_pass,
    mode_pretty,
    mode_debug_info,
}

pub struct config {
    // The library paths required for running the compiler
    compile_lib_path: ~str,

    // The library paths required for running compiled programs
    run_lib_path: ~str,

    // The rustc executable
    rustc_path: Path,

    // The directory containing the tests to run
    src_base: Path,

    // The directory where programs should be built
    build_base: Path,

    // Directory for auxiliary libraries
    aux_base: Path,

    // The name of the stage being built (stage1, etc)
    stage_id: ~str,

    // The test mode, compile-fail, run-fail, run-pass
    mode: mode,

    // Run ignored tests
    run_ignored: bool,

    // Only run tests that match this filter
    filter: Option<~str>,

    // Write out a parseable log of tests that were run
    logfile: Option<Path>,

    // A command line to prefix program execution with,
    // for running under valgrind
    runtool: Option<~str>,

    // Flags to pass to the compiler
    rustcflags: Option<~str>,

    // Run tests using the JIT
    jit: bool,

    // Explain what's going on
    verbose: bool

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

use core::prelude::*;

#[deriving(Eq)]
pub enum mode {
    mode_compile_fail,
    mode_run_fail,
    mode_run_pass,
    mode_pretty,
    mode_debug_info,
}

pub struct config {
    // The library paths required for running the compiler
    compile_lib_path: ~str,

    // The library paths required for running compiled programs
    run_lib_path: ~str,

    // The rustc executable
    rustc_path: Path,

    // The directory containing the tests to run
    src_base: Path,

    // The directory where programs should be built
    build_base: Path,

    // Directory for auxiliary libraries
    aux_base: Path,

    // The name of the stage being built (stage1, etc)
    stage_id: ~str,

    // The test mode, compile-fail, run-fail, run-pass
    mode: mode,

    // Run ignored tests
    run_ignored: bool,

    // Only run tests that match this filter
    filter: Option<~str>,

    // Write out a parseable log of tests that were run
    logfile: Option<Path>,

    // A command line to prefix program execution with,
    // for running under valgrind
    runtool: Option<~str>,

    // Flags to pass to the compiler
    rustcflags: Option<~str>,

    // Run tests using the JIT
    jit: bool,

    // Explain what's going on
    verbose: bool

}
<|endoftext|>


<commit_before>use hyper::Url;

/// Supported protocols
#[derive(Debug)]
pub enum Protocol {
    HTTP,
    HTTPS,
}

/// Returns an Option type, that contains a Protocol enum
pub fn get_protocol(url: &str) -> Option<Protocol> {
    match Url::parse(url) {
        Ok(url) => match url.scheme() {
            "http" => Some(Protocol::HTTP),
            "https" => Some(Protocol::HTTPS),
            _ => None,
        },
        Err(error) => {
            warning!(&format!("Canno't extract the protocol from the URL: {}", error));
            None
        }
    }
}<commit_msg>Change error message<commit_after>use hyper::Url;

/// Supported protocols
#[derive(Debug)]
pub enum Protocol {
    HTTP,
    HTTPS,
}

/// Returns an Option type, that contains a Protocol enum
pub fn get_protocol(url: &str) -> Option<Protocol> {
    match Url::parse(url) {
        Ok(url) => match url.scheme() {
            "http" => Some(Protocol::HTTP),
            "https" => Some(Protocol::HTTPS),
            _ => None,
        },
        Err(error) => {
            warning!(&format!("Error extracting the protocol: {}", error));
            None
        }
    }
}<|endoftext|>


<commit_before>#![feature(phase)]

#[phase(plugin, link)]
extern crate itertools;

use itertools::Itertools;

fn main() {
    println!("24 days of Rust - itertools (day 7)");
    let mut words = "hello supercalifragilisticexpialidocious programmer".words();
    words.apply(|word| println!("{} is {} characters long", word, word.len()));
    let even = range(1, 10u).map(|x| x * 2);
    let odd = range(1, 5u).map(|x| x * 2 + 1);
    println!("{}", even.interleave(odd).collect::<Vec<_>>());
    let it = range(1, 10u);
    println!("{}", it.intersperse(15u).collect::<Vec<_>>());
}
<commit_msg>Macros example.<commit_after>#![feature(phase)]

#[phase(plugin, link)]
extern crate itertools;

use std::iter::AdditiveIterator;
use itertools::Itertools;

fn main() {
    println!("24 days of Rust - itertools (day 7)");
    let mut words = "hello supercalifragilisticexpialidocious programmer".words();
    words.apply(|word| println!("{} is {} characters long", word, word.len()));
    let even = range(1, 10u).map(|x| x * 2);
    let odd = range(1, 5u).map(|x| x * 2 + 1);
    println!("{}", even.interleave(odd).collect::<Vec<_>>());
    let it = range(1, 10u);
    println!("{}", it.intersperse(15u).collect::<Vec<_>>());
    let numbers = range(1, 4u);
    let chars = vec!['a', 'b', 'c'];
    for (i, c) in iproduct!(numbers, chars.iter()) {
        println!("{}: {}", i, c);
    }
    let log = "GET / 4096\nGET /home/ 16301\nPOST /home/ 49\nGET / 4096\n";
    let lines = log.lines();
    let rows = icompr!(line.words().collect::<Vec<_>>() for line in lines);
    let bytes = icompr!(row[2] for row in rows if row[0] != "POST");
    let total = icompr!(from_str::<uint>(b).unwrap() for b in bytes).sum();
    println!("Total GET throughput: {} bytes", total);
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate time;
extern crate timely;
extern crate differential_dataflow;

use std::hash::Hash;
use std::mem;
use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::*;
use timely::dataflow::operators::*;

use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::operators::group::{GroupUnsigned, GroupBy};
use differential_dataflow::operators::join::{JoinUnsigned, JoinBy};
use differential_dataflow::collection::LeastUpperBound;

type Node = u32;
type Edge = (Node, Node);

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: u32 = std::env::args().nth(2).unwrap().parse().unwrap();

    timely::execute_from_args(std::env::args().skip(3), move |computation| {

        let start = time::precise_time_s();
        let start2 = start.clone();

        let mut input = computation.scoped::<u64,_,_>(|scope| {

            let (input, edges) = scope.new_input();
            let mut edges = Collection::new(edges);

            edges = _trim_and_flip(&edges);
            edges = _trim_and_flip(&edges);
            edges = _strongly_connected(&edges);

            let mut counter = 0;
            edges.consolidate_by(|x| x.0)
                 .inspect_batch(move |t, x| {
                     counter += x.len();
                     println!("{}s:\tobserved at {:?}: {:?} changes",
                              ((time::precise_time_s() - start2)) - (t.inner as f64),
                              t, counter)
                 });

            input
        });

        if computation.index() == 0 {

            println!("determining SCC of {} nodes, {} edges:", nodes, edges);

            let seed: &[_] = &[1, 2, 3, 4];
            let mut rng1: StdRng = SeedableRng::from_seed(seed);
            let mut rng2: StdRng = SeedableRng::from_seed(seed);

            rng1.gen::<f64>();
            rng2.gen::<f64>();

            for index in 0..edges {
                let edge = (rng1.gen_range(0, nodes), rng1.gen_range(0, nodes));
                // println!("edge: {:?}", edge);
                input.send((edge, 1));
                if (index % (1 << 12)) == 0 {
                    computation.step();
                }
            }

            println!("input ingested after {}", time::precise_time_s() - start);

            // while computation.step() {
            //     if time::precise_time_s() - start >= *input.epoch() as f64 {
            //         let change_count = 1;
            //         for _ in 0..change_count {
            //             input.give(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), 1));
            //             input.give(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)),-1));
            //         }
            //         let next_epoch = *input.epoch() + 1;
            //         input.advance_to(next_epoch);
            //     }
            // }
        }

        input.close();
    });
}

fn _trim_and_flip<G: Scope>(graph: &Collection<G, Edge>) -> Collection<G, Edge>
where G::Timestamp: LeastUpperBound {
        graph.iterate(|edges| {
            let inner = graph.enter(&edges.scope());
            edges.map(|(x,_)| x)
            //   .threshold(|&x| x, |i| (Vec::new(), i), |_, w| if w > 0 { 1 } else { 0 })
                 .group_by_u(|x|(x,()), |&x,_| x, |_,_,target| target.push(((),1)))
                 .join_by_u(&inner, |x| (x,()), |(s,d)| (d,s), |&d,_,&s| (s,d))
        }).map_in_place(|x| mem::swap(&mut x.0, &mut x.1))
}

fn _strongly_connected<G: Scope>(graph: &Collection<G, Edge>) -> Collection<G, Edge>
where G::Timestamp: LeastUpperBound+Hash {
    graph.iterate(|inner| {
        let edges = graph.enter(&inner.scope());
        let trans = edges.map_in_place(|x| mem::swap(&mut x.0, &mut x.1));
        _trim_edges(&_trim_edges(inner, &edges), &trans)
    })
}

fn _trim_edges<G: Scope>(cycle: &Collection<G, Edge>, edges: &Collection<G, Edge>)
    -> Collection<G, Edge> where G::Timestamp: LeastUpperBound+Hash {

    let nodes = edges.map_in_place(|x| mem::swap(&mut x.0, &mut x.1))
                     .consolidate_by(|&x| x.0);

    let labels = _reachability(&cycle, &nodes);

    edges.join_map_u(&labels, |&e1,&e2,&l1| (e2,(e1,l1)))
         .join_map_u(&labels, |&e2,&(e1,l1),&l2| ((e1,e2),(l1,l2)))
         .filter(|&(_,(l1,l2))| l1 == l2)
         .map(|((x1,x2),_)| (x2,x1))
    //   .consolidate_by(|x| x.0)
}

fn _reachability<G: Scope>(edges: &Collection<G, Edge>, nodes: &Collection<G, (Node, Node)>) -> Collection<G, Edge>
where G::Timestamp: LeastUpperBound+Hash {

    edges.filter(|_| false)
         .iterate(|inner| {
             let edges = edges.enter(&inner.scope());
             let nodes = nodes.enter_at(&inner.scope(), |r| 256 * (64 - ((r.0).0 as u64).leading_zeros() as u64));

             _improve_labels(inner, &edges, &nodes)
         })
        //  .consolidate_by(|x| x.0)
}

fn _improve_labels<G: Scope>(labels: &Collection<G, (Node, Node)>,
                                   edges: &Collection<G, Edge>,
                                   nodes: &Collection<G, (Node, Node)>)
    -> Collection<G, (Node, Node)>
where G::Timestamp: LeastUpperBound {

    labels.join_map_u(&edges, |_k,l,d| (*d,*l))
          .concat(&nodes)
          .group_u(|_, s, t| t.push((*s.peek().unwrap().0, 1)))
}
<commit_msg>minor glitch<commit_after>extern crate rand;
extern crate time;
extern crate timely;
extern crate differential_dataflow;

use std::hash::Hash;
use std::mem;
use rand::{Rng, SeedableRng, StdRng};

use timely::dataflow::*;
use timely::dataflow::operators::*;

use differential_dataflow::Collection;
use differential_dataflow::operators::*;
use differential_dataflow::operators::group::{GroupUnsigned, GroupBy};
use differential_dataflow::operators::join::{JoinUnsigned, JoinBy};
use differential_dataflow::collection::LeastUpperBound;

type Node = u32;
type Edge = (Node, Node);

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: u32 = std::env::args().nth(2).unwrap().parse().unwrap();

    timely::execute_from_args(std::env::args().skip(3), move |computation| {

        let start = time::precise_time_s();
        let start2 = start.clone();

        let mut input = computation.scoped::<u64,_,_>(|scope| {

            let (input, edges) = scope.new_input();
            let mut edges = Collection::new(edges);

            edges = _trim_and_flip(&edges);
            edges = _trim_and_flip(&edges);
            edges = _strongly_connected(&edges);

            let mut counter = 0;
            edges.consolidate_by(|x| x.0)
                 .inspect_batch(move |t, x| {
                     counter += x.len();
                     println!("{}s:\tobserved at {:?}: {:?} changes",
                              ((time::precise_time_s() - start2)) - (t.inner as f64),
                              t, counter)
                 });

            input
        });

        if computation.index() == 0 {

            println!("determining SCC of {} nodes, {} edges:", nodes, edges);

            let seed: &[_] = &[1, 2, 3, 4];
            let mut rng1: StdRng = SeedableRng::from_seed(seed);
            let mut rng2: StdRng = SeedableRng::from_seed(seed);

            rng1.gen::<f64>();
            rng2.gen::<f64>();

            for index in 0..edges {
                let edge = (rng1.gen_range(0, nodes), rng1.gen_range(0, nodes));
                // println!("edge: {:?}", edge);
                input.send((edge, 1));
                if (index % (1 << 12)) == 0 {
                    computation.step();
                }
            }

            println!("input ingested after {}", time::precise_time_s() - start);

            // while computation.step() {
            //     if time::precise_time_s() - start >= *input.epoch() as f64 {
            //         let change_count = 1;
            //         for _ in 0..change_count {
            //             input.give(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), 1));
            //             input.give(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)),-1));
            //         }
            //         let next_epoch = *input.epoch() + 1;
            //         input.advance_to(next_epoch);
            //     }
            // }
        }

        input.close();
    });
}

fn _trim_and_flip<G: Scope>(graph: &Collection<G, Edge>) -> Collection<G, Edge>
where G::Timestamp: LeastUpperBound {
        graph.iterate(|edges| {
            let inner = graph.enter(&edges.scope());
            edges.map(|(x,_)| x)
            //   .threshold(|&x| x, |i| (Vec::new(), i), |_, w| if w > 0 { 1 } else { 0 })
                 .group_by_u(|x|(x,()), |&x,_| x, |_,_,target| target.push(((),1)))
                 .join_by_u(&inner, |x| (x,()), |(s,d)| (d,s), |&d,_,&s| (s,d))
        }).map_in_place(|x| mem::swap(&mut x.0, &mut x.1))
}

fn _strongly_connected<G: Scope>(graph: &Collection<G, Edge>) -> Collection<G, Edge>
where G::Timestamp: LeastUpperBound+Hash {
    graph.iterate(|inner| {
        let edges = graph.enter(&inner.scope());
        let trans = edges.map_in_place(|x| mem::swap(&mut x.0, &mut x.1));
        _trim_edges(&_trim_edges(inner, &edges), &trans)
    })
}

fn _trim_edges<G: Scope>(cycle: &Collection<G, Edge>, edges: &Collection<G, Edge>)
    -> Collection<G, Edge> where G::Timestamp: LeastUpperBound+Hash {

    let nodes = edges.map_in_place(|x| x.0 = x.1)
                     .consolidate_by(|&x| x.0);

    let labels = _reachability(&cycle, &nodes);

    edges.join_map_u(&labels, |&e1,&e2,&l1| (e2,(e1,l1)))
         .join_map_u(&labels, |&e2,&(e1,l1),&l2| ((e1,e2),(l1,l2)))
         .filter(|&(_,(l1,l2))| l1 == l2)
         .map(|((x1,x2),_)| (x2,x1))
    //   .consolidate_by(|x| x.0)
}

fn _reachability<G: Scope>(edges: &Collection<G, Edge>, nodes: &Collection<G, (Node, Node)>) -> Collection<G, Edge>
where G::Timestamp: LeastUpperBound+Hash {

    edges.filter(|_| false)
         .iterate(|inner| {
             let edges = edges.enter(&inner.scope());
             let nodes = nodes.enter_at(&inner.scope(), |r| 256 * (64 - ((r.0).0 as u64).leading_zeros() as u64));

             _improve_labels(inner, &edges, &nodes)
         })
        //  .consolidate_by(|x| x.0)
}

fn _improve_labels<G: Scope>(labels: &Collection<G, (Node, Node)>,
                                   edges: &Collection<G, Edge>,
                                   nodes: &Collection<G, (Node, Node)>)
    -> Collection<G, (Node, Node)>
where G::Timestamp: LeastUpperBound {

    labels.join_map_u(&edges, |_k,l,d| (*d,*l))
          .concat(&nodes)
          .group_u(|_, s, t| t.push((*s.peek().unwrap().0, 1)))
}
<|endoftext|>


<commit_before>use std::cmp::PartialOrd;
use num::{Num, Signed, Zero, One, abs};
use {Anchor, Shape2D};

/// A rectangle type.
#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Default, Debug, Serialize, Deserialize)]
pub struct Rect<T: Copy> {
    /// Top left (closest to the origin) corner of the rectange.
    pub top: [T; 2],
    /// Size of the rectangle, all elements are assumed to always be positive.
    pub size: [T; 2],
}

impl<T> Rect<T>
    where T: Num + PartialOrd + Signed + Copy
{
    /// Create a new rectangle from two corner points.
    pub fn new<V: Into<[T; 2]>>(p1: V, p2: V) -> Rect<T> {
        let (p1, p2): ([T; 2], [T; 2]) = (p1.into(), p2.into());

        Rect {
            top: [*min(&p1[0], &p2[0]), *min(&p1[1], &p2[1])],
            size: [abs(p2[0] - p1[0]), abs(p2[1] - p1[1])],
        }
    }

    /// Get a point at an anchor position in the rectangle.
    pub fn point(&self, point: Anchor) -> [T; 2] {
        let one: T = One::one();
        let two = one + one;
        match point {
            Anchor::TopLeft => self.top,
            Anchor::TopRight => [self.top[0] + self.size[0], self.top[1]],
            Anchor::BottomLeft => [self.top[0], self.top[1] + self.size[1]],
            Anchor::BottomRight => {
                [self.top[0] + self.size[0], self.top[1] + self.size[1]]
            }
            Anchor::Top => [self.top[0] + self.size[0] / two, self.top[1]],
            Anchor::Left => [self.top[0], self.top[1] + self.size[1] / two],
            Anchor::Right => {
                [self.top[0] + self.size[0], self.top[1] + self.size[1] / two]
            }
            Anchor::Bottom => {
                [self.top[0] + self.size[0] / two, self.top[1] + self.size[1]]
            }
            Anchor::Center => {
                [self.top[0] + self.size[0] / two,
                 self.top[1] + self.size[1] / two]
            }
        }
    }

    /// Iterate tiles of the given size inside the rectangle.
    ///
    /// The tiles are ordered from left to right, then from top to bottom. The
    /// first tile snaps to the top left corner of the rectangle, and parts
    /// along the right and bottom edges of the rectangle are left uncovered
    /// if a whole tile will not fit in them.
    ///
    /// ```
    /// use calx_layout::Rect;
    ///
    /// let x = Rect::new([0, 0], [8, 16]);
    /// // To iterate integer points in the rectangle, just use [1, 1] tiles.
    /// assert_eq!(x.tiles([1, 1]).map(|t| t.top).next(), Some([0, 0]));
    /// assert_eq!(x.tiles([1, 1]).count(), 8 * 16);
    ///
    /// let y = Rect::new([0.0, 0.0], [3.141, 2.718]);
    /// assert_eq!(y.tiles([1.0, 1.0]).count(), 3 * 2);
    ///
    /// let z = Rect::new([3, 6], [8, 16]);
    /// assert_eq!(z.tiles([1, 1]).map(|t| t.top).next(), Some([3, 6]));
    /// ```
    pub fn tiles<'a, V: Into<[T; 2]>>(&'a self, dim: V) -> RectIter<'a, T> {
        RectIter::new(self, dim.into())
    }

    /// Get the area of the rectangle.
    pub fn area(&self) -> T {
        self.size[0] * self.size[1]
    }

    /// Produce the smallest new rectangle that contains both input
    /// rectangles.
    pub fn merge(&self, other: &Rect<T>) -> Rect<T> {
        Rect::new([*min(&self.top[0], &other.top[0]),
                   *min(&self.top[1], &other.top[1])],
                  [*max(&(self.top[0] + self.size[0]),
                        &(other.top[0] + other.size[0])),
                   *max(&(self.top[1] + self.size[1]),
                        &(other.top[1] + other.size[1]))])

    }

    /// Return whether this rectangle completely contains another rectangle.
    pub fn contains_rect(&self, other: &Rect<T>) -> bool {
        let p2 = self.point(Anchor::BottomRight);
        let q2 = other.point(Anchor::BottomRight);
        self.contains(other.point(Anchor::TopLeft)) && q2[0] <= p2[0] &&
        q2[1] <= p2[1]
    }
}

impl<T: Copy + Num + PartialOrd> Shape2D<T> for Rect<T> {
    fn bounding_box(&self) -> Rect<T> {
        *self
    }

    fn contains<V: Into<[T; 2]>>(&self, p: V) -> bool {
        let p = p.into();
        p[0] >= self.top[0] && p[1] >= self.top[1] &&
        p[0] < self.top[0] + self.size[0] &&
        p[1] < self.top[1] + self.size[1]
    }
}

/// Iterator for packed left-to-right top-to-bottom subrectangles
pub struct RectIter<'a, T: 'a + Copy> {
    base: &'a Rect<T>,
    dim: [T; 2],
    x: T,
    y: T,
}

impl<'a, T: Num + PartialOrd + Copy + 'a> RectIter<'a, T> {
    fn new(base: &'a Rect<T>, dim: [T; 2]) -> RectIter<T> {
        assert!(dim[0] > Zero::zero() && dim[1] > Zero::zero());
        RectIter {
            base: base,
            dim: dim,
            x: Zero::zero(),
            y: Zero::zero(),
        }
    }
}

impl<'a, T: Num + PartialOrd + Copy> Iterator for RectIter<'a, T> {
    type Item = Rect<T>;

    fn next(&mut self) -> Option<Rect<T>> {
        if self.dim[0] > self.base.size[0] {
            return None;
        }

        if (self.x + One::one()) * self.dim[0] > self.base.size[0] {
            self.y = self.y + One::one();
            self.x = Zero::zero();
        }

        if (self.y + One::one()) * self.dim[1] > self.base.size[1] {
            return None;
        }

        let ret = Rect {
            top: [self.base.top[0] + self.x * self.dim[0],
                  self.base.top[1] + self.y * self.dim[1]],
            size: self.dim,
        };
        self.x = self.x + One::one();
        Some(ret)
    }
}

fn min<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> &'a T {
    if a.lt(b) {
        a
    } else {
        b
    }
}

fn max<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> &'a T {
    if a.gt(b) {
        a
    } else {
        b
    }
}
<commit_msg>Alternative Rect constructor<commit_after>use std::cmp::PartialOrd;
use num::{Num, Signed, Zero, One, abs};
use {Anchor, Shape2D};

/// A rectangle type.
#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Default, Debug, Serialize, Deserialize)]
pub struct Rect<T: Copy> {
    /// Top left (closest to the origin) corner of the rectange.
    pub top: [T; 2],
    /// Size of the rectangle, all elements are assumed to always be positive.
    pub size: [T; 2],
}

impl<T> Rect<T>
    where T: Num + PartialOrd + Signed + Copy
{
    /// Create a new rectangle from two corner points.
    pub fn new<V: Into<[T; 2]>>(p1: V, p2: V) -> Rect<T> {
        let (p1, p2): ([T; 2], [T; 2]) = (p1.into(), p2.into());

        Rect {
            top: [*min(&p1[0], &p2[0]), *min(&p1[1], &p2[1])],
            size: [abs(p2[0] - p1[0]), abs(p2[1] - p1[1])],
        }
    }

    /// Create a new rectangle from top corner and size
    pub fn new_ts<V, U>(top: V, size: U) -> Rect<T>
        where V: Into<[T; 2]>,
              U: Into<[T; 2]>
    {
        let top = top.into();
        let size = size.into();
        assert!(size[0] >= T::zero() && size[1] >= T::zero());

        Rect {
            top: top,
            size: size,
        }
    }

    /// Get a point at an anchor position in the rectangle.
    pub fn point(&self, point: Anchor) -> [T; 2] {
        let one: T = One::one();
        let two = one + one;
        match point {
            Anchor::TopLeft => self.top,
            Anchor::TopRight => [self.top[0] + self.size[0], self.top[1]],
            Anchor::BottomLeft => [self.top[0], self.top[1] + self.size[1]],
            Anchor::BottomRight => {
                [self.top[0] + self.size[0], self.top[1] + self.size[1]]
            }
            Anchor::Top => [self.top[0] + self.size[0] / two, self.top[1]],
            Anchor::Left => [self.top[0], self.top[1] + self.size[1] / two],
            Anchor::Right => {
                [self.top[0] + self.size[0], self.top[1] + self.size[1] / two]
            }
            Anchor::Bottom => {
                [self.top[0] + self.size[0] / two, self.top[1] + self.size[1]]
            }
            Anchor::Center => {
                [self.top[0] + self.size[0] / two,
                 self.top[1] + self.size[1] / two]
            }
        }
    }

    /// Iterate tiles of the given size inside the rectangle.
    ///
    /// The tiles are ordered from left to right, then from top to bottom. The
    /// first tile snaps to the top left corner of the rectangle, and parts
    /// along the right and bottom edges of the rectangle are left uncovered
    /// if a whole tile will not fit in them.
    ///
    /// ```
    /// use calx_layout::Rect;
    ///
    /// let x = Rect::new([0, 0], [8, 16]);
    /// // To iterate integer points in the rectangle, just use [1, 1] tiles.
    /// assert_eq!(x.tiles([1, 1]).map(|t| t.top).next(), Some([0, 0]));
    /// assert_eq!(x.tiles([1, 1]).count(), 8 * 16);
    ///
    /// let y = Rect::new([0.0, 0.0], [3.141, 2.718]);
    /// assert_eq!(y.tiles([1.0, 1.0]).count(), 3 * 2);
    ///
    /// let z = Rect::new([3, 6], [8, 16]);
    /// assert_eq!(z.tiles([1, 1]).map(|t| t.top).next(), Some([3, 6]));
    /// ```
    pub fn tiles<'a, V: Into<[T; 2]>>(&'a self, dim: V) -> RectIter<'a, T> {
        RectIter::new(self, dim.into())
    }

    /// Get the area of the rectangle.
    pub fn area(&self) -> T {
        self.size[0] * self.size[1]
    }

    /// Produce the smallest new rectangle that contains both input
    /// rectangles.
    pub fn merge(&self, other: &Rect<T>) -> Rect<T> {
        Rect::new([*min(&self.top[0], &other.top[0]),
                   *min(&self.top[1], &other.top[1])],
                  [*max(&(self.top[0] + self.size[0]),
                        &(other.top[0] + other.size[0])),
                   *max(&(self.top[1] + self.size[1]),
                        &(other.top[1] + other.size[1]))])

    }

    /// Return whether this rectangle completely contains another rectangle.
    pub fn contains_rect(&self, other: &Rect<T>) -> bool {
        let p2 = self.point(Anchor::BottomRight);
        let q2 = other.point(Anchor::BottomRight);
        self.contains(other.point(Anchor::TopLeft)) && q2[0] <= p2[0] &&
        q2[1] <= p2[1]
    }
}

impl<T: Copy + Num + PartialOrd> Shape2D<T> for Rect<T> {
    fn bounding_box(&self) -> Rect<T> {
        *self
    }

    fn contains<V: Into<[T; 2]>>(&self, p: V) -> bool {
        let p = p.into();
        p[0] >= self.top[0] && p[1] >= self.top[1] &&
        p[0] < self.top[0] + self.size[0] &&
        p[1] < self.top[1] + self.size[1]
    }
}

/// Iterator for packed left-to-right top-to-bottom subrectangles
pub struct RectIter<'a, T: 'a + Copy> {
    base: &'a Rect<T>,
    dim: [T; 2],
    x: T,
    y: T,
}

impl<'a, T: Num + PartialOrd + Copy + 'a> RectIter<'a, T> {
    fn new(base: &'a Rect<T>, dim: [T; 2]) -> RectIter<T> {
        assert!(dim[0] > Zero::zero() && dim[1] > Zero::zero());
        RectIter {
            base: base,
            dim: dim,
            x: Zero::zero(),
            y: Zero::zero(),
        }
    }
}

impl<'a, T: Num + PartialOrd + Copy> Iterator for RectIter<'a, T> {
    type Item = Rect<T>;

    fn next(&mut self) -> Option<Rect<T>> {
        if self.dim[0] > self.base.size[0] {
            return None;
        }

        if (self.x + One::one()) * self.dim[0] > self.base.size[0] {
            self.y = self.y + One::one();
            self.x = Zero::zero();
        }

        if (self.y + One::one()) * self.dim[1] > self.base.size[1] {
            return None;
        }

        let ret = Rect {
            top: [self.base.top[0] + self.x * self.dim[0],
                  self.base.top[1] + self.y * self.dim[1]],
            size: self.dim,
        };
        self.x = self.x + One::one();
        Some(ret)
    }
}

fn min<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> &'a T {
    if a.lt(b) {
        a
    } else {
        b
    }
}

fn max<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> &'a T {
    if a.gt(b) {
        a
    } else {
        b
    }
}
<|endoftext|>


<commit_before>extern crate xdg_basedir;
use error::FsError;

use std::fs::create_dir_all;
use std::path::PathBuf;

pub fn dir_config_create(name: &str) -> Result<PathBuf, FsError> {
    let path: PathBuf = try!(dir_config(name));
    try!(create_dir_all(path.as_path()));
    Ok(path)
}

pub fn dir_config(name: &str) -> Result<PathBuf, FsError> {
    let mut path: PathBuf = try!(xdg_basedir::get_config_home());
    path.push(name);
    Ok(path)
}

pub fn dir_data_create(name: &str) -> Result<PathBuf, FsError> {
    let path: PathBuf = try!(dir_data(name));
    try!(create_dir_all(path.as_path()));
    Ok(path)
}

pub fn dir_data(name: &str) -> Result<PathBuf, FsError> {
    let mut path: PathBuf = try!(xdg_basedir::get_data_home());
    path.push(name);
    Ok(path)
}
<commit_msg>dirs: reorder use statements<commit_after>use error::FsError;

extern crate xdg_basedir;

use std::fs::create_dir_all;
use std::path::PathBuf;

pub fn dir_config_create(name: &str) -> Result<PathBuf, FsError> {
    let path: PathBuf = try!(dir_config(name));
    try!(create_dir_all(path.as_path()));
    Ok(path)
}

pub fn dir_config(name: &str) -> Result<PathBuf, FsError> {
    let mut path: PathBuf = try!(xdg_basedir::get_config_home());
    path.push(name);
    Ok(path)
}

pub fn dir_data_create(name: &str) -> Result<PathBuf, FsError> {
    let path: PathBuf = try!(dir_data(name));
    try!(create_dir_all(path.as_path()));
    Ok(path)
}

pub fn dir_data(name: &str) -> Result<PathBuf, FsError> {
    let mut path: PathBuf = try!(xdg_basedir::get_data_home());
    path.push(name);
    Ok(path)
}
<|endoftext|>